我是Erlang的新手,我想将bash脚本与Erlang节点和函数合并。我有一个Mnesia数据库,我们进入Erlang节点并运行几个函数,但我想通过一些bash脚本运行这些函数,这样我就可以在其他地方使用这些bash脚本输出。我的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> 在这个外壳中,当我们运行下面的函数时,它运行得很好,也给出了输出,请注意,order_node,pps_manager是数据库中的模块名,get_by_id,send_order_related_notification,update_status_of_order_node是该模块中的函数。
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().请告诉我如何使用bash脚本在erlang shell中运行上面的代码片段。
发布于 2020-05-27 04:18:33
当您使用escript时,您将启动一个新的Erlang VM,因此,如果您希望真正连接到正在运行的节点,则需要使用诸如expect之类的东西。
但是,使用escript,您可以启动一个新节点并将其添加到正在运行的集群中,并且借助rpc module中的方法,您可以在原始集群中运行代码:
假设您有一个以erl -name main@127.0.0.1 -setcookie cookie开头的节点,然后是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.将打印
$> ./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(): [](注意,由于-hidden flag,main的节点列表是空的)。
除了他的脚本没有运行任何有用的代码这一事实之外,这里还有三个问题:
1
escript节点名:由于erlang集群或同一主机中的名称必须是唯一的,如果escript有可能同时运行两次,这可能是一个问题。您可以通过生成一个随机名称(在Erlang或bash中,示例为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']但是,escript节点的名称是一个原子,原子没有GC,原子限制虽然很高,但仍然存在。这对您来说可能是问题,也可能不是问题,这取决于您的配置和使用模式。
2
原始节点名和cookie:要连接到main@127.0.0.1,您需要知道名称、是否以long or short names启动(如果主机部分有点,则需要长名称)和cookie。此信息在vm.args文件中(或在shell行中)。
如果没有设置cookie,Erlang会随机创建一个cookie并将其放入$HOME中。
3
与原始节点的网络连接: Erlang分布式协议需要4369端口(用于EPMD)和可到达的节点范围(可用于配置inet_dist_listen_min和inet_dist_listen_max)。
准备好脚本后,可以从bash脚本调用它,也可以在对其调用env escript之前从bash脚本将其写入临时文件(bash process substitution不起作用,因为脚本使用file:position,而进程替换是管道)。
https://stackoverflow.com/questions/62009886
复制相似问题