Add Path to Erlang Search Path? - erlang

I recently installed Erlang RFC4627 (JSON-RPC) with the debian package. I ran the test server using:
sudo erl -pa ebin
and then at the prompt:
test_jsonrpc:start_httpd().
returned
ok
I tested with http://:5671/ and got the success messages.
When I try to run rabbitmq-http2 however, I get the errors that the readme says are caused by rfc4627's code not being on the erlang search path. How do I put it on the path. I saw something on Dave Thomas's blog which suggested putting the path in the file:
~/.erlang
This didn't seem to work for me (maybe I did it wrong?).

The code module is how you manipulate the path within an application.
The flags -pa that you used in starting the Erlang shell actually refer to a function in this module:
add_patha(Dir) -> true | {error, What}
You are right about the .erlang file in your home directory - it is run at start-up time of the shell and you can add in handy paths.
For an application you can start the shell with a batch file that calls something like this:
erl -pa ./ebin ../../lib/some/path/ebin
The flags behaviour of erl is described here.
For more sophisticated path management you need to get familiar with how OTP release management is done (but I suspect that is a while away for you yet).

Related

Erlang Erl commands not working on Windows 10

Hello i was trying to issue some distributed erlang commands such as erl -sname/erl -name and i do not get a response.
If i put . at the end it says syntax error.
If i don't it won't return anything and it will treat it like an unfinished command.
I thought this is only for these commands but it seems there are others that will not do anything like
erl -man <module_name>.
Do i need to set something up to be able to issue erl commands.
P.S OS is Windows 10.
The erl command (with or without -sname) is simply how you run Erlang from a console window like cmd or powershell. On Windows, to get a fully working Erlang shell with command line editing etc, you need to use the special werl executable instead of erl - this is due to how Windows consoles work. Try opening a cmd or powershell windows and see how it works.
If you open the properties of the icon you have used for starting Erlang, you will see that the command it is running is werl (from the Start menu you have to use "more -> open file path" to find the actual icon first). You can edit this and add options like -sname yournodename to the command, or you can create a copy of the icon (e.g. to your desktop) and give it a more suitable name, like "My Erlang node", and then edit its options.

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

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.

erlang - startup script

To start my program I do the next sequence:
$ erl
> c(module1).
> c(module2).
> c(modulen).
modulen:start().
Is there any possibility to create script that allow me to launch my program ?
You could use a loader script that takes care of starting your application in an OTP fashion:
-module(XYZ_app).
-export([start/0]).
start() ->
application:start(inets),
application:start(XYZ).
You launch that script through a shell script. Beware of using escript if you plan on building daemons running at the OS boot time as they are tricky.
#!/bin/bash
erl -boot start_sasl -s XYZ_app start
Of course you need your XYZ.app file (just an example):
{application, tinycouch,
[{description, "tinycouch"},
{vsn, "0.1"},
{modules, [
tinycouch, tinycouch_app, tinycouch_sup,
tinycouch_server, tinycouch_logger_h, tinycouch_utils,
tinycouch_db, mod_tinycouch
]},
{registered, [tinycouch
,tinycouch_server
,tinycouch_sup
]},
{applications, [kernel, stdlib, sasl, inets]},
{env, []},
%% Application Start point
{mod, {tinycouch_sup, []}}]}.
... and all your .erl files must have been compiled.
Note that if you intend to distribute your application (e.g. Debian repository etc), you probably should consider having a make file to compile and install your app.
As a final note: you could also go with a boot file (the ultimate OTP way) but I find those very constraining: a boot file ties your application to specific version release of Erlang (and other dependent applications). Your application might be able to run in various Erlang releases but you will need to have a separate build/release process for each "platform release" you intend to ship for.
You can compile the modules with erlc
erlc module1 module2 module3
You can also create a script to run you program
#!/usr/bin/escript
main(_) ->
modulen:start().
Then in the console:
chmod +x start.erl
./start.erl
Two ways
precompile your code
$ erlc module1.erl
$ erl -s module1 funcname arg1 arg2 ....
Or use escript
#!/usr/bin/env escript
main() ->
module1:fun(...)
escript is a scripting interface to Erlang
You can use erl -make directly, as it assumes all *.erl files should be compiled to *.beam, and skip it if they haven't been changed since last compile. Check out the make module for what you can put in your Emakefile to change certain behavior.
Using plain Makefile to invoke this compile strategy also gives other users a familiar build-procedure.
Having a bootstrap start function as jldupont suggests is a nice way to start up your development environment. It is even sufficiently fine for using in production to some point.
The next step is to use full OTP (*.rel) release files and generate boot scripts that starts all the applications in the order the *.app specify dependencies on each other.
In the home directory, create file
.erlang
in that file write
compile:file(/path-to/module1).
compile:file(/path-to/module2).
compile:file(/edit-real-path-to/modulen). % etcetera; do not use c(module) inside this file!
then, if you need add (inside .erlang):
module1:start(). % etc
When you run erl (in the shell), the content of the .erlang (provided this file is in the home dir) will be executed at start (of the interpreter-erlang-VM you launch).
You can create .erlang file in some other (some 'current') directory, then, if you run erl (erlang interpreter) in that directory, that another .erlang will override the content of that .erlang in the home dir (of that which is like /home/your-user-name/.erlang ).
It is good idea to write inside of .erlang some reminder, like
io:format(".erlang loaded-compiled module1!\n"). %etc
(as not to forget about that code which otherwise will be executed silently !)
(also, you can check, for this case, that e.g. module1 is indeed compiled and loaded after start, this or some similar way:
AllLoaded = code:all_loaded().
lists:filter(fun({Module,_})-> Module =:= module1 end, AllLoaded).
the answer should be like:
[{module1,"/home/your-user-name/(path-to-your-code)/module1.beam"}]
)
Check out Sinan and Faxien: http://www.erlware.org

Resources