当你使用 escript 时,你启动了一个新的 Erlang VM,所以如果你想真正连接到一个正在运行的节点,你需要使用类似expect的东西。
但是,您可以使用 escript 启动一个新节点并将其添加到正在运行的集群中,并且借助rpc 模块中的方法,您可以在原始集群中运行代码:
假设您有一个以 开头的节点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 标志,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
您需要知道名称,是否以长名称或短名称开头(如果主机部分有一个点,您需要长名称)和cookie。此信息在vm.args
文件中(或在 shell 行中)。
如果没有设置 cookie,Erlang 会创建一个随机的 cookie 并将其放在$HOME
.
3
与原始节点的网络连接:Erlang 分布式协议要求 4369 端口(用于EPMD)和节点范围(可用于配置inet_dist_listen_min
和inet_dist_listen_max
)可达。
准备好 escript 后,您可以从 bash 脚本调用它,也可以在调用它之前从 bash 脚本将其写入临时文件env escript
(bash 进程替换不起作用,因为 escript 使用file:position并且进程替换是管道)。