【问题标题】:Erlang and bash scripting (escript)Erlang 和 bash 脚本(escript)
【发布时间】:2020-09-12 12:47:06
【问题描述】:

我是 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 中运行上面的代码 sn-p。

【问题讨论】:

    标签: bash shell erlang erlang-shell escript


    【解决方案1】:

    当你使用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 的节点列表是空的)。

    除了他的escript没有运行任何有用的代码之外,这里还有三个问题:

    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 会随机创建一个并将其放在 $HOME 中。

    3
    与原始节点的网络连接:Erlang 分布式协议要求 4369 端口(用于EPMD)和节点范围(可用于配置inet_dist_listen_mininet_dist_listen_max)可达。

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

    【讨论】:

      猜你喜欢
      • 2011-09-01
      • 2017-05-30
      • 1970-01-01
      • 1970-01-01
      • 2011-01-20
      • 2013-02-02
      • 2019-06-14
      • 2011-06-27
      • 1970-01-01
      相关资源
      最近更新 更多