How to run a beam file generated by erlang - erlang

I am a beginner in erlang. Please help me run an erlang program.
In the command line, I used this - c(main). to create a beam file. Now how do I run the program.
I am on windows.
% this is the hello world program I am trying to run
-module(main).
-export([start/0]).
start() ->
io:fwrite("Hello, world!\n").
Any help is highly appreciated.
Thank you

What you have written is a module. If compiled, then you will have to call the functions of this module to evaluate. Do like below, in the same command prompt where your Erlang Emulator(erl) is running...
Eshell V11.1.7 (abort with ^G)
1> main:start().
Hello, world!
ok
2>

Related

start erlang otp application from makefile

I've created an erlang application where I can use application:start(Name) to successfully start the application.
I tried to create a makefile step that uses rebar to compile, and then manually start the application. But it doesn't seem to work. Here's what I have now:
all: compile start
compile:
./rebar compile
start:
erl -s application load shoutcast -s application start shoutcast
All this does is loads up an interactive erlang shell
Aplication:start(Name)
calls
Name:start/2
while the -s flag calls
Name:start() or Name:start([arg1, arg2, ...]).
So, I don't think you can successfully invoke Application in this way. Assuming you don't want to create a release and boot file, you could (I think) add a method to you application module, start/0
-module(shoutcast).
-behaviour(application).
%% Application callbacks
-export([start/2, stop/1]).
%% Allow for erl -s invocation
-export([start/0]).
... Snip ...
start() ->
application:start(shoutcast).
... Snip ...
Then within your makefile
erl -s shoutcast
I'm not sure if this violates a best practice, but it should work.
It could be better to keep useful things in common Makefile
https://github.com/virtan/erlang-makefile

Problem with starting supervisor through script - Erlang

I have made an OTP compliant application where i have a gen_server and a supervisor. Also i have a script to start them.
My script contains something like this.
erl -pa module_name/ebin -name abc#hostname -setcookie test -s module_sup start_link()
This does not start the supervisor. But when i do module_sup:start_link() inside the shell, it works.
Also when i do
erl -pa module_name/ebin -name abc#hostname -setcookie test -s module_srv start_link()
i.e the server alone without the supervisor, the server gets started.
So, what am i doing wrong here. Are we not allowed to start supervisor in such a way.
Any help would be highly appriciated.
Thanx,
Wilson
supervisor:start_link/2 creates a link to its calling process. when that calling process exits, the supervisor is taken down with it.
erl -s module_sup start_link is starting the supervisor but it is killed because your start function runs inside its own process which dies once the function exits.
you can observe similar behavior with spawn(module_sup, start_link, []). the supervisor starts and gets killed immediately. when you manually start the supervisor, the calling process is the shell. when the shell exits, it will kill the supervisor.
generally the top-level supervisor is meant to be started by an application.
This is very similar to How do I start applications by command line as a daemon? In short, you can't use -s to start a supervisor unless use unlink/1, which is a total kludge. Your time is better spent learning how to package your code as an application. I'd recommend doing this with rebar.
It is important to notice that a process only dies if the linked process is terminating with a reason other than 'normal', which means that a process that simply finishes its execution does not kill the processes linked to it. (source http://www.erlang.org/doc/reference_manual/processes.html#id204170)
I think that is an important aspect of Erlang that should not be misinterpreted.
The following source code shows this:
1> spawn(
1> fun() ->
1> io:format("outer ~p~n", [self()]),
1> spawn_link(
1> fun () ->
1> io:format("inner ~p~n", [self()]),
1> receive
1> Msg -> io:format("received ~p~n", [Msg])
1> end
1> end)
1> end).
outer <0.37.0>
<0.37.0>
inner <0.38.0>
2> is_process_alive(pid(0,37,0)).
false
3> pid(0,38,0) ! test.
received test
test
4>
You can see that the caller <0.37.0> is not running, but the process <0.38.0> is still there, waiting for a message.
Anyway, the supervisor will not terminate when the caller terminates since the supervisor traps exit signals. Of course, unless it is programmed to do so. But I examined the source code and couldn't find this, but alas, my analysis may have been too superficial.
Have you had any luck with that? I will try to run some tests and see if I can figure out what is happening.

How do I start applications by command line as a daemon?

This has been my current routine
sudo nohup erl -sname foo -pa ./ebin -run foo_supervisor shell -noshell -noinput &
where the shell function looks something like this
shell() ->
{ok, Pid} = supervisor:start_link({local,?MODULE}, ?MODULE, _Arg = []),
unlink(Pid).
If I don't unlink from shell it immediately stops for some reason. Is there a way I can just start my application like I would normally ie application:start(foo). Also what if I want to start sasl too? Also where could I learn more about making a self contained package using rebar?
Preface. About your unlink
In this other SO thread #filippo explains why you need the unlink when testing supervisors from the shell.
First. What you need is an Erlang application.
Reading from the doc:
In OTP, application denotes a
component implementing some specific
functionality, that can be started and
stopped as a unit, and which can be
re-used in other systems as well.
Details on how to implement an Erlang application are available here. The three main things you will need to do are:
Have a proper directory structure for your application
Write an application callback module implementing the Erlang application behaviour. That's where you will start your root supervisor
Provide an application resource file. This is where you tell the system - among other things - where to find your application callback module (look at the mod parameter).
Second. Starting SASL.
In the above application resource file, you can specify a list of applications you want to start before your application. You will add something like:
...
{applications, [kernel, stdlib, sasl]},
...
To tell it to start SASL.
Third. Rebar.
There's an introduction to Rebar here, which explains you how to use Rebar to help you in the above steps, to pack your brand new application into an Erlang release and how to start it.

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.

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