erlang otp童工

erlang otp童工,erlang,otp,Erlang,Otp,我正试图让OTP主管启动童工(最终)连接到远程服务器。我使用钢筋创建了一个模板测试应用程序,并试图让主管在模块“foo”中启动函数“hi”。它编译OK并运行: Eshell V5.8.5 (abort with ^G) 1> test_app:start(1,1). {ok,<0.34.0>} 问题似乎与这个问题相似,但并不相同: 有什么想法吗 测试应用程序erl -module(test_app). -behaviour(application).net -export

我正试图让OTP主管启动童工(最终)连接到远程服务器。我使用钢筋创建了一个模板测试应用程序,并试图让主管在模块“foo”中启动函数“hi”。它编译OK并运行:

Eshell V5.8.5  (abort with ^G)
1> test_app:start(1,1).
{ok,<0.34.0>}
问题似乎与这个问题相似,但并不相同:

有什么想法吗

测试应用程序erl

-module(test_app).
-behaviour(application).net 
-export([start/2, stop/1]).

start(_StartType, _StartArgs) ->
    test_sup:start_link().

stop(_State) ->
    ok.
测试辅助设备:

-module(test_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1, start_foo/0]).
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).

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

init([]) ->
    {ok, { {one_for_one, 5, 10}, []} }.
start_foo()->
    supervisor:check_childspecs(?CHILD(foo, worker)),
    supervisor:start_child(?MODULE, ?CHILD(foo, permanent)). 
foo.erl:

-module(foo).
-export([hi/0]).
hi()->
io:format("worker ~n").

使用宏调用
?CHILD(foo,worker)
检查childspec,同时尝试使用宏调用
?CHILD(foo,permanent)
启动子级。
CHILD
宏的第二个参数是进程类型,它应该是
worker
supervisor
。因此,第一个宏调用是正确的。值
permanent
是重启类型的值,您已经将其设置为
permanent
,因此第二次调用错误,您会得到一个
badarg
错误


注意:库函数也会生成
badarg
错误,而不仅仅是来自内置函数。为什么它是一个badarg并不总是显而易见的。

您使用宏调用
?CHILD(foo,worker)
检查childspec,同时尝试使用宏调用
?CHILD(foo,permanent)
启动子级。
CHILD
宏的第二个参数是进程类型,它应该是
worker
supervisor
。因此,第一个宏调用是正确的。值
permanent
是重启类型的值,您已经将其设置为
permanent
,因此第二次调用错误,您会得到一个
badarg
错误


注意:库函数也会生成
badarg
错误,而不仅仅是来自内置函数。为什么这是一个错误并不总是显而易见的。

我认为Robert的回答是不完整的,在用worker替换了permanent之后,您仍然有一个由
主管返回的错误:检查儿童规格(?CHILD(foo,worker)),
,我不知道为什么

[编辑]

bard arg的问题来自。。。巴达格:o)

check_childspecs extepect一个child_specs列表,正确的语法是
supervisor:check_childspecs([?child(foo,worker)]),
然后它就可以正常工作了。以下代码已更新

[编辑结束]

但是您也会得到一个错误,因为主管将尝试启动foo模块中不存在的函数foo:start\u链接。 以下代码打印错误,但似乎工作正常

-module(foo).
-export([hi/0,start_link/0,loop/0]).

start_link() ->
    {ok,spawn_link(?MODULE,loop,[])}.

hi()->
io:format("worker ~n").

loop() ->
    receive
        _ -> ok
    end.


-module(test_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1, start_foo/0]).
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).

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

init([]) ->
    {ok, { {one_for_one, 5, 10}, []} }.
start_foo()->
    io:format("~p~n",[supervisor:check_childspecs([?CHILD(foo, worker)])]),
    supervisor:start_child(?MODULE, ?CHILD(foo, worker)). 
[编辑]

回答大卫的评论

在我的代码中,
loop/0
根本不循环,在接收块上,进程等待任何消息,一旦接收到一条消息,进程就结束并返回值ok。因此,只要工作进程没有收到任何消息,它就会继续存在,这在您与主管进行一些测试时是很好的:o)

相反,hi/0函数只是在控制台上打印“worker”并完成。由于监管者的重启策略是一对一,最大重启为5,子进程是永久性的,监管者将尝试启动hi进程5次,在控制台上打印5次“worker”,然后它将放弃并终止,并显示错误消息
**异常错误:shutdown


通常,对于永不结束的进程(例如,应用程序的主服务器),您应该选择
永久
。对于通常在完成工作后立即终止的进程,您应该使用
临时
。我从未使用过瞬态,但我读到它应该用于必须在临终前完成任务的流程。

我认为Robert的回答是不完整的,在用worker替换了permanent之后,
主管仍然返回了一个错误:check_childspecs(?CHILD(foo,worker)),
,我不知道为什么

[编辑]

bard arg的问题来自。。。巴达格:o)

check_childspecs extepect一个child_specs列表,正确的语法是
supervisor:check_childspecs([?child(foo,worker)]),
然后它就可以正常工作了。以下代码已更新

[编辑结束]

但是您也会得到一个错误,因为主管将尝试启动foo模块中不存在的函数foo:start\u链接。 以下代码打印错误,但似乎工作正常

-module(foo).
-export([hi/0,start_link/0,loop/0]).

start_link() ->
    {ok,spawn_link(?MODULE,loop,[])}.

hi()->
io:format("worker ~n").

loop() ->
    receive
        _ -> ok
    end.


-module(test_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1, start_foo/0]).
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).

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

init([]) ->
    {ok, { {one_for_one, 5, 10}, []} }.
start_foo()->
    io:format("~p~n",[supervisor:check_childspecs([?CHILD(foo, worker)])]),
    supervisor:start_child(?MODULE, ?CHILD(foo, worker)). 
[编辑]

回答大卫的评论

在我的代码中,
loop/0
根本不循环,在接收块上,进程等待任何消息,一旦接收到一条消息,进程就结束并返回值ok。因此,只要工作进程没有收到任何消息,它就会继续存在,这在您与主管进行一些测试时是很好的:o)

相反,hi/0函数只是在控制台上打印“worker”并完成。由于监管者的重启策略是一对一,最大重启为5,子进程是永久性的,监管者将尝试启动hi进程5次,在控制台上打印5次“worker”,然后它将放弃并终止,并显示错误消息
**异常错误:shutdown


通常,对于永不结束的进程(例如,应用程序的主服务器),您应该选择
永久
。对于通常在完成工作后立即终止的进程,您应该使用
临时
。我从未使用过瞬态,但我读到它应该用于必须在临终前完成任务的过程。

谢谢罗伯特,这是午夜编码,当你指出它时很明显。(爱你在Erlang播客上的表现,顺便说一句,鼓舞人心)谢谢Robert,这是午夜编码,显然是在y