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