2011-05-12 141 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的服務器代碼,然後調用服務器。

相關問題