perlでデーモンを作成することになりそうなので、
調べてみると、次のurlで Proc::Daemon が紹介されていたので、試しに書いてみました。
http://perltips.twinkle.cc/perl/daemon.php
http://perltips.twinkle.cc/server/linux_daemon_startup_init_d.php
とりあえず、動作しているけど、どうなのかな?
#!/usr/local/bin/perl use strict; use utf8; use FindBin; use File::Spec; use lib File::Spec->catdir($FindBin::Bin, '../lib'); use Proc::Daemon; use Sing::DBI; use Sing::Model::User; use Data::Dumper; my $WORK_DIR = $FindBin::Bin; my $PID_FILE = 'send_daemon.pid'; my $SLEEP_INTERVAL = 3; my $DAEMON; main(@ARGV); exit(0); sub main { my ($action) = @_; $DAEMON = Proc::Daemon->new(work_dir=> $WORK_DIR,pid_file=> $PID_FILE); $action ||=""; if ($action eq "start"){ #daemonの起動 #複数の起動はできません my ($pid_path,$pid) = get_pid_file(); if( -e $pid_path ){ print "$0 is already running. LOCK_FILE=$pid_path PID=$pid\n"; exit(1); } init(); run(); return; } if ($action eq "stop"){ #daemonの停止 unless( get_pid_file() ){ print "$0 is not running\n"; exit(1); } #action()の処理の途中でkillするのは怖いので #pid fileを削除することで間接的?にkillします del_pid_file(); return; } print "usage: $0 [start|stop]\n"; return; } sub init { Proc::Daemon::Init( {work_dir=> $WORK_DIR,pid_file=> $PID_FILE}); #signal送信時に実行するmethod $SIG{INT} = $SIG{HUP} = $SIG{QUIT} = $SIG{KILL} = $SIG{TERM} ='interrupt'; } sub interrupt { #signal送信時に実行されます my ($sig) = @_; $SIG{$sig} = 'IGNORE'; return del_pid_file(); } sub run { while(1) { action(); #actionの内容は、自由に編集してください sleep($SLEEP_INTERVAL); #pidファイルが削除されていれば、自分自身をkillします my ($pid_path,$pid) = get_pid_file(); if (not $pid_path ){ $DAEMON->Kill_Daemon(); return; } } } #ここに好きな処理を書いて下さい sub action { } sub get_pid_file { #pid fileの名称とpidの取得 my $pid_file_path = join('/',$WORK_DIR,$PID_FILE); return undef if not -e $pid_file_path; open(my $fh, $pid_file_path) or die "can't open $pid_file_path :$!"; my ($line) = <$fh>; close $fh or die "can't close $pid_file_path :$!"; my ($pid) = $line =~ /(\d+)/o; return ($pid_file_path,$pid); } sub del_pid_file { my $pid_file_path = join('/',$WORK_DIR,$PID_FILE); unlink $pid_file_path or die "can't unlink $pid_file_path :$!"; print "deleted $pid_file_path. daemon stop soon...\n"; } 1; __END__
参考までに、使用可能なシグナル名は、$Config{sig_name} で表示
使用可能なシグナル名は環境によって異なると思いますが、
使用可能なシグナル名は$Config{sig_name}で一覧表示できます。
#!/usr/local/bin/perl use strict; use warnings; use utf8; use Config; print $Config{sig_name},"\n";
実行結果
[endo@colinux tmp]$ ./foo.pl ZERO HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS NUM32 NUM33 RTMIN NUM35 NUM36 NUM37 NUM38 NUM39 NUM40 NUM41 NUM42 NUM43 NUM44 NUM45 NUM46 NUM47 NUM48 NUM49 NUM50 NUM51 NUM52 NUM53 NUM54 NUM55 NUM56 NUM57 NUM58 NUM59 NUM60 NUM61 NUM62 NUM63 RTMAX IOT CLD POLL UNUSED [endo@colinux tmp]$
gihyo.jpのPerl Hackers Hubも参考になるかも?
※2011/4/26追記
次のurlにあるPerl Hackers Hubでは、「第6回 UNIXプログラミングの勘所(3)」として
シグナル制御が記載されていました。
http://gihyo.jp/dev/serial/01/perl-hackers-hub/000603
シグナル名もよく忘れるので、機会があれば、読み返すつもりです
シグナル名 | 意味 |
---|---|
SIGHUP | 主に設定ファイルの再読み込みを要求するために使用 |
SIGINT | 割り込みを要求(Ctrl-Cが押された場合など) |
SIGKILL | プロセスを強制終了 |
SIGPIPE | 閉じられたパイプやソケットに書き込もうとした |
SIGALRM | alarmで設定した時間が経過 |
SIGTERM | プロセスの終了を要請 |
SIGCHLD | 子プロセスが終了 |
KILLシグナルは、IGNOREでトラップできません
すぐ忘れるのでメモ
KILL シグナルや STOP シグナル(TSTP ではない)のような幾つかのシグナルは、 トラップすることも無視することもできません。
http://perldoc.jp/docs/perl/5.8.8/perlipc.pod
apacheを使ったdaemon化
http://www.usupi.org/sysad/094.html
↑このurlで紹介されていますが、次のような方法もあるようです。
CustomLog "|/usr/bin/rotatelogs /var/log/access.log 86400" \ combined
や
SetEnvIf Request_URI "^arienai$" arienai CustomLog "|/usr/local/sbin/syslog2mail.sh" combined env=arienai
流石でございます