Erlang VM -s Argument is causing my program to fail - erlang

I have read the thread here: Erlang VM -s argument misbehaving and have been troubleshooting to no avail.
When I run the erlang vm without the -s flag, my function works:
bridge_sup:start_link().
Bridge Supervisor Initializing
[warning] ClientId is NULL!
[warning] ClientId is NULL!
Success
Success
However, if I have the -s flag set, when my function goes on to call another function emqttc:start_link(...) it never returns:
Bridge Supervisor Initializing
[warning] ClientId is NULL!
[warning] ClientId is NULL!
I can verify that it is not just a print problem because the program I am connecting to receives no signal.
What could possibly be causing this in the Erlang VM? I have also tried using eval to the same effect. Here is the ./run code:
erl -pa ebin -pa deps/*/ebin
Thank you in advance!

Could be a startup order problem. Specifying a command to run using -s (or -run or -eval) means that it starts very quickly, while parts of the system may still be starting up in the background. Try adding a sleep at the start of your function and see if it changes anything. In that case, try to figure out what depends on the order.

I am using Erlang version 19.2. I am not sure if this is a bug in this version, or it is a requirement to start a program, but I added a .app.src file and added "-eval 'application:start(myprog)'" and the program will now start!
Note that it did not start with -s, -eval, or any of that without the app.src file and without application:start

Related

Erlang: print loaded sys.config in OTP application

How do I show the absolute path that my Erlang OTP application is loading sys.config from? I.e., if get_all_env (http://erlang.org/doc/apps/kernel/application.html#get_all_env-0) shows unexpected results, how do I see what file is being loaded to debug?
I did this once, so I know it is possible, but sadly I cannot find that code =(
You can use init:get_plain_arguments/0 to get the full list of VM arguments:
(node#localhost)13> init:get_plain_arguments().
["/usr/local/bin/rebar3","shell","--apps","some_app",
"--config","priv/sys.config","--sname","node1#localhost"]
That certainly works if you have started the node manually on CLI. For reference, the output above corresponds to my start script using rebar3:
rebar3 shell --apps some_app --config priv/sys.config --sname node1#localhost

Docker - Handling multiple services in a single container

I would like to start two different services in my Docker container and exit the container as soon as one of them exits. I looked at supervisor, but I can't find how to get it to quit as soon as one of the managed applications exits. It tries to restart them up to three times, as is the standard setting and then just sits there doing nothing. Is supervisor able to do this or is there any other tool for this? A bonus would be if there also was a way to let both managed programs write to stdout, tagged with their application name, e.g.:
[Program 1] Some output
[Program 2] Some other output
[Program 1] Output again
Since you asked if there was another tool... we designed and wrote a powerful replacement for supervisord that is designed specifically for Docker. It automatically terminates when all applications quit, as well as has special service settings to control this behavior, plus will redirect stdout with tagged syslog-compatible output lines as well. It's open source, and being used in production.
Here is a quick start for Docker: http://garywiz.github.io/chaperone/guide/chap-docker-simple.html
There is also a complete set of tested base-images which are a good example at: https://github.com/garywiz/chaperone-docker, but these might be overkill and the earlier quickstart may do the trick.
I found solutions to both of my requirements by reading through the docs some more.
Exit supervisord on application exit
This can be achieved by using a custom eventlistener. I had to add the following segment into my supervisord configuration file:
[eventlistener:shutdownevent]
command=/shutdownhandler.sh
events=PROCESS_STATE_EXITED
supervisord will start the referenced script and upon the given event being triggered (PROCESS_STATE_EXITED is triggered after the exit of one of the managed programs and it not restarting automatically) will send a line containing data about the event on the scripts stdin.
The referenced shutdownhandler-script contains:
#!/bin/bash
while :
do
echo -en "READY\n"
read line
kill $(cat /supervisord.pid)
echo -en "RESULT 2\nOK"
done
The script has to indicate being ready by sending "READY\n" on its stdout, after which it may receive an event data line on its stdin. For my use case upon receival of a line (meaning one of the managed programs has exited), a SIGTERM is sent to the supervisord process being found by the pid it leaves in its pid file (situated in the root directory by default). For technical completeness, I also included a positive answer for the eventlistener, though that one should never matter.
Tagged output on stdout
I did this by simply starting a tail process in the background before starting supervisord, tailing the programs output log and piping the lines through ts (from the moreutils package) to prepend a tag to it. This way it shows up via docker logs with an easy way to see which program actually wrote the line.
tail -fn0 /var/log/supervisor/program1.log | ts '[Program 1]' &

ejabberd - Running escript from the same context as `ejabberdctl debug`

Part of setting up my ejabberd server includes running ejabberdctl debug and entering some commands. Instead, I would like to have a file that is executed, but have it run from the same context of the ejabberdctl debug REPL. How can I do this?
You can use the rpc:call command. The Node value is what you see at the debug prompt "name#host".
Also, make sure the escript sets the appropriate cookie value.
Let me clarify, if the debug environment looked like this:
(ejabberd#host)1>
You can create a escript file which looks like this. This updates the log level:
#!/usr/bin/env escript
%%! -sname script1 -setcookie cookie -hidden
main([Level]) ->
rpc:call('ejabberd#host', ejabberd_loglevel, set, [list_to_atom(Level)]).

Run erlang application without terminal depending

I have erlang application: *.app file and some *.erl files. I compile all of them. In terminal i start erl and there application:start(my_application)., all ok, but if i closed terminal application close too. How can i run application without terminal depending?
Thank you.
You likely want to use the -noshell option to erl. The syntax is
erl -noshell -s Module Function Arguments
So in your case, this might be
erl -noshell -s application start my_application
This should allow you (for example if you are on Unix/Linux) to start your application as a background process and leave it running.
One useful variation is to also call the stop/0 function of the init module so that the Erlang environment will stop when it has finished running your function. This comes in handy if you want to run a simple one-use function and pipe the output to some other process.
So, for example, to pipe to more you could do
erl -noshell -s mymodule myfunction -s init stop | more
Finally, you might also be able to use the escript command to run your Erlang code as scripts rather than compiled code if it makes sense for your situation.
Hope that helps.
The proper way to handle this situation, is building a release containing your app and running the system as so called embedded one.
This release is going to be completely independent (it will hold erts and all the libs like, kernel, std, mnesia etc.).
On start, the new process will not be connected to shell process.
It will be OS process, so you can attach to it with pipes. All script are included in OTP.
Here is some info: http://www.erlang.org/doc/design_principles/release_structure.html
It may seem to be complicated, but tools like rebar do everything for you.

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.

Resources