In my startup script, I am starting erlang with:
erl -args_file vm.args
Currently, while trying to run unit tests with rebar eunit is there a way for me to pass custom runtime arguments such as the -args_file option to the erlang process that rebar kicks off? I have searched docs high and low to no avail...
I appreciate the help.
I answered my own question. I use the ERL_FLAGS variable to pass command line args. Here is a snippet from my Makefile:
ERL_FLAGS="-args_file test/conf/vm.eunit.args" ./rebar skip_deps=true eunit
The first method is satisfied with your restriction:
1. in your eunit test function, to use erlang's "os:cmd("erl -name bar -detached arguments")." to start another erlang node. In the arguments, you can insert whatever you want. But eunit's check will be difficult because the test will cross the nodes.
The second methods is to change your restriction:
1. To use "configuremnt file" to pass arguments, and not to use command parameter to pass parameters.
Related
I am trying to pass command-line arguments to my elixir release. I have built the release using
MIX_ENV=prod mix release
Now, Am not able to pass any command-line arguments with the start command.
_build/prod/rel/prod/bin/prod start arg1 arg2
Using eval i have achieved passing the arguments but it stops after a while.
_build/prod/rel/prod/bin/prod eval "Hello.nodes([3, :node1])"
Is there any way that I can pass the args through the start flag?
Using eval i have achieved passing the arguments but it stops after a
while.
_build/prod/rel/prod/bin/prod eval "Hello.nodes([3, :node1])"
From the docs:
The eval command starts its own instance of the VM but without
starting any of the applications in the release and without starting
distribution. For example, if you need to do some prep work before
running the actual system, like migrating your database, eval can be a
good fit. Just keep in mind any application you may use during eval
has to be explicitly loaded and/or started.
I'm guessing that your eval tries to use an application that you didn't explicitly load before executing the eval.
Is there any way that I can pass the args through the start flag?
It's not documented, but there are various ways to configure a release:
https://elixir-lang.org/getting-started/mix-otp/config-and-releases.html
Maybe an escript would be a better fit?
escript provides support for running short Erlang programs without
having to compile them first, and an easy way to retrieve the
command-line arguments.
It is possible to bundle escript(s) with an Erlang runtime system to make it self-sufficient and relocatable.
I have a program that starts the application and then adds (children) workers to a supervisor. Obviously after doing only that it has nothing more left to do and it halts (exits). So making it not halt the VM would allow the workers to work.
The only solution I have came up was to add:
IO.gets "Working... To finish hit <Enter>."
at the end...
I want to build an escript that after running will not halt the Erlang VM just like:
elixir --no-halt -S mix run --eval 'MyApp.CLI.m
ain(["some-arg"])'
or
mix run --no-halt --eval 'MyApp.CLI.m
ain(["some-arg1,some-arg2"])'
Is there a way to do this with escript?
Or should I use a different solution to pack and distribute my program that is actually more like a server/daemon than a command line tool?
A typical approach to packaging such systems is an OTP release. You can use exrm for that.
If for some reasons, you still want to use escript, you can just call :timer.sleep(:infinity) after you start all the applications and processes.
NOTE: Starting from Elixir 1.9
We can use System.no_halt(true) to allow script to never stop.
Here is simple script example:
defmodule Mix.Tasks.NoHalt do
use Mix.Task
def run(_) do
System.no_halt(true)
IO.puts("Never die!")
end
end
I'm sure this will be so simple I will kick myself my asking but how do I pass erl args, like -config {file} to erl when calling rebar shell? I thought it would simply passthrough anything that didn't match it's own switches but not so.
rebar shell doesn't appear to allow arguments, but it's basically the equivalent of the following command line:
erl -pa deps/*/ebin -pa ebin
If your project has no dependencies, you don't need the -pa deps/*/ebin part.
If you need extra arguments, just add them to this command.
Another alternative is to use the ERL_FLAGS environment variable to specify extra arguments:
ERL_FLAGS='-config my_config_file.config' rebar shell
rebar3 supports this directly now:
rebar3 shell --config something.config, or
Add {shell, [{config, "something.config}]}. to your rebar.config
It's not elegant modify everytime your rebar.config but you can use the tuple {sys_config, FilePath}.
{sys_config, "config/sys.config"}.
When you run the command "rebar3 shell", they will load the configuration placed in "config/sys.config"
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.
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).