2011-05-12 84 views
-3

我准备开发一个心跳程序,它需要每5秒发送一次udp数据包。如何用erlang创建守护程序?

  1. 如何在erlang中睡5s或是否有睡眠(5)要使用的功能?

  2. 如何让它在后台运行?

+0

尽我们最大的尊重,请在提出这样的基本问题(关于睡眠)之前努力搜索Erlang文档。 – 2011-05-12 06:53:48

回答

6

如果你想让你的应用程序发送一个udp数据包,我会建议你从一个gen_server开始(因为你显然需要为你的应用程序添加其他功能)。

1.用于定期发送数据包。

 
timer:send_interval(5000,interval), 

这将调用 “handle_call(间隔状态)” gen_server回调从那里你可以把你的包

2.使得它在后台运行每5秒。

已发布使用“run_erl”。我自己用这个来成功地作为一个守护进程运行我的应用程序。

 
run_erl -daemon /tmp "erl" 

这将创建两个管道UNIX的“erlang.pipe.1.r”和“erlang.pipe.1.w”下的“/ tmp目录”目录,你可以写来写管道启动命令你用perl或任何脚本郎甚至C应用程序/ C++ :)

3

睡眠通过计时器功能在erlang中可用。

http://www.erlang.org/doc/man/timer.html

对于后台进程,您可以使用-detached CLI说法。 您可以-s

编辑指定的入口点

您还可以spawn从你的主程序的新工艺:

http://www.erlang.org/doc/reference_manual/processes.html

+0

你的意思是我可以通过-s在“erl”shell中运行我的程序? – why 2011-05-12 03:04:06

+0

不,我的意思是用erl来运行你的程序。换一种方法,请参阅编辑。 – Macmade 2011-05-12 03:11:54

3

对于daemonizing,考虑开始你的二郎山使用OTP附带的run_erl实用程序编程。特别注意-daemon命令行标志。

4

最近我一直在学习Erlang编程语言。我给自己的一个任务是编写一个linux守护进程。

正如您可能已经知道的那样,守护进程用于运行unix服务。通常由守护进程控制的服务包括数据库服务器,Web服务器,Web代理等。在此示例中,服务器非常简单,客户端调用函数“say_hi”,服务器以“hello”响应。

在linux环境中,守护进程由存储在诸如/etc/init.d等地方的脚本控制。这些脚本按照惯例对命令启动,停止和重新启动进行响应。

让我们从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,[email protected]). 
-define (DAEMON_NAME,list_to_atom("[email protected]"++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 =:= [email protected] -> 
     info(stdout,"~s","Error: Erlang not started with a name. Use -sname <name>"), 
     ?VM_STARTED_WITHOUT_NAME; 
     MyNode /= [email protected] -> 
     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处理,该函数通过操作系统调用os:cmd创建守护进程,等待erlang虚拟机初始化,然后生成名为start的服务器代码,然后调用服务器。

相关问题