[erlang-questions] How about make the erl to be relocatable ? for multiple erlang versions installed on a same host

derek denc716@REDACTED
Tue Jun 6 04:38:11 CEST 2017


the default erl is a shell script, like this:

#!/bin/sh
[...]
# %CopyrightEnd%
#
ROOTDIR="/usr/lib/erlang"
...


Where the ROOTDIR is set to a hard code string at installation time, and it
makes the erl script not relocatable,

sometimes we want to install multiple erlang versions for testing features,
like this following is my way to test install esl packaged erlang-20.0-rc2,
all just extract "install" to my $HOME/opt/... without sysadmin permission:

# download the deb or rpm package
$ wget -P ./Downloads -m
https://packages.erlang-solutions.com/erlang/esl-erlang/FLAVOUR_1_general/esl-erlang_20.0-rc2-1~debian~jessie_amd64.deb

# the deb is an ar format, you can use standard ar/tar tools to extract to
local ./usr/lib/erlang/
$ ar p ./Downloads/
packages.erlang-solutions.com/erlang/esl-erlang/FLAVOUR_1_general/esl-erlang_20.0-rc2-1~debian~jessie_amd64.deb
data.tar.xz | tar --xz -xvv ./usr/lib/erlang/

# or to extract the rpm, it is cpio format:
# rpm2cpio ./Downloads/
packages.erlang-solutions.com/erlang/esl-erlang/FLAVOUR_1_general/esl-erlang_20.0-rc2-1~centos~6_amd64.rpm
| cpio -vid './usr/lib/erlang/*'

Once I get ./usr/lib/erlang/ I usually renamed to ./opt/ ...

$ mv -v ./usr/lib/erlang/ ./opt/esl-erlang_20.0-rc2-1~debian~jessie

Then a problem is this erl doesn't run, because it tries to access the hard
coded ROOTDIR from /usr/lib/erlang (does not exist)

(the "bash -xe" is only to show how does the shell script run, but not
necessary)

$ bash -xe ./opt/esl-erlang_20.0-rc2-1~debian~jessie/bin/erl
+ ROOTDIR=/usr/lib/erlang
+ BINDIR=/usr/lib/erlang/erts-9.0/bin
+ EMU=beam
++ echo ./opt/esl-erlang_20.0-rc2-1~debian~jessie/bin/erl
++ sed 's/.*\///'
+ PROGNAME=erl
+ export EMU
+ export ROOTDIR
+ export BINDIR
+ export PROGNAME
+ exec /usr/lib/erlang/erts-9.0/bin/erlexec
./opt/esl-erlang_20.0-rc2-1~debian~jessie/bin/erl: line 29:
/usr/lib/erlang/erts-9.0/bin/erlexec: No such file or directory

So I back it up and make little changes to make it read path from where
it's installed:

$ \cp -va ./opt/esl-erlang_20.0-rc2-1~debian~jessie/bin/erl{,.orig}
`./opt/esl-erlang_20.0-rc2-1~debian~jessie/bin/erl' ->
`./opt/esl-erlang_20.0-rc2-1~debian~jessie/bin/erl.orig'

$ vim ./opt/esl-erlang_20.0-rc2-1~debian~jessie/bin/erl

Diff is here:

$ diff -u ./opt/esl-erlang_20.0-rc2-1~debian~jessie/bin/erl{.orig,}
--- ./opt/esl-erlang_20.0-rc2-1~debian~jessie/bin/erl.orig 2017-06-06
01:57:50.796140791 +0000
+++ ./opt/esl-erlang_20.0-rc2-1~debian~jessie/bin/erl 2017-06-06
01:59:15.713988348 +0000
@@ -18,10 +18,12 @@
 #
 # %CopyrightEnd%
 #
-ROOTDIR="/usr/lib/erlang"
+# ROOTDIR="/usr/lib/erlang"
+ROOTDIR="$(readlink -f ${0%/*}/..)"
 BINDIR=$ROOTDIR/erts-9.0/bin
 EMU=beam
-PROGNAME=`echo $0 | sed 's/.*\///'`
+# PROGNAME=`echo $0 | sed 's/.*\///'`
+PROGNAME="${0##*/}"
 export EMU
 export ROOTDIR
 export BINDIR

Then it runs:

$ bash -xe ./opt/esl-erlang_20.0-rc2-1~debian~jessie/bin/erl
++ readlink -f ./opt/esl-erlang_20.0-rc2-1~debian~jessie/bin/..
+ ROOTDIR=/home/username/opt/esl-erlang_20.0-rc2-1~debian~jessie
+ BINDIR=/home/username/opt/esl-erlang_20.0-rc2-1~debian~jessie/erts-9.0/bin
+ EMU=beam
+ PROGNAME=erl
+ export EMU
+ export ROOTDIR
+ export BINDIR
+ export PROGNAME
+ exec
/home/username/opt/esl-erlang_20.0-rc2-1~debian~jessie/erts-9.0/bin/erlexec
Erlang/OTP 20 [RELEASE CANDIDATE 2] [erts-9.0] [source] [64-bit]
[smp:24:24] [ds:24:24:10] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V9.0  (abort with ^G)
1>

I am aware of there is a "Install" script can be used to install itself to
another location, but the problem remains: it's still hard coded of new
install path:
./opt/esl-erlang_20.0-rc2-1~debian~jessie/Install


The problem need to be solved, especially when used with docker's bind
mount feature, it can be mounted to a complete different path, I hope the
erl can still run without any change:

Here it shows my changed erl escript can still run when bind mounted to the
container's "/opt/esl-erlang_20.0-rc2-1~debian~jessie"

$ docker run -it --rm -v $PWD/opt:/opt:ro ubuntu bash -xe
/opt/esl-erlang_20.0-rc2-1~debian~jessie/bin/erl
++ readlink -f /opt/esl-erlang_20.0-rc2-1~debian~jessie/bin/..
+ ROOTDIR=/opt/esl-erlang_20.0-rc2-1~debian~jessie
+ BINDIR=/opt/esl-erlang_20.0-rc2-1~debian~jessie/erts-9.0/bin
+ EMU=beam
+ PROGNAME=erl
+ export EMU
+ export ROOTDIR
+ export BINDIR
+ export PROGNAME
+ exec /opt/esl-erlang_20.0-rc2-1~debian~jessie/erts-9.0/bin/erlexec
Erlang/OTP 20 [RELEASE CANDIDATE 2] [erts-9.0] [source] [64-bit]
[smp:24:24] [ds:24:24:10] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V9.0  (abort with ^G)
1>
User switch command
 --> q

Or add to PATH:

$ docker run -it --rm -v $PWD/opt:/opt:ro -e
PATH=/opt/esl-erlang_20.0-rc2-1~debian~jessie/bin:$PATH -e LANG=C.UTF-8
ubuntu erl +pc unicode
Erlang/OTP 20 [RELEASE CANDIDATE 2] [erts-9.0] [source] [64-bit]
[smp:24:24] [ds:24:24:10] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V9.0  (abort with ^G)
1> io:format("~tp~n", [{'hello_юникод_世界', <<"Hello, 世界; юникод"/utf8>>,
"Hello, 世界; юникод"}]).
{'hello_юникод_世界',<<"Hello, 世界; юникод"/utf8>>,"Hello, 世界; юникод"}
ok
2>
User switch command
 --> q


Hopefully this entertains; I can make a PR to  https://github.com/erlang/otp
if somebody like.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20170605/d26e0526/attachment.htm>


More information about the erlang-questions mailing list