Running erlang shell as a daemon/service

2019-04-10 02:15发布

问题:

I have an Erlang program that runs in Erlang shell, obviously, and I want to monitor it.

This is what I want:

  • When the machine starts the Erlang shell should start up with it, and the program that runs in the shell too.
  • If the Erlang shell crashes for some reason it should get restarted.
  • You should be able to manually start/stop/restart the Erlang shell.

Example:

/etc/init.d/foobar start
/etc/init.d/foobar stop
/etc/init.d/foobar restart

I haven't started with the whole "restart itself if crash" thing yet, got stuck with the easy thing, or is it easy?

What I have done is this:

Taken the skeleton code from /etc/init.d/skeleton and replaced the PATH, DESC, NAME etc etc... This works, I can do:

/etc/init.d/foobar start

However, I cant stop it... The thing is that I start the Erlang shell with "erl" which is a script that does some fancy things that I dont understand. One thing it does is, it creates a very long and complex process name. It's not just "erl" it's like:

/usr/lib/erlang/erts-5.7.4/bin/beam.smp -- -root /usr/lib/erlang -progname erl -- -home /home/xxx -- .... and some more.

Is there a better way to do this?

OS: Ubuntu 11.04

回答1:

In addition to creating a target release, a standard Erlang production environment as recommended by @Martin, you need the following:

  • To allow for automatic restart of a crashed node, you should use the heart functionality.

  • To stop a running Erlang node, you could start up a temporary Erlang node, connect to the running node and issue a stop command:

    erl -noshell -sname temp_control \
        -eval "rpc:call(mynode@myhost, init, stop, [])" \
        -s init stop
    
    • noshell disables input and shell output
    • sname sets the name for the temporary node
    • eval let's you execute any valid Erlang expression
      • rpc:call(Node, M, F, A) will call M:F(A) on the node specified (A is list of arguments that will be passed to the function as real arguments)
    • s M F runs the function M:F()

    (eval and s are run in sequence)



回答2:

What you want to do is create a target-system. The documentation for doing so is here: http://www.erlang.org/doc/system_principles/create_target.html However, it is a bit complicated at first, until you get the basic concepts.

Roughly speaking, you do the following:

  1. Create an empty node. That is, the 'bin, erts and releases' directories (with updated scripts in bin).
  2. Create a release via release_tools as described in the dox.
  3. Unpack the release on the empty node, set the release/start_erl.data to point to the new release and erts versions.

This can then be managed as a service with restarts/monitors and whatever you like to add.



回答3:

The recently released erld project is an excellent way of truly daemonising an Erlang application. It provides support for all things a daemon should do, namely:

  • Can be started/stopped from an init script
  • On startup, control does not return to the console until the program has successfully started (or failed to do so).
  • Startup diagnostic information can be printed to the console to indicate progress, but output ceases once the daemon is running.
  • On returning to the console, the return code indicates success (0) or failure (some other number).
  • Log rotation can be triggered by sending a SIGHUP

See their github page here: https://github.com/ShoreTel-Inc/erld