简体   繁体   中英

Installing more than one version of Erlang/OTP on a machine

是否可以在同一平台上同时安装不同版本的 Erlang/OTP?

I use Kerl to install Erlang on my machines. Quite easy to use, and allows to have several Erlang systems installed on same machine. You can then easily choose the one you want to use.

Yes, I usually install different versions in my home directory. I build them from source:

./configure --prefix=$HOME/r15b01
make && make install

Then I can choose a version to use with PATH=$HOME/r15b01/bin:$PATH , and compile and run things as usual.


These days I use asdf for this. Install asdf and add the relevant line to your .bashrc , and then run:

asdf plugin add erlang
asdf install erlang 22.3.3
asdf install erlang 23.0.2

Then you can set one of the Erlang versions you just built as the default version:

asdf global erlang 23.0.2

Or you can set it to be used in the current directory and its subdirectories - this will create a .tool-versions file in the current directory:

asdf local erlang 22.3.3

It is no only possible, but also very frequent. On my machine I have one version that I installed for development (R13B03) it is the default version when I launch erl. A second copy of the same version associated with nitrogen. this copy is used when I start my nitrogen website. The version will not change when I will use the R16B.. for development A partial older version which came with the installation of Wings3D.

I believe this blog post could be very useful:

How to manage multiple Erlang installations

On a Mac, Macport helps switching, even between versions it covers and newer ones.

Eg with Erlang 17 installed directly from Erlang Solutions, you could switch back to RB1603 (open a new terminal window afterwards):

sudo port activate erlang @R16B03-1_0+hipe+ssl

Switch back to Erlang 17 by _de_activating the Macports install (and open a new terminal window afterwards):

sudo port deactivate erlang @R16B03-1_0+hipe+ssl

List all versions you have installed with:

port installed erlang

Using the Nix package manager there is no need to globally install interpreters (especially because sometimes multiple versions are needed), and nix-shell will open up a sub-shell with the Erlang executable available in the path.

1. Getting only the Erlang (no shell.nix )

For the current version in the active channel:

nix-shell -p erlang

For other versions not in the current channel, a specific channel can be given:

nix-shell -I nixpkgs=channel:nixos-unstable -p erlangR22

Or add path to the Nix expression in your NixOS/nixpkgs clone:

$ nix-shell -I nixpkgs=~/clones/nixpkgs -p erlangR23

2. More elaborate project setup configurations: use a shell.nix file

A complex development environment can be spun up, and calling nix-shell shell.nix will take care of all - even automatically when entering a directory if set up with direnv ( archived ).

2.1 Examples

Erlang

This will drop you in a shell with erl and rebar3 available, along with the other programs specified in buildInputs .

####################################################################
# Importing a cloned Nixpkgs repo  (from my home directory), because
# the latest channels don't have Elixir 1.9.
# See https://nixos.org/nix/manual/#idm140737317975776 for the meaning
# of `<nixpkgs>` and `~` in Nix expressions (towards the end of that
# section).
####################################################################

{ pkgs ? import ~/clones/nixpkgs {} }:

pkgs.mkShell {

  buildInputs = with pkgs; [
    beam.packages.erlangR22.elixir_1_9
    postgresql_11
    nodejs-12_x
    git
    inotify-tools
  ];

  shellHook = ''

    ####################################################################
    # Create a diretory for the generated artifacts
    ####################################################################

    mkdir .nix-shell
    export NIX_SHELL_DIR=$PWD/.nix-shell

    ####################################################################
    # Put the PostgreSQL databases in the project diretory.
    ####################################################################

    export PGDATA=$NIX_SHELL_DIR/db

    ####################################################################
    # Put any Mix-related data in the project directory
    ####################################################################

    export MIX_HOME="$NIX_SHELL_DIR/.mix"
    export MIX_ARCHIVES="$MIX_HOME/archives"

    ####################################################################
    # Clean up after exiting the Nix shell using `trap`.
    # ------------------------------------------------------------------
    # Idea taken from
    # https://unix.stackexchange.com/questions/464106/killing-background-processes-started-in-nix-shell
    # and the answer provides a way more sophisticated solution.
    #
    # The main syntax is `trap ARG SIGNAL` where ARG are the commands to
    # be executed when SIGNAL crops up. See `trap --help` for more.
    ####################################################################

    trap \
      "
        ######################################################
        # Stop PostgreSQL
        ######################################################

        pg_ctl -D $PGDATA stop

        ######################################################
        # Delete `.nix-shell` directory
        # ----------------------------------
        # The first  step is going  back to the  project root,
        # otherwise `.nix-shell`  won't get deleted.  At least
        # it didn't for me when exiting in a subdirectory.
        ######################################################

        cd $PWD
        rm -rf $NIX_SHELL_DIR
      " \
      EXIT

    ####################################################################
    # If database is  not initialized (i.e., $PGDATA  directory does not
    # exist), then set  it up. Seems superfulous given  the cleanup step
    # above, but handy when one gets to force reboot the iron.
    ####################################################################

    if ! test -d $PGDATA
    then

      ######################################################
      # Init PostgreSQL
      ######################################################

      pg_ctl initdb -D  $PGDATA

      ######################################################
      # PORT ALREADY IN USE
      ######################################################
      # If another `nix-shell` is  running with a PostgreSQL
      # instance,  the logs  will show  complaints that  the
      # default port 5432  is already in use.  Edit the line
      # below with  a different  port number,  uncomment it,
      # and try again.
      ######################################################

      # sed -i "s|^#port.*$|port = 5433|" $PGDATA/postgresql.conf

    fi

    ####################################################################
    # Start PostgreSQL
    # ==================================================================
    # Setting all  necessary configuration  options via  `pg_ctl` (which
    # is  basically  a wrapper  around  `postgres`)  instead of  editing
    # `postgresql.conf` directly with `sed`. See docs:
    #
    # + https://www.postgresql.org/docs/current/app-pg-ctl.html
    # + https://www.postgresql.org/docs/current/app-postgres.html
    #
    # See more on the caveats at
    # https://discourse.nixos.org/t/how-to-configure-postgresql-declaratively-nixos-and-non-nixos/4063/1
    # but recapping out of paranoia:
    #
    # > use `SHOW`  commands to  check the  options because  `postgres -C`
    # > "_returns values  from postgresql.conf_" (which is  not changed by
    # > supplying  the  configuration options  on  the  command line)  and
    # > "_it does  not reflect  parameters supplied  when the  cluster was
    # > started._"
    #
    # OPTION SUMMARY
    # --------------------------------------------------------------------
    #
    #  + `unix_socket_directories`
    #
    #    > PostgreSQL  will  attempt  to create  a  pidfile  in
    #    > `/run/postgresql` by default, but it will fail as it
    #    > doesn't exist. By  changing the configuration option
    #    > below, it will get created in $PGDATA.
    #
    #   + `listen_addresses`
    #
    #     > In   tandem  with   edits   in  `pg_hba.conf`   (see
    #     > `HOST_COMMON`  below), it  configures PostgreSQL  to
    #     > allow remote connections (otherwise only `localhost`
    #     > will get  authenticated and the rest  of the traffic
    #     > discarded).
    #     >
    #     > NOTE: the  edit  to  `pga_hba.conf`  needs  to  come
    #     >       **before**  `pg_ctl  start`  (or  the  service
    #     >       needs to be restarted otherwise), because then
    #     >       the changes are not being reloaded.
    #     >
    #     > More info  on setting up and  troubleshooting remote
    #     > PosgreSQL connections (these are  all mirrors of the
    #     > same text; again, paranoia):
    #     >
    #     >   + https://stackoverflow.com/questions/24504680/connect-to-postgres-server-on-google-compute-engine
    #     >   + https://stackoverflow.com/questions/47794979/connecting-to-postgres-server-on-google-compute-engine
    #     >   + https://medium.com/scientific-breakthrough-of-the-afternoon/configure-postgresql-to-allow-remote-connections-af5a1a392a38
    #     >   + https://gist.github.com/toraritte/f8c7fe001365c50294adfe8509080201#file-configure-postgres-to-allow-remote-connection-md

    HOST_COMMON="host\s\+all\s\+all"
    sed -i "s|^$HOST_COMMON.*127.*$|host all all 0.0.0.0/0 trust|" $PGDATA/pg_hba.conf
    sed -i "s|^$HOST_COMMON.*::1.*$|host all all ::/0 trust|"      $PGDATA/pg_hba.conf

     #  + `log*`
     #
     #    > Setting up basic logging,  to see remote connections
     #    > for example.
     #    >
     #    > See the docs for more:
     #    > https://www.postgresql.org/docs/current/runtime-config-logging.html

    pg_ctl                                                  \
      -D $PGDATA                                            \
      -l $PGDATA/postgres.log                               \
      -o "-c unix_socket_directories='$PGDATA'"             \
      -o "-c listen_addresses='*'"                          \
      -o "-c log_destination='stderr'"                      \
      -o "-c logging_collector=on"                          \
      -o "-c log_directory='log'"                           \
      -o "-c log_filename='postgresql-%Y-%m-%d_%H%M%S.log'" \
      -o "-c log_min_messages=info"                         \
      -o "-c log_min_error_statement=info"                  \
      -o "-c log_connections=on"                            \
      start

    ####################################################################
    # Install Node.js dependencies if not done yet.
    ####################################################################

    if test -d "$PWD/assets/" && ! test -d "$PWD/assets/node_modules/"
    then
      (cd assets && npm install)
    fi

    ####################################################################
    # If $MIX_HOME doesn't exist, set it up.
    ####################################################################

    if ! test -d $MIX_HOME
    then

      ######################################################
      # ...  but first,  test whether  there is  a `_backup`
      # directory. Had issues with  installing Hex on NixOS,
      # and Hex and  Phoenix can be copied  from there, just
      # in case.
      ######################################################

      if test -d "$PWD/_backup"
      then
        cp -r _backup/.mix .nix-shell/
      else
        ######################################################
        # Install Hex and Phoenix via the network
        ######################################################

        yes | mix local.hex
        yes | mix archive.install hex phx_new
      fi
    fi

    if test -f "mix.exs"
    then
      # These are not in the  `if` section above, because of
      # the `hex` install glitch, it  could be that there is
      # already a `$MIX_HOME` folder. See 2019-08-05_0553

      mix deps.get

      ######################################################
      # `ecto.setup` is defined in `mix.exs` by default when
      # Phoenix  project  is  generated via  `mix  phx.new`.
      # It  does  `ecto.create`,   `ecto.migrate`,  and  run
      # `priv/seeds`.
      ######################################################
      mix ecto.setup
    fi
  '';

  ####################################################################
  # Without  this, almost  everything  fails with  locale issues  when
  # using `nix-shell --pure` (at least on NixOS).
  # See
  # + https://github.com/NixOS/nix/issues/318#issuecomment-52986702
  # + http://lists.linuxfromscratch.org/pipermail/lfs-support/2004-June/023900.html
  ####################################################################

  LOCALE_ARCHIVE = if pkgs.stdenv.isLinux then "${pkgs.glibcLocales}/lib/locale/locale-archive" else "";
}
Elixir/Phoenix web project

This ( archived ) will set up an environment for an Elixir/Phoenix web app complete with a spun up PostgreSQL dev instance:

$ nix-env -f ~/clones/nixpkgs/ -qaP 'erlang*'
# ...
nixos.erlangR20            erlang-20.3.8.9
nixos.erlangR21            erlang-21.3.8.3
nixos.erlang               erlang-22.1.7
# ...
=== >>> erlangR23            erlang-23.0.2  <<<====

How to find packages with attributes path on the console

$ nix-env -qaP 'erlang*' # ... nixos.erlangR20 erlang-20.3.8.9 nixos.erlangR21 erlang-21.3.8.3 nixos.erlang erlang-22.1.7 # ...
 $ nix-env -f ~/clones/nixpkgs/ -qaP 'erlang*' # ... nixos.erlangR20 erlang-20.3.8.9 nixos.erlangR21 erlang-21.3.8.3 nixos.erlang erlang-22.1.7 # ... === >>> erlangR23 erlang-23.0.2 <<<====

Consider using kerl. It allows you to work with several Erlang installations https://github.com/kerl/kerl

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM