Perl でマルチプロセスなデーモンを動かすメモです。
ブログネタが切れたのでサーバ内を漁ってたらたまたま発見。
だいぶ前に処理を並行稼動させるために作ったみたいですが、自分でもすっかり忘れていたのでメモしておきます。
#!/usr/bin/perl
use strict;
use warnings;
use POSIX ();
my @basename = split(/\//, $0);
my $basename = pop(@basename);
$basename =~ s/.[a-z, 0-9]+$//;
$0 = $basename;
# 多重起動のチェック用
# pgrep の -u オプションには起動するユーザ名を指定
my $cmd = {
grep => '/usr/bin/grep',
pgrep => '/bin/pgrep -fo -u hoge',
kill => '/bin/kill',
};
my $chroot = "/home/hoge";
my $log = "/home/hoge/daemon.log";
my $pstatus = '0';
my $opt = $ARGV[0];
# 子プロセスの最大数
my $child_max = 3;
my $child_num = 0;
## start
&Check_Run( $opt );
sub Check_Run {
my $run;
my $pid=$$;
$run = `$cmd->{pgrep} $basename | $cmd->{grep} -v $pid`;
chomp( $run );
# 親プロセスの起動
if ( $run eq "" ) {
&Daemon();
# 親プロセスが既に起動している場合
} else {
# stop が指定された場合は親プロセスを kill
if ( $opt =~ /^stop$/ ) {
`$cmd->{kill} $run`;
print " $basename\[$run\] is stop.\n";
# オプションが指定されていなければ親プロセスの pid を返す
} else {
print " $basename\[$run\] is already running.\n";
}
}
}
sub Daemon {
chdir "$chroot" or die "Can't chdir: $!";
umask 0;
open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!";
open STDERR, '>/dev/null' or die "Can't write to /dev/null: $!";
# 親プロセスの起動
my $pid = fork();
if ( ! defined $pid ) { die "Failed to fork(): $!"; }
if ( $pid ) {
exit 0;
} else {
POSIX::setsid() || die "Could not detach from parent process";
}
&Run( $pid );
}
sub Run {
my ($pid, $wait_pid);
while ( 1 ) {
# 子プロセスを起動
my $pid = fork;
die "Cannot fork: $!" unless defined $pid;
if ( $pid ne 0 ) {
$child_num++;
# 子プロセスの処理
# $log に書き込んで一定時間後に停止
} elsif ( defined $pid ) {
my $str = rand;
open( LOG, ">> $log" );
print LOG "$str\n";
close( LOG );
sleep(1 + int rand 10);
exit 0;
} else {
exit 1;
}
# 子プロセスの管理
# 起動子プロセスが $child_max まで達したら子プロセスの生成を停止
if ($child_num == $child_max) {
$wait_pid = wait;
$child_num--;
}
}
}
exit;
コメントは失念している箇所もありますが概ねこんな感じです。
起動はこんな感じ。
# su - hoge # perl my-daemon.pl
続けて起動すると。
# perl my-daemon.pl my-daemon[38684] is already running.
停止する時。
# perl my-daemon.pl stop my-daemon[38684] is stop.
とりあえず、親プロセスが停止して残った子プロセスは処理が完了後に停止。