work.log

エンジニアの備忘録的ブログ

Perlでマルチプロセスなデーモン

投稿:2013-07-08 20:26  更新:

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.

とりあえず、親プロセスが停止して残った子プロセスは処理が完了後に停止。

スポンサーリンク

コメント

コメントを残す

よく読まれている記事

  • 今日
  • 週間
  • 月間