Perl でマルチプロセスなデーモンを動かすメモです。
ブログネタが切れたのでサーバ内を漁ってたらたまたま発見。
だいぶ前に処理を並行稼動させるために作ったみたいですが、自分でもすっかり忘れていたのでメモしておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | #!/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.
とりあえず、親プロセスが停止して残った子プロセスは処理が完了後に停止。