Erlang and bash scripting (escript)

倖福魔咒の 提交于 2020-08-07 18:21:31

问题


I am very new in Erlang and want to merge bash script with Erlang node and function. I have one Mnesia Database where we go into Erlang node and run several function but i want to run those functions via some bash script so that I can use those bash script output elsewhere. My Erlang shell:-

sudo /opt/butler_server/bin/butler_server remote_console
Erlang/OTP 20 [erts-9.3.3.6] [source] [64-bit] [smp:28:28] [ds:28:28:10] [async-threads:10] 

Eshell V9.3.3.6  (abort with ^G)
(butler_server@localhost)1> 

And inside this shell when we run below function its running fine and giving output also, Please note order_node, pps_manager are the module name in the Database and get_by_id,send_order_related_notification,update_status_of_order_node are the fuction in that module.

f().

ChangeStatus =
fun() ->
        {ok,C2}=order_node:search_by([{status,equal,inventory_awaited}],key),

        io:format("Total Orders ~p", [length(C2)]),

        lists:foreach(fun(Id) ->
                              io:format("Orders ~p~n", [Id]),
                              order_node:update_status_of_order_node(Id,cancelled),
                              pps_manager:send_order_related_notification(element(2,order_node:get_by_id(Id)))
                      end, C2)
end.

ChangeStatus().

Please let me know how i can run above code snippet in erlang shell by using a bash script.


回答1:


When you use escript, you start a new Erlang VM, so if you want to really connect to a running node, you need to use something like expect.

However, with escript you can start a new node and add it to a running cluster, and with the help of the methods in the rpc module you can run code in the original cluster:

Let's say that you have a node started with erl -name main@127.0.0.1 -setcookie cookie, then the escript

#!/usr/bin/env escript
%%! -name escript@127.0.0.1 -hidden -setcookie cookie
main([RemoteNodeString]) ->
    io:format("Escript node: ~p~n", [node()]),
    RemoteNode = list_to_atom(RemoteNodeString),
    io:format("~p's node(): ~p~n", [RemoteNode, rpc:call(RemoteNode, erlang, node, [])]),
    io:format("~p's nodes(): ~p~n", [RemoteNode, rpc:call(RemoteNode, erlang, nodes, [])]),
    ok.

will print

$> ./test.escript main@127.0.0.1
Escript node: 'escript@127.0.0.1'
'main@127.0.0.1''s node(): 'main@127.0.0.1'
'main@127.0.0.1''s nodes(): []

(Notice that main's nodes list is empty thanks to the -hidden flag).

Aside from the fact that his escript is not running any useful code, there are three issues here:

1
escript node name: As names in the erlang cluster or in the same host must be unique, this may be a problem if there's a chance that the escript is run twice concurrently. You can solve it by generating a random name (in Erlang or bash, the example is for Erlang):

#!/usr/bin/env escript
%%! -hidden -setcookie cookie
main([RemoteNodeString]) ->
    RandomTail = (<< <<($0 + rand:uniform(10)-1)>> || _ <- lists:seq(1,8) >>),
    RandomName = binary_to_atom(<<"escript", RandomTail/binary, "@127.0.0.1">>, utf8),
    io:format("Escript node: ~p~n", [RandomName]),
    net_kernel:start([RandomName, longnames]),
    RemoteNode = list_to_atom(RemoteNodeString),
    io:format("~p's node(): ~p~n", [RemoteNode, rpc:call(RemoteNode, erlang, node, [])]),
    io:format("~p's nodes(): ~p~n", [RemoteNode, rpc:call(RemoteNode, erlang, nodes, [])]),
    io:format("~p's nodes(hidden): ~p~n", [RemoteNode, rpc:call(RemoteNode, erlang, nodes, [hidden])]),
    ok.

$> ./test2.escript main@127.0.0.1 
Escript node: 'escript45560706@127.0.0.1'
'main@127.0.0.1''s node(): 'main@127.0.0.1'
'main@127.0.0.1''s nodes(): []
'main@127.0.0.1''s nodes(hidden): ['escript45560706@127.0.0.1']

However, the escript node's name is an atom, atoms are not GC'd and the atoms limit, although really high, is present. It may or may not be an issue for you depending on your configuration and your use pattern.

2
Original node name and cookie: To connect to main@127.0.0.1 you need to know the name, if it was started with long or short names (if the host part has a dot, you need longnames) and the cookie. This information is in the vm.args file (or in the shell line).
If no cookie was set, Erlang creates a random one and places it in the $HOME.

3
Network connection to the original node: Erlang distributed protocol requires the 4369 port (for EPMD) and a range for the nodes (avaliable for configuration with inet_dist_listen_min and inet_dist_listen_max) reachable.

Once you have the escript ready, you can call it from your bash script or you can write it to a tempfile from your bash script before calling env escript on it (bash process substitution does not work because escript uses file:position and the process substitution is a pipe).



来源:https://stackoverflow.com/questions/62009886/erlang-and-bash-scripting-escript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!