Erlang heartbeats - erlang

I am trying to create an application that can run on two different machines on the same network, and when one of the applications crahes, I want to use erlang heartbeat system to make it restart. How can I do this?
I've read the documentation, but have not figured out how to achieve this in practice.
Thanks

Did you specifically read http://erlang.org/doc/man/heart.html and try to follow the instructions there? In particular, you have to first set the environment variable HEART_COMMAND to the full command line to be used to restart your system.
To make this easier, you could use a launch script like this:
#!/bin/sh
erl -detached -heart -env HEART_COMMAND "$0 $#" -env HEART_BEAT_TIMEOUT 20 -sname mynode
In some environments (such as embedded systems) you might prefer a full OS reboot, and could simply run something like this:
#!/bin/sh
erl -detached -heart -env HEART_COMMAND "reboot" -env HEART_BEAT_TIMEOUT 20 -sname mynode

Related

How can I add setcookie into ejabberdctl to run the ejabberd service or connect two node on different machine without setcookie in startup?

I am new the Erlang. Currently, we are using ejabberd for our xmpp service.
Recently, dues to some capability issue, I have written a distributed erlange program. I need to run rpc:call between two machines. I can do the rpc:call successfully on erl simulator. But our current system was using ejabberdctl to start the ejabberd service. I have check and try to modify the ejabberdctl file. But I can't add -setcookie successfully.
the code section in ejabberdctl is
ctlexec()
{
CONN_NAME=$1; shift
COMMAND=$#
$EXEC_CMD "$ERL \
$NAME ${CONN_NAME} \
-noinput \
-hidden \
-pa $EJABBERD_EBIN_PATH \
$KERNEL_OPTS \
-s ejabberd_ctl -extra $ERLANG_NODE $COMMAND"
}
the problem caused by the last two line:
$KERNEL_OPTS \
-s ejabberd_ctl -extra $ERLANG_NODE $COMMAND"
I think this file is referenced some one's before, but I don't know where are there from.
Does anybody know how can I add -setcookie abc to this erl command?
If I can't change the ejabberdctl file or the worse case, I can't change the current system.
i.e. I don't have a chance to add setcookie to the ejabberd system.
How can I connect my new node to the existing ejabberd node(our current system).
The ejabberd suppose to start first.
You have a solution right under your nose. How ctlexec() works? It runs --hidden node named $NAME ${CONN_NAME}, sets options $KERNEL_OPTS, inserts $EJABBERD_EBIN_PATH into search path and calls ejabberd_ctl:start() with some additional parameters in $ERLANG_NODE $COMMAND. So there must be -setcookie Cookie parameter in $KERNEL_OPTS or it uses default cookie in $HOME/.erlang.cookie. It is exactly what you need. Just replace -s ejabberd_ctl with your own module and use $KERNEL_OPTS and $ERLANG_NODE content which you already have. Search around in the script for clues what $KERNEL_OPTS and $ERLANG_NODE contains.
It is a usual way how scripts like ejabberd_ctl are made. It is pretty simple and elegant. You just run your own node set it --hidden so you don't disturb other nodes in a cluster if there is such. Don't forget set some random node name. Connect to the application node and then do your rpc:call/4,5 and that's it. There is usually some modules like ejabberd_ctl.erl to make it more comfortable, process extra parameters and so on.

How to ban ban ctrl+c in erlang

I use run_erl to start an erlang application, just like this
run_erl -daemon /tmp/erl_pipe /tmp/erl_log "erl -name 1#127.0.0.1 -setcookie 123456"
Then I Attach to erlang shell like this
to_erl /tmp/erl_pipe
And the question is, I used to quit erlang shell with 'ctrl + c', in this situation, 'ctrl+c' will quit the main node, I have seen my lead to ban this command by modify erlang/OTP source code, how to do that?
Start Erlang as erl +Bi. Note that you'll have to use init:stop() (shortcut q() in the shell) or halt() to stop the node if signals are ignored. Also, the Ctrl-G menu will not have the q option if you use this flag.
It is also possible to use +Bc, which makes Ctrl-C abort the current shell command instead of stopping the whole node. In this case, you can still use q from the Ctrl-G menu.
See http://erlang.org/doc/man/erl.html#emu_flags for the full documentation on runtime system flags.

How to run Erlang nodes?

How to create new node? i try some like here
how to run this erlang example
and find the same in tutorial
http://www.erlang.org/doc/reference_manual/distributed.html when i write
% erl -name dilbert
my compiler behaves i forgot '.' at the end. Of course i try end, result the same.
Any ideas?
The command erl -name dilbert is not meant to be typed into the Erlang shell; it's the command you run to start a distributed node instead of plain erl.
(If you really want to turn a running node into a distributed node, you can use net_kernel:start/1, but I've never had a reason to do that except in tests.)
In Linux, you can type erl -name dilbert in the terminal.
In Windows you run it in CMD.

script to start erlang code

I am trying to build a script on ubuntu to start some Erlang code of mine:
the script is something like:
#!/bin/sh
EBIN=$HOME/path_to_beams
ERL=/usr/local/bin/erl
export HEART_COMMAND="$EBIN/starting_script start"
case $1 in
start)
$ERL -sname mynode -pa $EBIN \
-heart -detached -s my_module start_link
;;
*)
echo "Usage: $0 {start|stop|debug}"
exit 1
esac
exit 0
but I'm having a couple of problems.
First of all, the code can be executed only if the script is in the same directory as the beams, this seems strange to me, I double checked the paths, so why doesn't the -pa flag work?
Second, the script (without the -pa) works fine, but if I try to start instead of the main module (a gen_server) its supervisor (-s my_module_sup start_link) it doesn't work...this is strange, because if I start the supervisor from a normal shell everything works fine.
Third, the -heart flag, should restart the script in case of failure, but if I kill the process with a normal Unix kill, the process is not restarted.
Can someone give me some hints?
Thanks in advance,
pdn
The first thing that comes to mind is that you're using erlexport instead of erl. Not sure why you're doing this (I've not heard of erlexport before). Try it with erl instead.
Your -heart flag won't have meaning if the Erlang node itself is killed because the process can't keep itself alive. You would need another process running that monitors the Erlang process and restarts it if killed.

How to run Erlang from unix shell with complex params?

I need to run complex Erlang module function from unix shell
rpc:call('node#example.com', mnesia, dirty_first, [mytable])
how can i do it?
UPD:
i make test.escript
chmod +x test.escript
#!/usr/lib64/erlang/bin/escript
%%! -name 'test#example.com'
main(_Args) ->
R = rpc:call('node#example.com', mnesia, dirty_first, [mytable]),
io:format("~p~n",[R]).
and receive {badrpc, nodedown}
but when run
erl -name test#example.com
1> rpc:call('node#example.com', mnesia, dirty_first, [mytable]).
{my, data}.
I mean it works, but howto make escript work proprely?
I think escript might be something worth looking into.
Edit:
Some examples.
First for all examples: Start the remote node somewhere, somehow.
dannib#duval:~:> erl -sname bar
(bar#duval)1> erlang:get_cookie().
'KNKKCFPYMJUPIOLYPOAA'
Escript
1: Create a file named hello.escript with content
#!/usr/bin/env escript
%%! -sname foo#duval -setcookie KNKKCFPYMJUPIOLYPOAA
main(_String) ->
Node = 'bar#duval',
Mod = 'erlang',
Fun = 'node',
Args = [],
R = rpc:call(Node, Mod, Fun, Args),
io:format("Hello there ~p~n",[R]).
Notice that the %%! -sname foo#bar identifies the node on the host (instead of creating nonode#nohost), allow setting the same cookie %%! -sname foo#duvel -setcookie KNKKCFPYMJUPIOLYPOAA as target host which solves the problem of getting {badrpc,nodedown}. Notice that the same statement holds for the following examples (erl_call, and -eval) where both the node name and cookie is set.
2: Set the execution bit and run
$ chmod +x hello.escript
$ ./hello.escript
Hello there bar#duval
Erl_call
1: run
$ erl_call -c 'KNKKCFPYMJUPIOLYPOAA' -a 'erlang node' -n bar#duval
bar#duval
Eval
1: run
$ erl -sname foo -setcookie 'KNKKCFPYMJUPIOLYPOAA'
-eval 'io:format("Hello there ~p~n",[rpc:call(bar#duval,erlang, node, [])])'
... Eshell V5.7.4 (abort with ^G)
(foo#duval)1> Hello there bar#duval
This creates a shell which might not be what you want in this case.
I might mention that if both nodes are on the same host and using the same cookie default value, the cookie value for foo and bar don't have to be explicitly set like in the examples.
After doing these examples and reading your question again I think what I GIVE TERRIBLE ADVICE said will be your best choice, erl_call. I fell for the word "complex" in question title where imho escripts allow much more "complex" setups in a easy-to-read manner. The variable _String in the escript example holds the arguments to the script which allows you to both access input through shell and perform complex erlang operations in the EVM. But erl_call might be more straight forward if you already have logic in some other application and just need to make this simple call to an erlang node.
The erl_call application is exactly what you need:
erl_call makes it possible to start and/or communicate with a distributed Erlang node. It is built upon the erl_interface library as an example application. Its purpose is to use an Unix shell script to interact with a distributed Erlang node. It performs all communication with the Erlang rex server, using the standard Erlang RPC facility. It does not require any special software to be run at the Erlang target node.
The main use is to either start a distributed Erlang node or to make an ordinary function call. However, it is also possible to pipe an Erlang module to erl_call and have it compiled, or to pipe a sequence of Erlang expressions to be evaluated (similar to the Erlang shell).
See the examples for more details
You can use -eval flag of erl:
$ erl -eval 'io:format("Hello, World!~n")'
You can parse complex arguments with escript:
#!/usr/bin/env escript
main(String) ->
{Node, Mod, Fun, Args} = parse_args(String),
R = rpc:call(Node, Mod, Fun, Args),
io:format("~p~n",[R]).
If your problem is how to set the Erlang node in network mode (i.e. turn the node into a distributed node), you might want to do something like
EPMD = code:root_dir() ++ "/bin/epmd &",
os:cmd(EPMD),
net_kernel:start([Sname, shortnames])
where Sname is your wanted node name. Only after this can you start communicating to another node with e.g. rpc.

Resources