run erlang from unix shell with complex params

2019-02-07 13:01发布

问题:

i need run complex erlang module function from unix shell

rpc:call('node@example.com', mnesia, dirty_first, [mytable])

how can i do it?

UPD:

i make test.escript

chmod +x test.escript

#!/usr/lib64/erlang/bin/escript
%%! -name 'test@example.com'
main(_Args) ->
    R = rpc:call('node@example.com', mnesia, dirty_first, [mytable]),
    io:format("~p~n",[R]).

and receive {badrpc, nodedown}

but when run

erl -name test@example.com
1> rpc:call('node@example.com', mnesia, dirty_first, [mytable]).
{my, data}.

i mean it works, but howto make escript work proprely?

回答1:

I think escript might be something worth looking into.

Edit: Some examples.

First for all examples: Start the remote node somewhere, somehow.

            dannib@duval:~:> erl -sname bar
            (bar@duval)1> erlang:get_cookie().
            'KNKKCFPYMJUPIOLYPOAA'

Escript

1: Create a file named hello.escript with content

            #!/usr/bin/env escript
            %%! -sname foo@duval -setcookie KNKKCFPYMJUPIOLYPOAA

            main(_String) ->
                Node = 'bar@duval',
                Mod = 'erlang',
                Fun = 'node', 
                Args = [], 
                    R = rpc:call(Node, Mod, Fun, Args),
                io:format("Hello there ~p~n",[R]).

Notice that the %%! -sname foo@bar identifies the node on the host (instead of creating nonode@nohost), allow setting the same cookie %%! -sname foo@duvel -setcookie KNKKCFPYMJUPIOLYPOAA as target host which solves the problem of getting {badrpc,nodedown}. Notice that the same statement holds for the following examples (erl_call, and -eval) where both the node name and cookie is set.

2: Set the execution bit and run

            $ chmod +x hello.escript
            $ ./hello.escript 
            Hello there bar@duval

Erl_call

1: run

            $ erl_call -c 'KNKKCFPYMJUPIOLYPOAA' -a 'erlang node' -n bar@duval
            bar@duval

Eval

1: run

            $ erl -sname foo -setcookie 'KNKKCFPYMJUPIOLYPOAA' 
            -eval 'io:format("Hello there ~p~n",[rpc:call(bar@duval,erlang, node, [])])'
            ... Eshell V5.7.4  (abort with ^G)
            (foo@duval)1> Hello there bar@duval

This creates a shell which might not be what you want in this case.

I might mention that if both nodes are on the same host and using the same cookie default value, the cookie value for foo and bar don't have to be explicitly set like in the examples.

After doing these examples and reading your question again I think what I GIVE TERRIBLE ADVICE said will be your best choice, erl_call. I fell for the word "complex" in question title where imho escripts allow much more "complex" setups in a easy-to-read manner. The variable _String in the escript example holds the arguments to the script which allows you to both access input through shell and perform complex erlang operations in the EVM. But erl_call might be more straight forward if you already have logic in some other application and just need to make this simple call to an erlang node.



回答2:

The erl_call application is exactly what you need:

erl_call makes it possible to start and/or communicate with a distributed Erlang node. It is built upon the erl_interface library as an example application. Its purpose is to use an Unix shell script to interact with a distributed Erlang node. It performs all communication with the Erlang rex server, using the standard Erlang RPC facility. It does not require any special software to be run at the Erlang target node.

The main use is to either start a distributed Erlang node or to make an ordinary function call. However, it is also possible to pipe an Erlang module to erl_call and have it compiled, or to pipe a sequence of Erlang expressions to be evaluated (similar to the Erlang shell).

See the examples for more details



回答3:

You can use -eval flag of erl:

$ erl -eval 'io:format("Hello, World!~n")'


回答4:

You can parse complex arguments with escript:

#!/usr/bin/env escript

main(String) ->
  {Node, Mod, Fun, Args} = parse_args(String),
  R = rpc:call(Node, Mod, Fun, Args),
  io:format("~p~n",[R]).


回答5:

If your problem is how to set the Erlang node in network mode (i.e. turn the node into a distributed node), you might want to do something like

EPMD = code:root_dir() ++ "/bin/epmd &",
os:cmd(EPMD),
net_kernel:start([Sname, shortnames])

where Sname is your wanted node name. Only after this can you start communicating to another node with e.g. rpc.



标签: erlang