无法在erlang节点

时间:2017-04-29 14:05:05

标签: erlang

我有两个erlang节点,node01是'vm01@192.168.146.128',node02是'vm02@192.168.146.128'。我想在node02上使用spawn(Node, Mod, Fun, Args)在node01上启动一个进程,但我总是得到无用的pid。

节点连接正常:

(vm02@192.168.146.128)14> net_adm:ping('vm01@192.168.146.128').
pong

模块位于node01和node02:

的路径中
(vm01@192.168.146.128)7> m(remote_process).
Module: remote_process
MD5: 99784aa56b4feb2f5feed49314940e50
Compiled: No compile time info available
Object file: /src/remote_process.beam
Compiler options:  []
Exports: 
         init/1
         module_info/0
         module_info/1
         start/0
ok
(vm02@192.168.146.128)20> m(remote_process).
Module: remote_process
MD5: 99784aa56b4feb2f5feed49314940e50
Compiled: No compile time info available
Object file: /src/remote_process.beam
Compiler options:  []
Exports: 
         init/1
         module_info/0
         module_info/1
         start/0
ok

然而,产卵不成功:

(vm02@192.168.146.128)21> spawn('vm01@192.168.146.128', remote_process, start, []). 
I'm on node 'vm01@192.168.146.128'
<9981.89.0>
My pid is <9981.90.0>

(vm01@192.168.146.128)8> whereis(remote_process).
undefined

该过程能够在本地节点上运行:

(vm02@192.168.146.128)18> remote_process:start().
I'm on node 'vm02@192.168.146.128'
My pid is <0.108.0>
{ok,<0.108.0>}

(vm02@192.168.146.128)24> whereis(remote_process).
<0.115.0>

但它在远程节点上失败了。谁能给我一些想法?

这是源代码remote_process.erl:

-module(remote_process).
-behaviour(supervisor).
-export([start/0, init/1]).

start() ->
    {ok, Pid} = supervisor:start_link({global, ?MODULE}, ?MODULE, []),
    {ok, Pid}.

init([]) ->
    io:format("I'm on node ~p~n", [node()]),
    io:format("My pid is ~p~n", [self()]),
    {ok, {{one_for_one, 1, 5}, []}}.

1 个答案:

答案 0 :(得分:2)

您正在为您的流程使用全局注册,这是您的目的所必需的。检索它的函数是global:whereis_name(remote_process)

编辑:如果

,则有效
  • 连接2个节点(用nodes()检查)
  • 该流程已在全局模块中注册
  • 这个过程还活着

如果不满足任何这些条件,您将获得undefined

enter image description here

编辑2:使用:werl -sname p1启动节点1并输入shell:

(p1@W7FRR00423L)1> c(remote_process).
{ok,remote_process}
(p1@W7FRR00423L)2> remote_process:start().
I'm on node p1@W7FRR00423L
My pid is <0.69.0>
{ok,<0.69.0>}
(p1@W7FRR00423L)3> global:whereis_name(remote_process).
<0.69.0>
(p1@W7FRR00423L)4> 

然后用werl - sname p2启动第二个节点并输入shell(稍后可以连接第二个节点,全局注册是&#34;更新&#34;必要时):

(p2@W7FRR00423L)1> net_kernel:connect_node(p1@W7FRR00423L).
true
(p2@W7FRR00423L)2> nodes().
[p1@W7FRR00423L]
(p2@W7FRR00423L)3> global:whereis_name(remote_process).
<7080.69.0>
(p2@W7FRR00423L)4> 
(p2@W7FRR00423L)4>

编辑3:

在测试中,您将在远程节点上生成一个进程P1,该进程执行函数remote_process:start/0

此函数调用supervisor:start_link/3,它基本上产生一个新的管理程序进程P2并将其自身链接到它。在此之后,P1无所事事,因此它会死亡,导致关联的流程P2也会死亡,并且您会收到undefined来回global:whereis_name的回复。

在我的测试中,我从远程节点的shell启动进程;在评估remote_process:start/0之后,shell不会消失,因此主管进程不会死亡,global:whereis_name会找到请求的pid。

如果您希望主管在通话中生存,您需要一个不带链接的中间过程,因此它不会因其父级而死亡。我根据你的代码给你一个小例子:

-module(remote_process).
-behaviour(supervisor).
-export([start/0, init/1,local_spawn/0,remote_start/1]).

remote_start(Node) ->
    spawn(Node,?MODULE,local_spawn,[]).

local_spawn() ->
    % spawn without link so start_wait_stop will survive to
    % the death of local_spawn process
    spawn(fun start_wait_stop/0).

start_wait_stop() ->
    start(),
    receive
        stop -> ok
    end.

start() ->
    io:format("start (~p)~n",[self()]),
    {ok, Pid} = supervisor:start_link({global, ?MODULE}, ?MODULE, []),
    {ok, Pid}.

init([]) ->
    io:format("I'm on node ~p~n", [node()]),
    io:format("My pid is ~p~n", [self()]),
    {ok, {{one_for_one, 1, 5}, []}}.

在节点1中的shell中

(p1@W7FRR00423L)1> net_kernel:connect_node(p2@W7FRR00423L).
true
(p1@W7FRR00423L)2> c(remote_process).
{ok,remote_process}
(p1@W7FRR00423L)3> global:whereis_name(remote_process).
undefined
(p1@W7FRR00423L)4> remote_process:remote_start(p2@W7FRR00423L).
<7080.68.0>
start (<7080.69.0>)
I'm on node p2@W7FRR00423L
My pid is <7080.70.0>
(p1@W7FRR00423L)5> global:whereis_name(remote_process).        
<7080.70.0>
(p1@W7FRR00423L)6> global:whereis_name(remote_process).
undefined

和节点2

(p2@W7FRR00423L)1> global:registered_names(). % before step 4
[]
(p2@W7FRR00423L)2> global:registered_names(). % after step 4
[remote_process]
(p2@W7FRR00423L)3> rp(processes()).
[<0.0.0>,<0.1.0>,<0.4.0>,<0.30.0>,<0.31.0>,<0.33.0>,
 <0.34.0>,<0.35.0>,<0.36.0>,<0.37.0>,<0.38.0>,<0.39.0>,
 <0.40.0>,<0.41.0>,<0.42.0>,<0.43.0>,<0.44.0>,<0.45.0>,
 <0.46.0>,<0.47.0>,<0.48.0>,<0.49.0>,<0.50.0>,<0.51.0>,
 <0.52.0>,<0.53.0>,<0.54.0>,<0.55.0>,<0.56.0>,<0.57.0>,
 <0.58.0>,<0.62.0>,<0.64.0>,<0.69.0>,<0.70.0>]
ok
(p2@W7FRR00423L)4> pid(0,69,0) ! stop. % between steps 5 and 6
stop
(p2@W7FRR00423L)5> global:registered_names().
[]