我对 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>
在这个 shell 中,当我们在下面运行时,它运行良好并给出输出,请注意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 中运行上面的代码片段。
当你使用escript 时,你会启动一个新的 Erlang VM,所以如果你想真正连接到一个正在运行的节点,你需要使用类似 expect 的东西。
但是,使用 escript,您可以启动一个新节点并将其添加到正在运行的集群中,并且在 rpc 模块中的方法的帮助下,您可以在原始集群中运行代码:
假设您有一个以erl -name main@127.0.0.1 -setcookie cookie
开头的节点,然后是
#!/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 标志,主节点列表为空(。
除了他的脚本没有运行任何有用的代码之外,这里还有三个问题:
1个
脚本节点名称:由于 erlang 群集或同一主机中的名称必须是唯一的,因此如果脚本有可能同时运行两次,这可能是一个问题。你可以通过生成一个随机名称来解决它(在 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']
但是,脚本节点的名称是一个原子,原子不是GC'd,并且原子限制虽然非常高,但存在。这对您来说可能是也可能不是问题,具体取决于您的配置和使用模式。
2
原始节点名称和 cookie:要连接到main@127.0.0.1
,您需要知道名称,如果它是以长名称或短名称开头的(如果主机部分有一个点,则需要长名称(和 cookie。此信息位于vm.args
文件(或外壳行(中。
如果没有设置 cookie,Erlang 会随机创建一个并将其放在$HOME
中。
3 与原始节点的网络连接:Erlang 分布式协议需要 4369 端口(用于 EPMD(和节点的范围(可用于inet_dist_listen_min
和inet_dist_listen_max
的配置(。
准备好 escript 后,您可以从 bash 脚本调用它,也可以在调用 bash 脚本之前将其写入临时文件env escript
(bash 进程替换不起作用,因为 escript 使用 file:position 并且进程替换是管道(。