Erlang Can';t启动erlag节点时启动进程

Erlang Can';t启动erlag节点时启动进程,erlang,Erlang,我试图启动一个主管和gen_服务器进程,当从命令行创建一个节点时,我使用以下命令启动该节点: erl -name vm01@192.168.146.129 -s ets_sup start vm02@192.168.146.129 calc 但是,当我在新创建的节点上使用whereis检查流程时,发现流程是undefined。直接在节点shell上运行ets_sup和ets_srv没有问题,但是从命令行启动节点不起作用。我想知道为什么会这样 ets_sup.erl: -module(ets_s

我试图启动一个主管和gen_服务器进程,当从命令行创建一个节点时,我使用以下命令启动该节点:

erl -name vm01@192.168.146.129 -s ets_sup start vm02@192.168.146.129 calc
但是,当我在新创建的节点上使用
whereis
检查流程时,发现流程是
undefined
。直接在节点shell上运行ets_sup和ets_srv没有问题,但是从命令行启动节点不起作用。我想知道为什么会这样

ets_sup.erl:

-module(ets_sup).
-behaviour(supervisor).
-export([start/1, start_link/1, init/1]).

start([A, B]) ->
        start_link([A, B]).


start_link([A, B]) ->
        supervisor:start_link({local, ?MODULE}, ?MODULE, [A, B]).

init([A, B]) ->
        {ok, {{one_for_all, 0, 1},
                [{ets_srv, {ets_srv, start_link, [A, B]}, permanent, 5000, worker, [ets_srv]}]}}.
ets_srv.erl:

-module(ets_srv).
-behaviour(gen_server).
-compile(export_all).

-record(state, {a, b}).

start_link(A,B) ->
        gen_server:start_link({local, ?MODULE}, ?MODULE, [A, B], []).

init([A, B]) ->
        {ok, #state{a = A, b = B}}.

check_sys() ->
        gen_server:call(?MODULE, check_sys).

handle_call(check_sys, _From, #state{a = A, b = B} = State) ->
        {reply, {A, B}, State}.

handle_info(_Info, State) -> {noreply, State}.

handle_cast(_Req, State) -> {noreply, State}.

code_change(_Ol, State, _Ex) -> {ok, State}.

terminate(_R, _S) -> ok.

我认为您确实可以使用参数列表启动函数
ets\u sup:start/1
。您可以通过在
ets\u sup:start\u链接/1
之前添加
io:format(…)
来验证它

但是执行函数
ets_sup:start/1
的进程是一个很早的进程,它很快就会因为原因
shutdown
而死亡,并且由于您的主管与它链接,它也会死亡,它的所有子进程也会死亡

您必须从不会消亡的进程调用此函数(通常,它是应用程序管理器的角色)。例如,请执行以下操作:

start([A, B]) ->
    % spawn a new process
    spawn(fun () -> 
               start_link([A, B]),
               % add a loop to keep it alive
               loop()
               end).


loop() ->
    receive
        stop -> ok;
        _ -> loop()
    end.
编辑,但不是答案

我已修改了您的代码:

  • 在初始化服务器中添加
    process\u标志(trap\u exit,true),
    ,以便捕获退出消息
  • 在服务器终止函数中添加
    io:format(“服务器终止原因~p,进程~p~n”,[\u R,self()]),
    ,以便打印主管最终发送的退出原因(注意:如果另一个进程发送退出消息,将触发句柄信息)
  • 添加
    ets\u srv:check\u sys()
这是修改后的代码

-module(ets_sup).
-behaviour(supervisor).
-export([start/1, start_link/1, init/1]).

start([A, B]) ->
    start_link([A, B]).


start_link([A, B]) ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, [A, B]),
    ets_srv:check_sys().

init([A, B]) ->
    {ok, {{one_for_all, 0, 1},
            [{ets_srv, {ets_srv, start_link, [A, B]}, permanent, 5000, worker, [ets_srv]}]}}.

-module(ets_srv).
-behaviour(gen_server).
-compile(export_all).

-record(state, {a, b}).

start_link(A,B) ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [A, B], []).

init([A, B]) ->
    process_flag(trap_exit, true),
    {ok, #state{a = A, b = B}}.

check_sys() ->
    gen_server:call(?MODULE, check_sys).

handle_call(check_sys, _From, #state{a = A, b = B} = State) ->
    io:format("check_sys state ~p, process ~p~n",[State,self()]),
    {reply, {A, B}, State}.

handle_info(_Info, State) ->
    {noreply, State}.

handle_cast(_Req, State) ->
    {noreply, State}.

code_change(_Ol, State, _Ex) ->
    {ok, State}.

terminate(_R, _S) ->
    io:format("server terminate with reason ~p, process ~p~n",[_R,self()]),
    ok.
运行此版本将显示主管正确启动服务器,然后向其发送关机消息。如果在shell中启动了监控器,则不会发生这种情况

C:\src>erl -s ets_sup start vm02@192.168.146.129 calc
check_sys state {state,'vm02@192.168.146.129',calc}, process <0.56.0>
server terminate with reason shutdown, process <0.56.0>
Eshell V8.2  (abort with ^G)
1> whereis(ets_srv).
undefined
2> ets_sup:start(['vm02@192.168.146.129',calc]).
check_sys state {state,'vm02@192.168.146.129',calc}, process <0.61.0>
{'vm02@192.168.146.129',calc}
3> whereis(ets_srv).
<0.61.0>
4> ets_srv:check_sys().
check_sys state {state,'vm02@192.168.146.129',calc}, process <0.61.0>
{'vm02@192.168.146.129',calc}
5> exit(whereis(ets_srv),shutdown).
true
6> whereis(ets_srv).
<0.61.0>
7> exit(whereis(ets_srv),kill).
** exception exit: shutdown
8> whereis(ets_srv).
undefined
9>
执行结果如下:

C:\src>erl -s st start vm02@192.168.146.129 calc
spawn from <0.3.0>
init with ['vm02@192.168.146.129',calc] in <0.55.0>
Eshell V8.2  (abort with ^G)
1> whereis(st).
<0.55.0>
2> exit(whereis(st),shutdown).
true
3> whereis(st).
<0.55.0>
4> st ! state.
state is ['vm02@192.168.146.129',calc]
state
5> st ! stop.
stopping
loop received {'DOWN',#Ref<0.0.4.66>,process,<0.55.0>,normal}
stop
6> whereis(st).
undefined
7>
现在它可以工作了:

C:\src>erl -s ets_sup start vm02@192.168.146.129 calc
check_sys state {state,'vm02@192.168.146.129',calc}, process <0.56.0>
Eshell V8.2  (abort with ^G)
1> ets_srv:check_sys().
check_sys state {state,'vm02@192.168.146.129',calc}, process <0.56.0>
{'vm02@192.168.146.129',calc}
2>
C:\src>erl-s ets\u sup启动vm02@192.168.146.129计算
检查系统状态{state,'vm02@192.168.146.129“,calc},进程
Eshell V8.2(使用^G中止)
1> ets\U srv:检查系统()。
检查系统状态{state,'vm02@192.168.146.129“,calc},进程
{'vm02@192.168.146.129“,calc}
2>
-module(ets_sup).
-behaviour(supervisor).
-export([start/1, start_link/1, init/1]).

start([A, B]) ->
    start_link([A, B]).


start_link([A, B]) ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, [A, B]),
    ets_srv:check_sys().

init([A, B]) ->
    {links,[Parent]} = process_info(self(),links),
    unlink(Parent),
    {ok, {{one_for_all, 0, 1},
            [{ets_srv, {ets_srv, start_link, [A, B]}, permanent, 5000, worker, [ets_srv]}]}}.
C:\src>erl -s ets_sup start vm02@192.168.146.129 calc
check_sys state {state,'vm02@192.168.146.129',calc}, process <0.56.0>
Eshell V8.2  (abort with ^G)
1> ets_srv:check_sys().
check_sys state {state,'vm02@192.168.146.129',calc}, process <0.56.0>
{'vm02@192.168.146.129',calc}
2>