I've got a module that I'm attempting to turn into a proper OTP application. Currently, the module has start/0 which starts a genserver which supplies configuration data read from a config file. It then calls inets:start(httpd,config:lookup(httpd_conf)). I gather that I need to move the starting of these out into the .app file's (application list) but I'm not sure how to get my config data into the inets:start function (or pass in httpd)?
Thanks,
--tim
Here's what I've figured out...
First, I needed to create the inets config file:
inets.config:
[{inets, [{services, [{httpd, [{proplist_file,
"8080.conf"}]},
].
Then, create the httpd conf file:
8080.conf
[
{modules, [
mod_alias,
mod_auth,
mod_esi,
mod_actions,
mod_cgi,
mod_dir,
mod_get,
mod_head,
mod_log,
mod_disk_log
]},
{port,8080},
{server_name,"hello_world"},
{server_root,"log"},
{document_root,"www"},
{erl_script_alias, {"/erl", [hello_world]}},
{error_log, "error.log"},
{security_log, "security.log"},
{transfer_log, "transfer.log"},
{mime_types,[
{"html","text/html"},
{"css","text/css"},
{"js","application/x-javascript"}
]}
]
Now, when booting my app, I just reference the inets.conf file with:
$ erl -boot start_sasl -pa ebin -config inets.config
This seems to work not sure if it's the "right" way or not...
Related
I'm adding Elvis check style to Erlang project built with rebar3.
Initially I've found rebar3_lint plugin for this. But then it appeared to use some old version of Elvis and fails not very graciously on errors.
Then after some play I attached elvis directly as a test dependency and then calling it with pre_hook and erlang code line:
{profiles, [
{test, [
{deps, [
{elvis_core,
{git, "https://github.com/inaka/elvis_core",
{branch, "master"}}}
]},
{pre_hooks, [{compile,
"erl -pa _build/test/lib/*/ebin -noshell -eval 'init:stop(case elvis_core:rock() of ok -> 0; _ -> 1 end)'"}]}
]},
]}
This works nicely, though looks awkward.
So is there any more "proper" way? Thanks in advance!
When I run ./rebar get-deps compile escriptize, it fails with the following:
WARN: 'escriptize' command does not apply to directory /path/to/foo
Command 'escriptize' not understood or not applicable
What have I forgotten?
Even though you're generating an escript package, rebar still needs the foo.app file. If you didn't use ./rebar create-app appid=foo to create your "application", you'll need to create one by hand:
{application, foo,
[
{description, ""},
{vsn, "1"},
{registered, []},
{applications, [
kernel, stdlib
]},
{env, []}
]}.
Note that you might need to ./rebar compile again in order to generate the foo.app file before ./rebar escriptize will generate the script correctly.
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
I would like to write a standalone Erlang application which could be run just like any other program (by clicking on .exe executable). Something like Wings3D does.
How can I do it ? What is the best approach to make it possible ? I am on Windows platform, if it is important.
2nd UPDATE:
Well, I haven't exported the promodb:start/0 function and that was the reason Erlang could'n start (and, as the Muzaaya Joshua says, werl -s does not work). But now, I have another strange problem. In my rebar.config I have 2 dependencies:
{deps, [
{cowboy, ".*", {git, "https://github.com/extend/cowboy.git"}},
{erlydtl, ".*", {git, "https://github.com/evanmiller/erlydtl.git"}}
]
}.
and after I start Erlang using
erl -pa ebin deps/cowboy/ebin deps/erlydtl/ebin deps/proper/ebin -s promodb
I find by application:which_application() that only Cowboy is started:
[{cowboy,"Small, fast, modular HTTP server.","0.4.0"},
{stdlib,"ERTS CXC 138 10","1.18"},
{kernel,"ERTS CXC 138 10","2.15"}]
As far as I know, Erlang should start all needed applications that I put in my promodb.app file, as:
{application, promodb,
[
{description, ""},
{vsn, "0.1"},
{registered, [promodb_sup]},
{applications, [
kernel,
stdlib,
cowboy,
erlydtl
]},
{mod, { promodb, []}},
{env, []}
]}.
What did I do wrong ?
I use rebar escriptize to pack a standalone package like rebar. Then you can use ./PackageName in linux or escript.exe PackageName in windows.
I think you need to create a release package and a boot script as explained in the documentation.
Actually the -s option works everywhere. Just use erl NOT werl. The werl command attempts to load a GUI on Windows.
The BitRock Install Builder is a great tool you need to check out. Yaws Web Server written in Erlang, uses it and many other applications.
Erlydtl doesn't have an application behaviour, it works like a library. As you can see in erlydtl examples, no app is needed to be started.
https://github.com/evanmiller/erlydtl#template-compilation
Check this:
erl -pa ebin deps/*/ebin
1> erlydtl:compile(<<"{{ foo }}">>, my_module_name).
Does it works?
I like escriptize rebar option to create executables.
I have an Emakefile that looks like:
%% --
%%
%% --
{'/Users/user/projects/custom_test/trunk/*',
[debug_info,
{outdir, "/Users/user/projects/custom_test/trunk/ebin"},
{i, "/Users/user/projects/custom_test/trunk/include/."}
]
}.
What is an explanation in layman's terms for what each item does in the list?
How do I run the emakefile so that I am able to compile it?
After compilation, how do I run that generated BEAM file?
1/ {"source files globbed", Options}
Here the options are :
debug_info add debug info for the debugger
{outdir, "/Users/user/projects/custom_test/trunk/ebin"} where should the output be written (the .beam files)
{i, "/Users/user/projects/custom_test/trunk/include/."} where to find the .hrl header files.
2/ erl -make
3/ erl -pa /Users/user/projects/custom_test/trunk/ebin starts a shell.
Find the module serving as an entry point in your application and call the functions :
module:start().
You can also run the code non interactively :
erl -noinput -noshell -pa /Users/user/projects/custom_test/trunk/ebin -s module start
For the Emakefile synax visit the man page
In the directory where the Emakefile is run erl -make to compile using the Emakefile
Simplest way to run would be to simply start an erlang shell in the same directory as the beam files with the command erl. Then run the code with module_name:function_name(). (including the dot).