-
- whileで無限ループなものを書くのならいっそデーモンにしてしまえということで
- Proc::Daemonというのがいいらしい perldoc perlfaq8 にものってるし。
- という安易な考えで調べて見てたら結構深い。
- 素直にモジュール使うのがいいかもしれない。
- App::Daemonは実行ユーザーの変更、ログ出力もサポートしてるがLog::Log4perl,Proc::ProcessTableと依存モジュールがある。
- Proc::DaemonはPP
- 手順
- forkで子プロセスを作成する
- 親プロセスを終了する
- umask(0)でマスク値を設定する
- umaskが設定されていると意図しない権限でファイルを作成してしまうかもしれない
- setsid
- setsidするにはセッションリーダーでない必要があるので上記forkが必要
- さらにforkする
- セッションリーダーのままだと端末に関連付けられてしまうことがあるのを回避
- カレントディレクトリを "/" に移動する
- プロセスが居座っているディレクトリは消せないしアンマウントもできない
- ファイルディスクリプタを閉じる
#!/usr/bin/perl
use strict;
use warnings;
use POSIX;
use FindBin qw/$Bin/;
my $user = "ymko";
daemonize();
set_stdio(
stdin => "/dev/null",
stdout => "$Bin/daemon.log",
stderr => "$Bin/daemon_error.log",
);
set_process_user($user);
set_trap_signal();
set_pidfile(
pidfile => "$Bin/pidfile.txt",
);
`touch "$Bin/hold.txt"`;
my $cnt = 0;
while (1) {
$cnt++;
print "$cnt\n";
sleep 1;
exit 0 unless -f "$Bin/hold.txt";
}
sub set_pidfile
{
my (%ref) = @_;
my $pidfile = (exists $ref{'pidfile'}) ? $ref{'pidfile'} : undef;
die "pidfile not defined\n" unless $pidfile;
open my $fh, ">", $pidfile or die "$!";
print $fh "$$\n";
close $fh;
return;
}
sub set_process_user
{
if ($> == 0) {
my ($user) = @_;
my ($uid, $gid) = (getpwnam $user)[2, 3];
POSIX::setgid($gid);
POSIX::setuid($uid);
}
return ;
}
sub set_trap_signal
{
$SIG{'HUP'} = sub {
print "get signal hup\n";
};
$SIG{'QUIT'} = sub {
print "get signal quit\n";
};
$SIG{'USR1'} = sub {
print "get signal user1\n";
};
$SIG{'USR2'} = sub {
print "get signal user2\n";
};
$SIG{'TERM'} = sub {
print "get signal term\n";
exit 0;
};
return ;
}
sub set_stdio
{
my (%ref) = @_;
my $stdin = (exists $ref{'stdin' }) ? $ref{'stdin' } : "/dev/null";
my $stdout = (exists $ref{'stdout'}) ? $ref{'stdout'} : "/dev/null";
my $stderr = (exists $ref{'stderr'}) ? $ref{'stderr'} : "/dev/null";
open (STDIN, "<", $stdin);
open (STDOUT, ">>", $stdout);
open (STDERR, ">>", $stderr);
return;
}
sub daemonize
{
my $pid = fork;
if ($pid > 0) {
exit 0;
}
elsif ($pid < 0) {
exit -1;
}
if (POSIX::setsid() < 0) {
die "setsid failed\n";
}
my $sub_pid = fork;
if ($sub_pid) {
exit 0;
}
chdir "/";
umask 0;
my $open_max = POSIX::sysconf( POSIX::_SC_OPEN_MAX );
foreach (0 .. $open_max) {
POSIX::close( $_ );
}
return ;
}