我准备开发一个心跳节目,需要每5秒发送一次udp数据包。
如何在erlang中睡5s或者是否有睡眠(5)功能?
如何让它在后台运行?
答案 0 :(得分:6)
如果您希望您的应用程序发送udp数据包,我建议您从gen_server开始(因为您显然需要在应用程序中添加其他功能)。
1.定期发送数据包。
timer:send_interval(5000,interval),
这将调用gen_server的“handle_call(interval,State)”回调,每隔5秒发送一次数据包
2.让它在后台运行。
已经发布使用“run_erl”。我自己使用它作为守护进程成功运行我的应用程序。
run_erl -daemon /tmp "erl"
这将在unix的“/ tmp”目录下创建两个管道“erlang.pipe.1.r”和“erlang.pipe.1.w”,您可以编写命令来编写管道,以便使用perl或任何脚本来启动应用程序甚至是c / c ++ :)
答案 1 :(得分:4)
最近我一直在学习erlang编程语言。我给自己的一个任务就是编写一个linux守护进程。
您可能已经知道,守护进程用于运行unix服务。通常由守护进程控制的服务包括数据库服务器,Web服务器,Web代理等。在此示例中,服务器非常简单,客户端调用函数“say_hi”,服务器以“hello”响应。
在linux环境中,守护进程由存储在/etc/init.d等位置的脚本控制。这些脚本根据约定响应命令start,stop和restart。
让我们从shell脚本开始:
#!/bin/sh
EBIN=$HOME/Documents/Erlang/Daemon
ERL=/usr/bin/erl
case $1 in
start|stop|restart)
$ERL -detached -sname mynode \
-run daemon shell_do $1 >> daemon2.log
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0
这必须是您见过的最简单的shell脚本之一。守护进程响应三个不同的命令,停止,启动和重启。在此脚本中,命令只是传递给守护程序。一个改进是退出守护程序执行的返回代码。
守护进程怎么样?这是......
%% PURPOSE
%% Author: Tony Wallace
%%
%% Manage an erlang daemon process as controlled by a shell scripts
%% Allow standard daemon control verbs
%% Start - Starts a daemon in detached mode and exits
%% Stop - Attaches to the daemon, monitors it, sends an EXIT message and waits for it to die
%% Restart - Calls stop and then start
%% Log events
%% Return UNIX compatible codes for functions called from shell scripts
%% Exit shell script calls so as to not stop the scripts from completing
%% Shell scripts expected to use shell_do to execute functions
%%
%% Allow interaction with daemon from other erlang nodes.
%% Erlang processes are expected to call functions directly rather than through shell_do
%%
%% MOTIVATION
%% Erlang is great, but as an application it needs to be managed by system scripts.
%% This is particularly for process that are expected to be running without user initiation.
%%
%% INVOCATION
%% See daemon.sh for details of calling this module from a shell script.
%%
%% TO DO
%% Define and use error handler for spawn call.
-module(daemon).
%-compile([{debug_info}]).
-export [start/0,start/1,stop_daemon/0,say_hi/0,kill/0,shell_do/1].
%%-define (DAEMON_NAME,daemon@blessing).
-define (DAEMON_NAME,list_to_atom("daemon@"++net_adm:localhost())).
-define (UNIX_OKAY_RESULT,0).
-define (TIMEOUT_STARTING_VM,1).
-define (VM_STARTED_WITHOUT_NAME,2).
-define (INVALID_VERB,3).
-define (COULD_NOT_CONNECT,4).
-define (TIMEOUT_WAITING_QUIT,5).
-define (TIMEOUT_STOPPING_VM,6).
wait_vm_start(_,0) -> ?TIMEOUT_STARTING_VM;
wait_vm_start(D,N) ->
net_kernel:connect(D),
Dl = lists:filter(fun(X) -> X==D end,nodes()),
if Dl =:= [] ->
receive after 1000 -> true end,
wait_vm_start(D,N-1);
Dl /= [] -> ?UNIX_OKAY_RESULT
end.
wait_vm_stop(_,0) -> ?TIMEOUT_STOPPING_VM;
wait_vm_stop(D,N) ->
net_kernel:connect(D),
Dl = lists:filter(fun(X) -> X==D end,nodes()),
if Dl /= [] ->
receive after 1000 -> true end,
wait_vm_start(D,N-1);
Dl == [] -> ?UNIX_OKAY_RESULT
end.
flush() ->
receive
_ ->
flush()
after
0 ->
true
end.
sd(Hdl) ->
MyNode=node(),
if
MyNode =:= nonode@nohost ->
info(stdout,"~s","Error: Erlang not started with a name. Use -sname <name>"),
?VM_STARTED_WITHOUT_NAME;
MyNode /= nonode@nohost ->
Atm_daemon = ?DAEMON_NAME,
Connected = net_kernel:connect(Atm_daemon),
case Connected of
true ->
info(Hdl,"~s",["daemon process already started"]),
?UNIX_OKAY_RESULT;
false ->
info(Hdl,"~s",["starting daemon process"]),
StartString = "erl -detached -sname daemon",
os:cmd(StartString),
Vm_daemon = wait_vm_start(Atm_daemon,10),
case Vm_daemon of
?UNIX_OKAY_RESULT ->
info(Hdl,"~s",["spawning main daemon process"]),
spawn(Atm_daemon,?MODULE,start,[]), ?UNIX_OKAY_RESULT;
A -> A
end
end % case Connected %
end.
say_hi() ->
Daemon = ?DAEMON_NAME,
Connected = net_kernel:connect(Daemon),
if Connected ->
{listener,Daemon} ! {hello,self()},
receive
Response -> Response
after 10000 -> timeout end;
not Connected -> could_not_connect
end.
stop_daemon() ->
Daemon = ?DAEMON_NAME,
Connected = net_kernel:connect(Daemon),
if Connected ->
flush(),
{listener,Daemon} ! {quit,self()},
receive
bye -> wait_vm_stop(Daemon,10)
after 10000 -> ?TIMEOUT_WAITING_QUIT
end;
not Connected -> ?COULD_NOT_CONNECT
end.
shell_do(Verb) ->
{A,Hdl} = file:open('daemon_client.log',[append]),
case A of
ok ->
info(Hdl,"~s",[Verb]);
error -> error
end,
Result = handle_verb(Hdl,Verb),
info(Hdl,"Return status ~.10B",[Result]),
init:stop(Result).
%%handle_verb(_,_) -> 0;
handle_verb(Hdl,["start"]) -> sd(Hdl);
handle_verb(_,["stop"]) -> stop_daemon();
handle_verb(Hdl,["restart"]) ->
stop_daemon(),
sd(Hdl);
handle_verb(Hdl,X) ->
info(Hdl,"handle_verb failed to match ~p",[X]),
?INVALID_VERB.
kill() ->
rpc:call(?DAEMON_NAME, init, stop, []).
start(Source) ->
Source ! starting,
start().
start() ->
register(listener,self()),
case {_,Hdl}=file:open("daemon_server.log",[append]) of
{ok,Hdl} -> server(Hdl);
{error,Hdl} -> {error,Hdl}
end.
info(Hdl,Fmt,D)->
io:fwrite(Hdl,"~w"++Fmt++"~n",[erlang:localtime()] ++ D).
server(Hdl) ->
info(Hdl,"~s",["waiting"]),
receive
{hello,Sender} ->
info(Hdl,"~s~w",["hello received from",Sender]),
Sender ! hello,
server(Hdl);
{getpid,Sender} ->
info(Hdl,"~s~w",["pid request from ",Sender]),
Sender ! self(),
server(Hdl);
{quit,Sender} ->
info(Hdl,"~s~w",["quit recevied from ",Sender]),
Sender ! bye,
init:stop();
_ ->
info(Hdl,"~s",["Unknown message received"])
after
50000 ->
server(Hdl)
end.
对于不习惯读取erlang的读者,有些代码是由我们上面看到的shell脚本运行的。此文件中的其他代码是守护程序本身。回到shell脚本,我们看到脚本调用过程shell_do。 Shell_do写入日志条目,调用handle_verb并退出。 Handle_verb为每个动词实现不同的行为。启动守护进程由函数sd处理,函数sd通过操作系统调用os:cmd创建守护进程,等待erlang虚拟机初始化,然后生成名为start的服务器代码,该代码又调用服务器。
答案 2 :(得分:3)
通过计时器功能在erlang中可以使用睡眠。
http://www.erlang.org/doc/man/timer.html
对于后台进程,您可以使用-detached
cli参数。
您可以使用-s
修改强>
您还可以spawn
主程序中的新进程:
答案 3 :(得分:3)
关于守护进程,请考虑使用OTP附带的run_erl实用程序启动erlang程序。请特别注意-daemon
命令行标志。