Running An Erlang Escript File With SSL Distribution - erlang

I have a little escript file that connects to a node and does some rpc calls and stuff...
It works fine for short or longnames but relies on standard http comms for distributed Erlang.
I would like to use it but with https/SSL for distribution.
To start a 'normal' Erlang system with SSL you have to pass in the various flags to tell Erlang to run that way, as the documentation suggests:
$ ERL_FLAGS="-boot \"/home/me/ssl/start_ssl\" -proto_dist inet_ssl
-ssl_dist_opt client_certfile \"/home/me/ssl/erlclient.pem\"
-ssl_dist_opt server_certfile \"/home/me/ssl/erlserver.pem\"
-ssl_dist_opt verify 1 -ssl_dist_opt depth 1"
$ export ERL_FLAGS
$ erl -sname ssl_test
This replaces the default distribution mechanism (inet_tcp_dist) with the ssl one (inet_ssl_dist).
escript runs an erlang file as a shell scripting file.
My questions are:
is it possible to get the Erlang 'environment' in which escript runs to use the secure distribution mechanism instead of the default one?
and if so, how would I do it?

You don't have to set these flags via the environment, you can also pass them directly to erl, see ch. 1.4 here. erl flags can be passed to escript via the %%! argument line.
z.escript
#!/usr/bin/env escript
%%! -boot start_ssl -proto_dist inet_ssl -ssl_dist_opt client_certfile /home/me/ssl/erlclient.pem -ssl_dist_opt server_certfile /home/me/ssl/erlserver.pem -ssl_dist_opt verify 1 -ssl_dist_opt depth 1
main(_) ->
io:format("~p~n", [init:get_arguments()]).
zed#zed:~$ ./z.escript
[{root,["/opt/erlang-R13B03/lib/erlang"]},
{progname,["erl"]},
{home,["/home/zed"]},
{boot,["start_clean"]},
{noshell,[]},
{boot,["start_ssl"]},
{proto_dist,["inet_ssl"]},
{ssl_dist_opt,["client_certfile","/home/me/ssl/erlclient.pem"]},
{ssl_dist_opt,["server_certfile","/home/me/ssl/erlserver.pem"]},
{ssl_dist_opt,["verify","1"]},
{ssl_dist_opt,["depth","1"]}]

Related

How do I connect to an Erlang node which uses a short name?

When I run erl -sname foo, the node name created uses the hostname, rather than "localhost", so it is generated as, for example, foo#roger-pc.
I then register(shell, self()), and I can send messages to it from another node (erl -sname bar) as follows:
{shell, 'foo#roger-pc'} ! {hello, world}.
But it doesn't work if I use {shell, foo} ! {knock, knock}. The message is never received.
How do I connect to an Erlang node on the same PC which is using a short name? Or: how do I derive the "#roger-pc" part of the destination node name? Or: should I just use erl -name foo#localhost to register a long name?
Some background: I'm writing a an escript which spawns an erl process, and I'd like to be able to send messages from that OS process back to the original script.
you can specify 'localhost' explicitly for sname.
first shell
erl -sname ax#localhost
register(rcvr, self()).
second shell
erl -sname bx#localhost
net_kernel:connect_node(ax#localhost).
{rcvr, ax#localhost} ! hello.
and first shell again
(ax#localhost)7> flush().
Shell got hello
ok
sname still requires the '#' notation. You just don't have to input the full uri when sending messages.
c:\>erl -sname short
(short#hostname)1> {process, 'short#hostname'} ! Message.
c:\>erl -name short
(short#hostname.more.stuff)1> {process, 'short#hostname.more.stuff'} ! Message.
short is not the full name. sname and name merely decide how much of the rest of the path is required.
A node is an executing Erlang runtime system which has been given a name, using the command line flag -name (long names) or -sname (short names).
The format of the node name is an atom name#host where name is the name given by the user and host is the full host name if long names are used, or the first part of the host name if short names are used. node() returns the name of the node. Example:
% erl -name dilbert
(dilbert#uab.ericsson.se)1> node().
'dilbert#uab.ericsson.se'
% erl -sname dilbert
(dilbert#uab)1> node().
dilbert#uab

erlang R16B01 and Windows CMD

I'm windows 7 user and try to learn erlang and here's the time when I get to the paragraph where I have to deal with creating and naming nodes. I used to start erlang emulator from shortcut and don't know how to start it from command prompt window to use -name or -sname commands, and when I try to use
net_kernel:start([node,shortnames]).
command I get
{error,
{{shutdown,
{failed_to_start_child,net_kernel,{'EXIT',nodistribution}}},
{child,undefined,net_sup_dynamic,
{erl_distribution,start_link,[[node,shortnames]]},
permanent,1000,supervisor,
[erl_distribution]}}}
=INFO REPORT==== 23-Aug-2013::15:28:03 ===
Protocol: "inet_tcp": register/listen error: econnrefused
error. I thought it was because of windows firewall and turned it off, but nothing has changed. So can someone answer what's going on?? And if you don't mind teach me how can I start erlang from CMD and use -name and -sname commands.
1) make sure you have in the path, program files \ erlang \ bin \ erl
2) open the command prompt and type
3) erl -sname dilbert
-name = for fully qualified name [dilbert#mypc.maydomain.com]
-sname for short name [dilbert#mypc]
this will give you
% erl -sname dilbert
(dilbert#mypc)1> node().
dilbert#mypc
I am, most of the time, a windows user, and as it is not natural in this environment to use command windows, I used to write some command files to invoke werl (the usual VM interface in windows). But I stopped that, because it is less convenient and less flexible than the command window, and also because I very often need other command line tools like ping, ipconfig, or git...
I join an example of the code you can use:
launch_werl.bat:
echo off
echo Select a project:
echo 1: project 1
echo 2: project 2
echo 3: project 3
set /p proj=
goto label%proj%
:label1
d:
cd "\git\project1"
set prname=proj1
goto end
:label2
d:
cd "\documents and Settings\user\My Documents\path\to\some\code"
set prname=proj2
goto end
:label3
d:
cd "\git\proj3"
set prname=PLC
goto end
:end
start werl -sname %prname% -pa "./ebin"
echo on

How to run erlang (rebar build) application

I am new to Erlang world and currently can't figure out how to start my dummy erlang application. Probably, I am just missing something... So, I created an application with rebar (rebar create-app appid=dummys).
Currently I have
rebar.config
src/dummys.app.src
src/dummys_app.erl
src/dummys_sup.erl
I have found that in order to run an application during a development it is better to create an additional start method which should call application:start(module).
I added some basic logging to my start methods..
start() ->
error_logger:info_msg("Starting app(dev)..~n"),
application:start(dummys_app).
start(_StartType, _StartArgs) ->
error_logger:info_msg("Starting app..~n"),
dummys_sup:start_link().
If I try
erl -noshell -pa ebin -s application start dummys
erl -noshell -pa ebin -s application start dummys_app
there are no output..
If I try
erl -noshell -pa ebin -s dummys start
erl crashes with an error..
If I try
erl -noshell -pa ebin -s dummys_app start
it outputs just "Starting app(dev).." and that's all. But I also expect to see "Starting app.."
What I am missing or doing wrong??
=============
And another question: How to add a new module to my dummy application correctly? For example I have an additional module called "*dummys_cool*" which has a "start" method. How to tell my application to run that "dummys_cool#start" method?
Thank you!
For quick development, if you just want to ensure your appliction can start, start a shell, then start the application:
erl -pa ebin
1> dummys_app:start().
That will give you a clean indication of what is wrong and right without the shell bombing out after.
Since you're making an application to run, rather than just a library to share, you'll want to make a release. Rebar can get you most of the way there:
mkdir rel
cd rel
rebar create-node nodeid=dummysnode
After you've compiled your application, you can create a release:
rebar generate
This will build a portable release which includes all the required libraries and even the erlang runtime system. This is put by default in the rel/ directory; in your case rel/dummys.
Within that directory there will be a control script that you can use to start, stop, and attach to the application:
rel/dummys/bin/dummys start
rel/dummys/bin/dummys stop
rel/dummys/bin/dummys start
rel/dummys/bin/dummys attach
Have a look at your dummys.app.src file. The meaning of all the directives is explained in the 'app' manpage, but the one I suspect is missing here is mod, which indicates the name of your application callback module. So make sure that this line is present:
{mod, {dummys_app, []}}
The empty list in there will be passed as the StartArgs argument to dummys_app:start/2.
To make a new module start along with your application, add it to the supervision tree in dummys_sup:init. This function should look something like:
init(_) ->
{ok, {{one_for_one, 10, 10},
[{dummys_cool, {dummys_cool, start_link, []},
permanent, brutal_kill, worker, [dummys_cool]}]}.
This is described in the 'supervisor' manpage, but basically this means that on startup, this supervisor will start one child process. dummys_cool:start_link() will be called, and that function is expected to spawn a new process, link to it, and return its process id. If you need more processes, just add more child specifications to the list.
erl -noshell -pa ebin -s application start dummys
The code above will not work because application:start([dummys]) will be called.
You can take a reference of the Erlang documentation for details.
For your case,
erl -noshell -pa ebin -s dummys
I ran into this problem, and this was the first answer on Google.
If you are using rebar3, the standard configuration will have a shell command that compiles your project and opens a shell:
$ rebar3 shell
===> Analyzing applications...
===> Compiling myapp
Erlang/OTP 21 [erts-10.2.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1]
Eshell V10.2.4 (abort with ^G)
1> ===> Booted myapp

How do I install LFE on Ubuntu Karmic?

Erlang was already installed:
$dpkg -l|grep erlang
ii erlang 1:13.b.3-dfsg-2ubuntu2 Concurrent, real-time, distributed function
ii erlang-appmon 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP application monitor
ii erlang-asn1 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP modules for ASN.1 support
ii erlang-base 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP virtual machine and base applica
ii erlang-common-test 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP application for automated testin
ii erlang-debugger 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP application for debugging and te
ii erlang-dev 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP development libraries and header
[... many more]
Erlang seems to work:
$ erl
Erlang R13B03 (erts-5.7.4) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.7.4 (abort with ^G)
1>
I downloaded lfe from github and checked out 0.5.2:
git clone http://github.com/rvirding/lfe.git
cd lfe
git checkout -b local0.5.2 e207eb2cad
$ configure
configure: command not found
$ make
mkdir -p ebin
erlc -I include -o ebin -W0 -Ddebug +debug_info src/*.erl
#erl -I -pa ebin -noshell -eval -noshell -run edoc file src/leex.erl -run init stop
#erl -I -pa ebin -noshell -eval -noshell -run edoc_run application "'Leex'" '"."' '[no_packages]'
#mv src/*.html doc/
Must be something stupid i missed :o
$ sudo make install
make: *** No rule to make target `install'. Stop.
$ erl -noshell -noinput -s lfe_boot start
{"init terminating in do_boot",{undef,[{lfe_boot,start,[]},{init,start_it,1},{init,start_em,1}]}}
Crash dump was written to: erl_crash.dump
init terminating in do_boot ()
Is there an example how I would create a hello world source file and compile and run it?
No, there is nothing you missed. The Makefile in LFE is "less than perfect" and should be ignored, it will be improved upon in the next release. To compensate all the needed files have already compiled and the .beam files are in the ebin directory. As it is not part of OTP I don't think it should ever install there.
The easiest way to handle this to create a private erlang library directory and point the environment variable ERL_LIBS to it. Then just drop the whole LFE directory there. When erlang starts the code server will automatically add the lfe/ebin directories into the path and the .beam files there will automagically be found and loaded. This will work with any package that contains an ebin directory. This also works on Windows. So:
Make an libs directory, say ~/erlang/lib
Set the environment variable ERL_LIBS, export ERL_LIBS=~/erlang/lib
Put the whole LFE directory there
When you start erlang you will then see /Users/rv/erlang/lib/lfe/ebin (or wherever you have it) in the code path (code:get_path()). You will then also be able to start the LFE shell directly with
erl -noshell -noinput -s lfe_boot start
There will be an lfe and an lfe.bat which does this included as well in the future.
As with erlang any text editor will work to edit LFE. For emacs there is an LFE mode which is still rather basic but works. You cannot yet run LFE in a window. Soon. The best way to include this is to put the following in your .emacs file:
;; LFE mode.
(setq load-path (cons "/Users/rv/erlang/lib/lfe/emacs" load-path))
(require 'lfe-start)
There are some example files in lfe/examples, all should work. In lfe/test/visual there is a bunch of my test files which have been included as example files. To compile an LFE file from the normal erlang shell do
lfe_comp:file("foo").
l(foo). %No autloload here, do this to ensure loading
while from the LFE shell do:
(c '"foo") ;This will autoload
There is a bunch of documentation in lfe/docs which is quite accurate but the user_guide.txt needs to be extended. There is also a Google group for LFE at
http://groups.google.se/group/lisp-flavoured-erlang
which contains some interesting discussions and people have written quite a lot in the github LFE wiki.
That's about it I think. contact me if/when you have more questions.

Log errors in a file

How do I log all process crashes into a file instead of a tty ? I've read in the documentation that there are some standard Erlang modules that can do it (SASL, error_logger), but unfortunately haven't found any clean examples.
Start your erl node with
erl -boot start_sasl -sasl sasl_error_logger \{file,\"path/to/logfile.log\"\}

Resources