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

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

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

books

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

# the deb is an ar format, you can use standard ar/tar tools to extract to local ./usr/lib/erlang/

# or to extract the rpm, it is cpio format:

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.



_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How about make the erl to be relocatable ? for multiple erlang versions installed on a same host

Michael Truog
What I find useful to handle multiple Erlang versions, is to move the installation directory in lib to separate name, and use a symbolic link when switching between versions.  The installation is has been setup for awhile in a way where this doesn't break, which is nice.  So, PREFIX=="/usr/local" if installing from source, but whatever it is:
cd PREFIX/lib/
mv erlang erlang_VERSION
ln -s erlang_VERSION erlang

In the future, to switch versions, you only need to change the symbolic link target.

I don't see a good reason to change the erl executable to handle testing separate versions, because your concerns seem focused on troubles dealing with packages.  That would likely be an issue with packages, where the package manager wants to enforce having 1 version of something.  If the packages were built to have the version number in the path, then the problem could be avoided (and the solution is similar to the info above), but it would remain a package problem.

On 06/05/2017 07:38 PM, derek wrote:

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

# the deb is an ar format, you can use standard ar/tar tools to extract to local ./usr/lib/erlang/

# or to extract the rpm, it is cpio format:

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.




_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How about make the erl to be relocatable ? for multiple erlang versions installed on a same host

Attila Rajmund Nohl
In reply to this post by books
Hello!

I'm not sure if I totally understand your problem, but I see two solutions:
1, use kerl (https://github.com/kerl/kerl) to manage your
installations. Download, build and install all required Erlang
versions, then simply activate the one you need to use.
2, create a Docker image for each required Erlang version and install
your software inside that image (possibly using bind mount).

2017-06-06 4:38 GMT+02:00 derek <[hidden email]>:

>
> 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.
>
>
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions
>
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions