首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Erlang和bash脚本(escript)

Erlang和bash脚本(escript)
EN

Stack Overflow用户
提问于 2020-05-26 04:02:23
回答 1查看 427关注 0票数 4

我是Erlang的新手,我想将bash脚本与Erlang节点和函数合并。我有一个Mnesia数据库,我们进入Erlang节点并运行几个函数,但我想通过一些bash脚本运行这些函数,这样我就可以在其他地方使用这些bash脚本输出。我的Erlang shell:

代码语言:javascript
复制
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是该模块中的函数。

代码语言:javascript
复制
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中运行上面的代码片段。

EN

回答 1

Stack Overflow用户

发布于 2020-05-27 04:18:33

当您使用escript时,您将启动一个新的Erlang VM,因此,如果您希望真正连接到正在运行的节点,则需要使用诸如expect之类的东西。

但是,使用escript,您可以启动一个新节点并将其添加到正在运行的集群中,并且借助rpc module中的方法,您可以在原始集群中运行代码:

假设您有一个以erl -name main@127.0.0.1 -setcookie cookie开头的节点,然后是escript

代码语言:javascript
复制
#!/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.

将打印

代码语言:javascript
复制
$> ./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)来解决此问题:

代码语言:javascript
复制
#!/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.
代码语言:javascript
复制
$> ./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_mininet_dist_listen_max)。

准备好脚本后,可以从bash脚本调用它,也可以在对其调用env escript之前从bash脚本将其写入临时文件(bash process substitution不起作用,因为脚本使用file:position,而进程替换是管道)。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62009886

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档