Run an escript using TLS distribution - erlang
I have been unable to make TLS distribution work when providing arguments for the vm via the %! line in the escript.
cat test.es
#!/usr/bin/env escript
%%! +P 256000 -env ERL_MAX_ETS_TABLES 256000 -env ERL_CRASH_DUMP /dev/null -env ERL_FULLSWEEP_AFTER 0 -env ERL_MAX_PORTS 65536 +A 64 +K true +W w -smp auto -boot /tmp/start_clean -proto_dist inet_tls -ssl_dist_opt server_certfile "/var/lib/cinched/cert.pem" server_cacertfile "/var/lib/cinched/cacert.pem" client_certfile "/var/lib/cinched/cert.pem" client_cacertfile "/var/lib/cinched/cacert.pem" server_keyfile "/var/lib/cinched/key.pem" client_keyfile "/var/lib/cinched/key.pem" -name test#192.168.101.1
main(_) ->
io:format("Ping: ~p~n",[net_adm:ping('cinched#192.168.101.1')]).
[root#dev1 ~]# ./test.es
{error_logger,{{2016,1,15},{23,36,42}},"Protocol: ~tp: not supported~n",["inet_tls"]}
{error_logger,{{2016,1,15},{23,36,42}},crash_report,[[{initial_call,{net_kernel,init,['Argument__1']}},{pid,<0.21.0>},{registered_name,[]},{error_info,{exit,{error,badarg},[{gen_server,init_it,6,[{file,"gen_server.erl"},{line,322}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,237}]}]}},{ancestors,[net_sup,kernel_sup,<0.10.0>]},{messages,[]},{links,[<0.18.0>]},{dictionary,[{longnames,true}]},{trap_exit,true},{status,running},{heap_size,376},{stack_size,27},{reductions,211}],[]]}
{error_logger,{{2016,1,15},{23,36,42}},supervisor_report,[{supervisor,{local,net_sup}},{errorContext,start_error},{reason,{'EXIT',nodistribution}},{offender,[{pid,undefined},{name,net_kernel},{mfargs,{net_kernel,start_link,[['test#192.168.101.1',longnames]]}},{restart_type,permanent},{shutdown,2000},{child_type,worker}]}]}
{error_logger,{{2016,1,15},{23,36,42}},supervisor_report,[{supervisor,{local,kernel_sup}},{errorContext,start_error},{reason,{shutdown,{failed_to_start_child,net_kernel,{'EXIT',nodistribution}}}},{offender,[{pid,undefined},{name,net_sup},{mfargs,{erl_distribution,start_link,[]}},{restart_type,permanent},{shutdown,infinity},{child_type,supervisor}]}]}
{error_logger,{{2016,1,15},{23,36,42}},crash_report,[[{initial_call,{application_master,init,['Argument__1','Argument__2','Argument__3','Argument__4']}},{pid,<0.9.0>},{registered_name,[]},{error_info,{exit,{{shutdown,{failed_to_start_child,net_sup,{shutdown,{failed_to_start_child,net_kernel,{'EXIT',nodistribution}}}}},{kernel,start,[normal,[]]}},[{application_master,init,4,[{file,"application_master.erl"},{line,133}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,237}]}]}},{ancestors,[<0.8.0>]},{messages,[{'EXIT',<0.10.0>,normal}]},{links,[<0.8.0>,<0.7.0>]},{dictionary,[]},{trap_exit,true},{status,running},{heap_size,376},{stack_size,27},{reductions,164}],[]]}
{error_logger,{{2016,1,15},{23,36,42}},std_info,[{application,kernel},{exited,{{shutdown,{failed_to_start_child,net_sup,{shutdown,{failed_to_start_child,net_kernel,{'EXIT',nodistribution}}}}},{kernel,start,[normal,[]]}}},{type,permanent}]}
{"Kernel pid terminated",application_controller,"{application_start_failure,kernel,{{shutdown,{failed_to_start_child,net_sup,{shutdown,{failed_to_start_child,net_kernel,{'EXIT',nodistribution}}}}},{kernel,start,[normal,[]]}}}"}
The boot file it's pointing to doesn't seem to be taken into account. I've tried other variations (trying to start the dependant apps via the -s switch), however nothing seems to work so far.
The boot file:
{release,{"start_clean",[]},
{erts,"6.4"},
[{kernel,"3.2"},
{stdlib,"2.4"},
{sasl,"2.4.1"},
{crypto,"3.5"},
{asn1,"3.0.4"},
{public_key,"0.23"},
{ssl,"6.0"}
]}.
Erlang ssl distribution needs a started ssl application which should be included into a boot script and is passed to emulator with -boot flag. But It seems that escript doesn't pass the -boot flag based on this example:
release file:
{release,
{"foo_rel", "0.1"},
{erts, "6.4"},
[{kernel, "3.2"},
{stdlib, "2.4"},
{crypto, "3.5"},
{asn1, "3.0.4"},
{public_key, "0.23"},
{ssl, "6.0"}]
}.
escript source:
#!/usr/bin/env escript
%%! -sname foo -boot /path/to/foo
main(_) ->
io:format("~p~n", [application:which_applications()]).
escript result:
[{stdlib,"ERTS CXC 138 10","2.4"},
{kernel,"ERTS CXC 138 10","3.2"}]
But booting the foo release with erl does start all the defined applications in boot file in a way that confirms the boot file is correct:
$ erl -boot /path/to/foo
Erlang/OTP 17 [erts-6.4] [...]
1> application:which_applications().
[{ssl,"Erlang/OTP SSL application","6.0"},
{public_key,"Public key infrastructure","0.23"},
{asn1,"The Erlang ASN1 compiler version 3.0.4","3.0.4"},
{crypto,"CRYPTO","3.5"},
{stdlib,"ERTS CXC 138 10","2.4"},
{kernel,"ERTS CXC 138 10","3.2"}]
Although I don't know why escript doesn't pass boot script to emulator, it is obvious that using boot file escript doesn't start ssl application, so the ssl distribution mode cannot be started.
Related
Change Erlang file handle limit?
I'm running into trouble with an Erlang OTP + Cowboy app that does not allow me to open enough files simultaneously. How do I change the number of open file handles allowed in the BEAM? Potentially, I'll need about 500 small text files open at the same time, but it appears that the file limit is 224. I've got the value of 224 from this little test program: -module(test_fds). -export([count/0]). count() -> count(1, []). count(N, Fds) -> case file:open(integer_to_list(N), [write]) of {ok, F} -> count(N+1, [F| Fds]); {error, Err} -> [ file:close(F) || F <- Fds ], delete(N-1), {Err, N} end. delete(0) -> ok; delete(N) -> case file:delete(integer_to_list(N)) of ok -> ok; {error, _} -> meh end, delete(N-1). This gives $ erl Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [kernel-poll:false] Eshell V9.2 (abort with ^G) 1> c(test_fds). {ok,test_fds} 2> test_fds:count(). {emfile,224} 3> This seems to be an Erlang problem rather than a Mac OSX problem since from the command line, I get: $ sysctl -h kern.maxfiles kern.maxfiles: 49,152 $ sysctl -h kern.maxfilesperproc kern.maxfilesperproc: 24,576
The number of open file descriptors is most likely being limited by your shell. You can increase it by running ulimit -n 1000 (or more) in your shell before invoking erl. On my system, the default value was 7168 and your script could open 7135 files before returning emfile. Here's the output of me running your script with different ulimit values: $ ulimit -n 64; erl -noshell -eval 'io:format("~p~n", [test_fds:count()]), erlang:halt()' {emfile,32} $ ulimit -n 128; erl -noshell -eval 'io:format("~p~n", [test_fds:count()]), erlang:halt()' {emfile,96} $ ulimit -n 256; erl -noshell -eval 'io:format("~p~n", [test_fds:count()]), erlang:halt()' {emfile,224} $ ulimit -n 512; erl -noshell -eval 'io:format("~p~n", [test_fds:count()]), erlang:halt()' {emfile,480} erl is most likely opening 32 file descriptors before it starts evaluating our code which explains the constant difference of 32 in the ulimit and the output.
Rebar3 + Cowboy Kernel PID Terminated
I installed rebar3 and created a new release with cd ~/apps rebar3 new release tunnel Then I copied my src files from ~/tunnel/src/* to ~/apps/tunnel/src/ I ran into a compile error with rebar3 run and found Erlang "Kernel pid terminated" error as a possible solution. I renamed everything about tunnel_app to tunnel. So my src contains tunnel.erl , tunnel.app.src and tunnel_sup.erl. I renamed the module definition as appropriate. Here's the rebar3 run error: ~/apps/tunnel:.rebar3 run ===> Verifying dependencies... ===> Compiling tunnel ===> Starting relx build process ... ===> Resolving OTP Applications from directories: /Users/quantum/apps/tunnel/_build/default/lib /Users/quantum/apps/tunnel/apps /usr/local/Cellar/erlang/19.2/lib/erlang/lib /Users/quantum/apps/tunnel/_build/default/rel ===> Resolved tunnel-0.1.0 ===> Dev mode enabled, release will be symlinked ===> release successfully created! readlink: illegal option -- f usage: readlink [-n] [file ...] Exec: /usr/local/Cellar/erlang/19.2/lib/erlang/erts-8.2/bin/erlexec -boot /Users/quantum/apps/tunnel/_build/default/rel/tunnel/releases/0.1.0/tunnel -mode embedded -boot_var ERTS_LIB_DIR /usr/local/Cellar/erlang/19.2/lib/erlang/lib -config /Users/quantum/apps/tunnel/_build/default/rel/tunnel/releases/0.1.0/sys.config -args_file /Users/quantum/apps/tunnel/_build/default/rel/tunnel/releases/0.1.0/vm.args -pa -- console Root: /Users/quantum/apps/tunnel/_build/default/rel/tunnel /Users/quantum/apps/tunnel/_build/default/rel/tunnel Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:8:8] [async-threads:30] [hipe] [kernel-poll:true] [dtrace] =INFO REPORT==== 16-Feb-2017::15:02:21 === application: tunnel exited: {bad_return, {{tunnel,start,[normal,[]]}, {'EXIT', {undef, [{cowboy_router,compile, [[{'_', [{"/info",lobby_handler,[]}, {"/join/:name",join_handler,[]}, {"/play/:table_pid/:name/:auth/:team/:action/:x/:y", play_handler,[]}]}]], []}, {tunnel,start,2, [{file, "/Users/quantum/apps/tunnel/_build/default/lib/tunnel/src/tunnel.erl"}, {line,8}]}, {application_master,start_it_old,4, [{file,"application_master.erl"}, {line,273}]}]}}}} type: permanent {"Kernel pid terminated",application_controller,"{application_start_failure,tunnel,{bad_return,{{tunnel,start,[normal,[]]},{'EXIT',{undef,[{cowboy_router,compile,[[{'_',[{\"/info\",lobby_handler,[]},{\"/join/:name\",join_handler,[]},{\"/play/:table_pid/:name/:auth/:team/:action/:x/:y\",play_handler,[]}]}]],[]},{tunnel,start,2,[{file,\"/Users/quantum/apps/tunnel/_build/default/lib/tunnel/src/tunnel.erl\"},{line,8}]},{application_master,start_it_old,4,[{file,\"application_master.erl\"},{line,273}]}]}}}}}"} Kernel pid terminated (application_controller) ({application_start_failure,tunnel,{bad_return,{{tunnel,start,[normal,[]]},{'EXIT',{undef,[{cowboy_router,compile,[[{'_',[{"/info",lobby_handler,[]},{"/j Crash dump is being written Why is this crashing?
If this is your first experience with rebar3, I suggest starting with an OTP application, not an OTP release: rebar3 new app tunnel and then do not blindly copy over the source files because you risk overwriting the files that have been created for you below src. Have a look at the contents of that directory beforehand. I also suggest to take the time to read the rebar3 https://www.rebar3.org/docs/basic-usage page. You will also have to read about what an OTP application is. I know, quite a lot to understand and sometimes confusing. A free source is http://learnyousomeerlang.com/building-applications-with-otp. It is also worthwhile to buy a book about Erlang. There are a few, I suggest https://www.manning.com/books/erlang-and-otp-in-action. There is also an online course, free, that starts in a few days (20th Feb 2017) https://www.mooc-list.com/course/functional-programming-erlang-futurelearn
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
An error with Erlang router
I try to make a comet-server using Mochiweb like there. If I do it from erlang shell, it's alright. But If try to start 1st node with mochiweb from command line: erl -pa ebin edit deps/*/ebin -boot start_sasl -sname n1 -s server +K true -setcookie secret_key -s reloader And 2nd one with router: erl -pa ebin edit deps/*/ebin -boot start_sasl -sname router -setcookie secret_key -eval 'net_adm:ping(n1#localhost), router:start_link().' If I connect to mochiweb from browser I have this error =CRASH REPORT==== 18-Jul-2012::19:04:45 === crasher: initial call: mochiweb_acceptor:init/3 pid: <0.73.0> registered_name: [] exception exit: {noproc, {gen_server,call, [undefined,{login,"234567e",<0.73.0>}]}} in function gen_server:call/2 in call from server_web:loop/2 in call from mochiweb_http:headers/5 ancestors: [server_web,server_sup,<0.55.0>] messages: [] links: [<0.57.0>,#Port<0.1406>] dictionary: [{mochiweb_request_qs, [{"session_id","234567e"},{"obj_id","page"}]}, {mochiweb_request_path,"/polling"}] trap_exit: false status: running heap_size: 2584 stack_size: 24 reductions: 1516 I think that problem is in this string from router.erl: -define(SERVER, global:whereis_name(?MODULE)). Because first part of -eval (net_adm:ping(n1#localhost)) was started without errors and I could see n1#localhost in nodes().. But the second part of -eval (router:start_link()) was not available for ?MODULE. How can I resolve this problem?
Looks like the gen_server that was supposed to be globally registered with name of current module (?MODULE is replaced with it) just has not been started yet. global:whereis_name(?MODULE) will return undefined right in this case, like you see in log you posted. Find the part of your code that's supposed to do that (by grepping for ?MODULe and/or gen_server:start_link in that module) and make sure it was executed on the first node.
Running An Erlang Escript File With SSL Distribution
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"]}]