| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
################################################################################ |
|
2
|
|
|
|
|
|
|
## File: |
|
3
|
|
|
|
|
|
|
## Daemon.pm |
|
4
|
|
|
|
|
|
|
## Authors: |
|
5
|
|
|
|
|
|
|
## Earl Hood earl@earlhood.com |
|
6
|
|
|
|
|
|
|
## Detlef Pilzecker deti@cpan.org |
|
7
|
|
|
|
|
|
|
## Pavel Denisov akreal@cpan.org |
|
8
|
|
|
|
|
|
|
## Description: |
|
9
|
|
|
|
|
|
|
## Run Perl program(s) as a daemon process, see docs in the Daemon.pod file |
|
10
|
|
|
|
|
|
|
################################################################################ |
|
11
|
|
|
|
|
|
|
## Copyright (C) 1997-2015 by Earl Hood, Detlef Pilzecker and Pavel Denisov. |
|
12
|
|
|
|
|
|
|
## |
|
13
|
|
|
|
|
|
|
## All rights reserved. |
|
14
|
|
|
|
|
|
|
## |
|
15
|
|
|
|
|
|
|
## This module is free software. It may be used, redistributed and/or modified |
|
16
|
|
|
|
|
|
|
## under the same terms as Perl itself. |
|
17
|
|
|
|
|
|
|
################################################################################ |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
package Proc::Daemon; |
|
21
|
|
|
|
|
|
|
|
|
22
|
11
|
|
|
11
|
|
223726
|
use strict; |
|
|
11
|
|
|
|
|
16
|
|
|
|
11
|
|
|
|
|
298
|
|
|
23
|
11
|
|
|
11
|
|
5813
|
use POSIX(); |
|
|
11
|
|
|
|
|
65430
|
|
|
|
11
|
|
|
|
|
20409
|
|
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
$Proc::Daemon::VERSION = '0.21'; |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
################################################################################ |
|
29
|
|
|
|
|
|
|
# Create the Daemon object: |
|
30
|
|
|
|
|
|
|
# my $daemon = Proc::Daemon->new( [ %Daemon_Settings ] ) |
|
31
|
|
|
|
|
|
|
# |
|
32
|
|
|
|
|
|
|
# %Daemon_Settings are hash key=>values and can be: |
|
33
|
|
|
|
|
|
|
# work_dir => '/working/daemon/directory' -> defaults to '/' |
|
34
|
|
|
|
|
|
|
# setgid => 12345 -> defaults to |
|
35
|
|
|
|
|
|
|
# setuid => 12345 -> defaults to |
|
36
|
|
|
|
|
|
|
# child_STDIN => '/path/to/daemon/STDIN.file' -> defautls to '
|
|
37
|
|
|
|
|
|
|
# child_STDOUT => '/path/to/daemon/STDOUT.file' -> defaults to '+>/dev/null' |
|
38
|
|
|
|
|
|
|
# child_STDERR => '/path/to/daemon/STDERR.file' -> defaults to '+>/dev/null' |
|
39
|
|
|
|
|
|
|
# dont_close_fh => [ 'main::DATA', 'PackageName::DATA', 'STDOUT', ... ] |
|
40
|
|
|
|
|
|
|
# -> arrayref with file handles you do not want to be closed in the daemon. |
|
41
|
|
|
|
|
|
|
# dont_close_fd => [ 5, 8, ... ] -> arrayref with file |
|
42
|
|
|
|
|
|
|
# descriptors you do not want to be closed in the daemon. |
|
43
|
|
|
|
|
|
|
# pid_file => '/path/to/pid/file.txt' -> defaults to |
|
44
|
|
|
|
|
|
|
# undef (= write no file). |
|
45
|
|
|
|
|
|
|
# file_umask => 022 -> defaults to 066 |
|
46
|
|
|
|
|
|
|
# exec_command => 'perl /home/script.pl' -> execute a system command |
|
47
|
|
|
|
|
|
|
# via Perls *exec PROGRAM* at the end of the Init routine and never return. |
|
48
|
|
|
|
|
|
|
# Must be an arrayref if you want to create several daemons at once. |
|
49
|
|
|
|
|
|
|
# |
|
50
|
|
|
|
|
|
|
# Returns: the blessed object. |
|
51
|
|
|
|
|
|
|
################################################################################ |
|
52
|
|
|
|
|
|
|
sub new { |
|
53
|
18
|
|
|
18
|
1
|
53136
|
my ( $class, %args ) = @_; |
|
54
|
|
|
|
|
|
|
|
|
55
|
18
|
|
|
|
|
96
|
my $self = \%args; |
|
56
|
18
|
|
|
|
|
71
|
bless( $self, $class ); |
|
57
|
|
|
|
|
|
|
|
|
58
|
18
|
|
|
|
|
186
|
$self->{memory} = {}; |
|
59
|
|
|
|
|
|
|
|
|
60
|
18
|
|
|
|
|
107
|
return $self; |
|
61
|
|
|
|
|
|
|
} |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
################################################################################ |
|
65
|
|
|
|
|
|
|
# Become a daemon: |
|
66
|
|
|
|
|
|
|
# $daemon->Init |
|
67
|
|
|
|
|
|
|
# |
|
68
|
|
|
|
|
|
|
# or, for more daemons with other settings in the same script: |
|
69
|
|
|
|
|
|
|
# Use a hash as below. The argument must (!) now be a hashref: {...} |
|
70
|
|
|
|
|
|
|
# even if you don't modify the initial settings (=> use empty hashref). |
|
71
|
|
|
|
|
|
|
# $daemon->Init( { [ %Daemon_Settings ] } ) |
|
72
|
|
|
|
|
|
|
# |
|
73
|
|
|
|
|
|
|
# or, if no Daemon->new() object was created and for backward compatibility: |
|
74
|
|
|
|
|
|
|
# Proc::Daemon::Init( [ { %Daemon_Settings } ] ) |
|
75
|
|
|
|
|
|
|
# In this case the argument must be or a hashref! |
|
76
|
|
|
|
|
|
|
# |
|
77
|
|
|
|
|
|
|
# %Daemon_Settings see &new. |
|
78
|
|
|
|
|
|
|
# |
|
79
|
|
|
|
|
|
|
# Returns to the parent: |
|
80
|
|
|
|
|
|
|
# - nothing (parent does exit) if the context is looking for no return value. |
|
81
|
|
|
|
|
|
|
# - the PID(s) of the daemon(s) created. |
|
82
|
|
|
|
|
|
|
# Returns to the child (daemon): |
|
83
|
|
|
|
|
|
|
# its PID (= 0) | never returns if used with 'exec_command'. |
|
84
|
|
|
|
|
|
|
################################################################################ |
|
85
|
|
|
|
|
|
|
sub Init { |
|
86
|
24
|
|
|
24
|
1
|
5375611
|
my Proc::Daemon $self = shift; |
|
87
|
24
|
|
|
|
|
72
|
my $settings_ref = shift; |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# Check if $self has been blessed into the package, otherwise do it now. |
|
91
|
24
|
50
|
33
|
|
|
272
|
unless ( ref( $self ) && eval{ $self->isa( 'Proc::Daemon' ) } ) { |
|
|
|
100
|
|
|
|
|
|
|
92
|
0
|
0
|
|
|
|
0
|
$self = ref( $self ) eq 'HASH' ? Proc::Daemon->new( %$self ) : Proc::Daemon->new(); |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
# If $daemon->Init is used again in the same script, |
|
95
|
|
|
|
|
|
|
# update to the new arguments. |
|
96
|
|
|
|
|
|
|
elsif ( ref( $settings_ref ) eq 'HASH' ) { |
|
97
|
6
|
|
|
|
|
24
|
map { $self->{ $_ } = $$settings_ref{ $_ } } keys %$settings_ref; |
|
|
18
|
|
|
|
|
69
|
|
|
98
|
|
|
|
|
|
|
} |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# Open a filehandle to an anonymous temporary pid file. If this is not |
|
102
|
|
|
|
|
|
|
# possible (some environments do not allow all users to use anonymous |
|
103
|
|
|
|
|
|
|
# temporary files), use the pid_file(s) to retrieve the PIDs for the parent. |
|
104
|
24
|
|
|
|
|
53
|
my $FH_MEMORY; |
|
105
|
24
|
0
|
33
|
|
|
4451
|
unless ( open( $FH_MEMORY, "+>", undef ) || $self->{pid_file} ) { |
|
106
|
0
|
|
|
|
|
0
|
die "Can not anonymous temporary pidfile ('$!'), therefore you must add 'pid_file' as an Init() argument, e.g. to: '/tmp/proc_daemon_pids'"; |
|
107
|
|
|
|
|
|
|
} |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# Get the file descriptors the user does not want to close. |
|
111
|
24
|
|
|
|
|
69
|
my %dont_close_fd; |
|
112
|
24
|
50
|
|
|
|
132
|
if ( defined $self->{dont_close_fd} ) { |
|
113
|
|
|
|
|
|
|
die "The argument 'dont_close_fd' must be arrayref!" |
|
114
|
0
|
0
|
|
|
|
0
|
if ref( $self->{dont_close_fd} ) ne 'ARRAY'; |
|
115
|
0
|
|
|
|
|
0
|
foreach ( @{ $self->{dont_close_fd} } ) { |
|
|
0
|
|
|
|
|
0
|
|
|
116
|
0
|
0
|
|
|
|
0
|
die "All entries in 'dont_close_fd' must be numeric ('$_')!" if $_ =~ /\D/; |
|
117
|
0
|
|
|
|
|
0
|
$dont_close_fd{ $_ } = 1; |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
} |
|
120
|
|
|
|
|
|
|
# Get the file descriptors of the handles the user does not want to close. |
|
121
|
24
|
50
|
|
|
|
80
|
if ( defined $self->{dont_close_fh} ) { |
|
122
|
|
|
|
|
|
|
die "The argument 'dont_close_fh' must be arrayref!" |
|
123
|
0
|
0
|
|
|
|
0
|
if ref( $self->{dont_close_fh} ) ne 'ARRAY'; |
|
124
|
0
|
|
|
|
|
0
|
foreach ( @{ $self->{dont_close_fh} } ) { |
|
|
0
|
|
|
|
|
0
|
|
|
125
|
0
|
0
|
|
|
|
0
|
if ( defined ( my $fn = fileno $_ ) ) { |
|
126
|
0
|
|
|
|
|
0
|
$dont_close_fd{ $fn } = 1; |
|
127
|
|
|
|
|
|
|
} |
|
128
|
|
|
|
|
|
|
} |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
# If system commands are to be executed, put them in a list. |
|
133
|
24
|
50
|
|
|
|
149
|
my @exec_command = ref( $self->{exec_command} ) eq 'ARRAY' ? @{ $self->{exec_command} } : ( $self->{exec_command} ); |
|
|
0
|
|
|
|
|
0
|
|
|
134
|
24
|
50
|
|
|
|
109
|
$#exec_command = 0 if $#exec_command < 0; |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# Create a daemon for every system command. |
|
138
|
24
|
|
|
|
|
87
|
foreach my $exec_command ( @exec_command ) { |
|
139
|
|
|
|
|
|
|
# The first parent is running here. |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
# Using this subroutine or loop multiple times we must modify the filenames: |
|
143
|
|
|
|
|
|
|
# 'child_STDIN', 'child_STDOUT', 'child_STDERR' and 'pid_file' for every |
|
144
|
|
|
|
|
|
|
# daemon (a higher number will be appended to the filenames). |
|
145
|
24
|
|
|
|
|
188
|
$self->adjust_settings(); |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# First fork. |
|
149
|
24
|
|
|
|
|
76
|
my $pid = Fork(); |
|
150
|
24
|
100
|
66
|
|
|
791
|
if ( defined $pid && $pid == 0 ) { |
|
151
|
|
|
|
|
|
|
# The first child runs here. |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
# Set the new working directory. |
|
155
|
10
|
50
|
|
|
|
835
|
die "Can't to $self->{work_dir}: $!" unless chdir $self->{work_dir}; |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
# Set the file creation mask. |
|
158
|
10
|
|
|
|
|
291
|
$self->{_orig_umask} = umask; |
|
159
|
10
|
|
|
|
|
56
|
umask($self->{file_umask}); |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# Detach the child from the terminal (no controlling tty), make it the |
|
162
|
|
|
|
|
|
|
# session-leader and the process-group-leader of a new process group. |
|
163
|
10
|
50
|
|
|
|
565
|
die "Cannot detach from controlling terminal" if POSIX::setsid() < 0; |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
# "Is ignoring SIGHUP necessary? |
|
166
|
|
|
|
|
|
|
# |
|
167
|
|
|
|
|
|
|
# It's often suggested that the SIGHUP signal should be ignored before |
|
168
|
|
|
|
|
|
|
# the second fork to avoid premature termination of the process. The |
|
169
|
|
|
|
|
|
|
# reason is that when the first child terminates, all processes, e.g. |
|
170
|
|
|
|
|
|
|
# the second child, in the orphaned group will be sent a SIGHUP. |
|
171
|
|
|
|
|
|
|
# |
|
172
|
|
|
|
|
|
|
# 'However, as part of the session management system, there are exactly |
|
173
|
|
|
|
|
|
|
# two cases where SIGHUP is sent on the death of a process: |
|
174
|
|
|
|
|
|
|
# |
|
175
|
|
|
|
|
|
|
# 1) When the process that dies is the session leader of a session that |
|
176
|
|
|
|
|
|
|
# is attached to a terminal device, SIGHUP is sent to all processes |
|
177
|
|
|
|
|
|
|
# in the foreground process group of that terminal device. |
|
178
|
|
|
|
|
|
|
# 2) When the death of a process causes a process group to become |
|
179
|
|
|
|
|
|
|
# orphaned, and one or more processes in the orphaned group are |
|
180
|
|
|
|
|
|
|
# stopped, then SIGHUP and SIGCONT are sent to all members of the |
|
181
|
|
|
|
|
|
|
# orphaned group.' [2] |
|
182
|
|
|
|
|
|
|
# |
|
183
|
|
|
|
|
|
|
# The first case can be ignored since the child is guaranteed not to have |
|
184
|
|
|
|
|
|
|
# a controlling terminal. The second case isn't so easy to dismiss. |
|
185
|
|
|
|
|
|
|
# The process group is orphaned when the first child terminates and |
|
186
|
|
|
|
|
|
|
# POSIX.1 requires that every STOPPED process in an orphaned process |
|
187
|
|
|
|
|
|
|
# group be sent a SIGHUP signal followed by a SIGCONT signal. Since the |
|
188
|
|
|
|
|
|
|
# second child is not STOPPED though, we can safely forego ignoring the |
|
189
|
|
|
|
|
|
|
# SIGHUP signal. In any case, there are no ill-effects if it is ignored." |
|
190
|
|
|
|
|
|
|
# Source: http://code.activestate.com/recipes/278731/ |
|
191
|
|
|
|
|
|
|
# |
|
192
|
|
|
|
|
|
|
# local $SIG{'HUP'} = 'IGNORE'; |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
# Second fork. |
|
195
|
|
|
|
|
|
|
# This second fork is not absolutely necessary, it is more a precaution. |
|
196
|
|
|
|
|
|
|
# 1. Prevent possibility of reacquiring a controlling terminal. |
|
197
|
|
|
|
|
|
|
# Without this fork the daemon would remain a session-leader. In |
|
198
|
|
|
|
|
|
|
# this case there is a potential possibility that the process could |
|
199
|
|
|
|
|
|
|
# reacquire a controlling terminal. E.g. if it opens a terminal device, |
|
200
|
|
|
|
|
|
|
# without using the O_NOCTTY flag. In Perl this is normally the case |
|
201
|
|
|
|
|
|
|
# when you use on this kind of device, instead of |
|
202
|
|
|
|
|
|
|
# with the O_NOCTTY flag set. |
|
203
|
|
|
|
|
|
|
# Note: Because of the second fork the daemon will not be a session- |
|
204
|
|
|
|
|
|
|
# leader and therefore Signals will not be send to other members of |
|
205
|
|
|
|
|
|
|
# his process group. If you need the functionality of a session-leader |
|
206
|
|
|
|
|
|
|
# you may want to call POSIX::setsid() manually on your daemon. |
|
207
|
|
|
|
|
|
|
# 2. Detach the daemon completely from the parent. |
|
208
|
|
|
|
|
|
|
# The double-fork prevents the daemon from becoming a zombie. It is |
|
209
|
|
|
|
|
|
|
# needed in this module because the grandparent process can continue. |
|
210
|
|
|
|
|
|
|
# Without the second fork and if a child exits before the parent |
|
211
|
|
|
|
|
|
|
# and you forget to call in the parent you will get a zombie |
|
212
|
|
|
|
|
|
|
# until the parent also terminates. Using the second fork we can be |
|
213
|
|
|
|
|
|
|
# sure that the parent of the daemon is finished near by or before |
|
214
|
|
|
|
|
|
|
# the daemon exits. |
|
215
|
10
|
|
|
|
|
359
|
$pid = Fork(); |
|
216
|
10
|
50
|
33
|
|
|
440
|
if ( defined $pid && $pid == 0 ) { |
|
217
|
|
|
|
|
|
|
# Here the second child is running. |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# Close all file handles and descriptors the user does not want |
|
221
|
|
|
|
|
|
|
# to preserve. |
|
222
|
10
|
|
|
|
|
80
|
my $hc_fd; # highest closed file descriptor |
|
223
|
10
|
|
|
|
|
445
|
close $FH_MEMORY; |
|
224
|
10
|
|
|
|
|
126
|
foreach ( 0 .. OpenMax() ) { |
|
225
|
5242890
|
50
|
|
|
|
7209805
|
unless ( $dont_close_fd{ $_ } ) { |
|
226
|
5242890
|
100
|
|
|
|
9288139
|
if ( $_ == 0 ) { close STDIN } |
|
|
10
|
100
|
|
|
|
93
|
|
|
|
|
100
|
|
|
|
|
|
|
227
|
10
|
|
|
|
|
109
|
elsif ( $_ == 1 ) { close STDOUT } |
|
228
|
10
|
|
|
|
|
39
|
elsif ( $_ == 2 ) { close STDERR } |
|
229
|
5242860
|
100
|
|
|
|
10900262
|
else { $hc_fd = $_ if POSIX::close( $_ ) } |
|
230
|
|
|
|
|
|
|
} |
|
231
|
|
|
|
|
|
|
} |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
# Sets the real group identifier and the effective group |
|
234
|
|
|
|
|
|
|
# identifier for the daemon process before opening files. |
|
235
|
|
|
|
|
|
|
# Must set group first because you cannot change group |
|
236
|
|
|
|
|
|
|
# once you have changed user |
|
237
|
10
|
100
|
|
|
|
196
|
POSIX::setgid( $self->{setgid} ) if defined $self->{setgid}; |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
# Sets the real user identifier and the effective user |
|
240
|
|
|
|
|
|
|
# identifier for the daemon process before opening files. |
|
241
|
10
|
100
|
|
|
|
106
|
POSIX::setuid( $self->{setuid} ) if defined $self->{setuid}; |
|
242
|
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
# Reopen STDIN, STDOUT and STDERR to 'child_STD...'-path or to |
|
244
|
|
|
|
|
|
|
# /dev/null. Data written on a null special file is discarded. |
|
245
|
|
|
|
|
|
|
# Reads from the null special file always return end of file. |
|
246
|
10
|
50
|
50
|
|
|
981
|
open( STDIN, $self->{child_STDIN} || "
|
|
247
|
10
|
50
|
50
|
|
|
1234
|
open( STDOUT, $self->{child_STDOUT} || "+>/dev/null" ) unless $dont_close_fd{ 1 }; |
|
248
|
10
|
50
|
50
|
|
|
549
|
open( STDERR, $self->{child_STDERR} || "+>/dev/null" ) unless $dont_close_fd{ 2 }; |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
# Since is in some cases "secretly" closing |
|
251
|
|
|
|
|
|
|
# file descriptors without telling it to perl, we need to |
|
252
|
|
|
|
|
|
|
# re and as many files as we closed with |
|
253
|
|
|
|
|
|
|
# . Otherwise it can happen (especially with |
|
254
|
|
|
|
|
|
|
# FH opened by __DATA__ or __END__) that there will be two perl |
|
255
|
|
|
|
|
|
|
# handles associated with one file, what can cause some |
|
256
|
|
|
|
|
|
|
# confusion. :-) |
|
257
|
|
|
|
|
|
|
# see: http://rt.perl.org/rt3/Ticket/Display.html?id=72526 |
|
258
|
10
|
50
|
|
|
|
63
|
if ( $hc_fd ) { |
|
259
|
10
|
|
|
|
|
65
|
my @fh; |
|
260
|
10
|
|
|
|
|
51
|
foreach ( 3 .. $hc_fd ) { open $fh[ $_ ], "
|
|
|
50
|
|
|
|
|
1201
|
|
|
261
|
|
|
|
|
|
|
# Perl will try to close all handles when @fh leaves scope |
|
262
|
|
|
|
|
|
|
# here, but the rude ones will sacrifice themselves to avoid |
|
263
|
|
|
|
|
|
|
# potential damage later. |
|
264
|
|
|
|
|
|
|
} |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
# Restore the original file creation mask. |
|
267
|
10
|
|
|
|
|
56
|
umask $self->{_orig_umask}; |
|
268
|
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
# Execute a system command and never return. |
|
270
|
10
|
100
|
|
|
|
46
|
if ( $exec_command ) { |
|
271
|
2
|
0
|
|
|
|
0
|
exec ($exec_command) or die "couldn't exec $exec_command: $!"; |
|
272
|
0
|
|
|
|
|
0
|
exit; # Not a real exit, but needed since Perl warns you if |
|
273
|
|
|
|
|
|
|
# there is no statement like , , or |
|
274
|
|
|
|
|
|
|
# following . The function executes a system |
|
275
|
|
|
|
|
|
|
# command and never returns. |
|
276
|
|
|
|
|
|
|
} |
|
277
|
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
# Return the childs own PID (= 0) |
|
280
|
8
|
|
|
|
|
199
|
return $pid; |
|
281
|
|
|
|
|
|
|
} |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
# First child (= second parent) runs here. |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
# Print the PID of the second child into ... |
|
288
|
0
|
|
0
|
|
|
0
|
$pid ||= ''; |
|
289
|
|
|
|
|
|
|
# ... the anonymous temporary pid file. |
|
290
|
0
|
0
|
|
|
|
0
|
if ( $FH_MEMORY ) { |
|
291
|
0
|
|
|
|
|
0
|
print $FH_MEMORY "$pid\n"; |
|
292
|
0
|
|
|
|
|
0
|
close $FH_MEMORY; |
|
293
|
|
|
|
|
|
|
} |
|
294
|
|
|
|
|
|
|
# ... the real 'pid_file'. |
|
295
|
0
|
0
|
|
|
|
0
|
if ( $self->{pid_file} ) { |
|
296
|
0
|
0
|
|
|
|
0
|
open( my $FH_PIDFILE, "+>", $self->{pid_file} ) || |
|
297
|
|
|
|
|
|
|
die "Can not open pidfile (pid_file => '$self->{pid_file}'): $!"; |
|
298
|
0
|
|
|
|
|
0
|
print $FH_PIDFILE $pid; |
|
299
|
0
|
|
|
|
|
0
|
close $FH_PIDFILE; |
|
300
|
|
|
|
|
|
|
} |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
# Don't for the second child to exit, |
|
304
|
|
|
|
|
|
|
# even if we don't have a value in $exec_command. |
|
305
|
|
|
|
|
|
|
# The second child will become orphan by here, but then it |
|
306
|
|
|
|
|
|
|
# will be adopted by init(8), which automatically performs a |
|
307
|
|
|
|
|
|
|
# to remove the zombie when the child exits. |
|
308
|
|
|
|
|
|
|
|
|
309
|
0
|
|
|
|
|
0
|
POSIX::_exit(0); |
|
310
|
|
|
|
|
|
|
} |
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
# Only first parent runs here. |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
# A child that terminates, but has not been waited for becomes |
|
317
|
|
|
|
|
|
|
# a zombie. So we wait for the first child to exit. |
|
318
|
14
|
|
|
|
|
29719
|
waitpid( $pid, 0 ); |
|
319
|
|
|
|
|
|
|
} |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
# Only first parent runs here. |
|
323
|
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
# Exit if the context is looking for no value (void context). |
|
326
|
14
|
50
|
|
|
|
123
|
exit 0 unless defined wantarray; |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
# Get the daemon PIDs out of the anonymous temporary pid file |
|
329
|
|
|
|
|
|
|
# or out of the real pid-file(s) |
|
330
|
14
|
|
|
|
|
46
|
my @pid; |
|
331
|
14
|
50
|
|
|
|
164
|
if ( $FH_MEMORY ) { |
|
|
|
0
|
|
|
|
|
|
|
332
|
14
|
|
|
|
|
305
|
seek( $FH_MEMORY, 0, 0 ); |
|
333
|
14
|
50
|
|
|
|
725
|
@pid = map { chomp $_; $_ eq '' ? undef : $_ } <$FH_MEMORY>; |
|
|
14
|
|
|
|
|
86
|
|
|
|
14
|
|
|
|
|
123
|
|
|
334
|
14
|
|
|
|
|
401
|
$_ = (/^(\d+)$/)[0] foreach @pid; # untaint |
|
335
|
14
|
|
|
|
|
786
|
close $FH_MEMORY; |
|
336
|
|
|
|
|
|
|
} |
|
337
|
|
|
|
|
|
|
elsif ( $self->{memory}{pid_file} ) { |
|
338
|
0
|
|
|
|
|
0
|
foreach ( keys %{ $self->{memory}{pid_file} } ) { |
|
|
0
|
|
|
|
|
0
|
|
|
339
|
0
|
0
|
|
|
|
0
|
open( $FH_MEMORY, "<", $_ ) || die "Can not open pid_file '<$_': $!"; |
|
340
|
0
|
|
|
|
|
0
|
push( @pid, <$FH_MEMORY> ); |
|
341
|
0
|
|
|
|
|
0
|
close $FH_MEMORY; |
|
342
|
|
|
|
|
|
|
} |
|
343
|
|
|
|
|
|
|
} |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
# Return the daemon PIDs (from second child/ren) to the first parent. |
|
346
|
14
|
50
|
|
|
|
836
|
return ( wantarray ? @pid : $pid[0] ); |
|
347
|
|
|
|
|
|
|
} |
|
348
|
|
|
|
|
|
|
# For backward capability: |
|
349
|
|
|
|
|
|
|
*init = \&Init; |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
################################################################################ |
|
353
|
|
|
|
|
|
|
# Set some defaults and adjust some settings. |
|
354
|
|
|
|
|
|
|
# Args: ( $self ) |
|
355
|
|
|
|
|
|
|
# Returns: nothing |
|
356
|
|
|
|
|
|
|
################################################################################ |
|
357
|
|
|
|
|
|
|
sub adjust_settings { |
|
358
|
24
|
|
|
24
|
1
|
56
|
my Proc::Daemon $self = shift; |
|
359
|
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
# Set default 'work_dir' if needed. |
|
361
|
24
|
|
50
|
|
|
97
|
$self->{work_dir} ||= '/'; |
|
362
|
|
|
|
|
|
|
|
|
363
|
24
|
50
|
|
|
|
80
|
$self->fix_filename( 'child_STDIN', 1 ) if $self->{child_STDIN}; |
|
364
|
|
|
|
|
|
|
|
|
365
|
24
|
50
|
|
|
|
139
|
$self->fix_filename( 'child_STDOUT', 1 ) if $self->{child_STDOUT}; |
|
366
|
|
|
|
|
|
|
|
|
367
|
24
|
50
|
|
|
|
116
|
$self->fix_filename( 'child_STDERR', 1 ) if $self->{child_STDERR}; |
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
# Check 'pid_file's name |
|
370
|
24
|
50
|
|
|
|
70
|
if ( $self->{pid_file} ) { |
|
371
|
24
|
50
|
|
|
|
171
|
die "Pidfile (pid_file => '$self->{pid_file}') can not be only a number. I must be able to distinguish it from a PID number in &get_pid('...')." if $self->{pid_file} =~ /^\d+$/; |
|
372
|
|
|
|
|
|
|
|
|
373
|
24
|
|
|
|
|
65
|
$self->fix_filename( 'pid_file' ); |
|
374
|
|
|
|
|
|
|
} |
|
375
|
|
|
|
|
|
|
|
|
376
|
24
|
|
100
|
|
|
152
|
$self->{file_umask} ||= 066; |
|
377
|
|
|
|
|
|
|
|
|
378
|
24
|
|
|
|
|
38
|
return; |
|
379
|
|
|
|
|
|
|
} |
|
380
|
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
################################################################################ |
|
383
|
|
|
|
|
|
|
# - If the keys value is only a filename add the path of 'work_dir'. |
|
384
|
|
|
|
|
|
|
# - If we have already set a file for this key with the same "path/name", |
|
385
|
|
|
|
|
|
|
# add a number to the file. |
|
386
|
|
|
|
|
|
|
# Args: ( $self, $key, $extract_mode ) |
|
387
|
|
|
|
|
|
|
# key: one of 'child_STDIN', 'child_STDOUT', 'child_STDERR', 'pid_file' |
|
388
|
|
|
|
|
|
|
# extract_mode: true = separate MODE form filename before checking |
|
389
|
|
|
|
|
|
|
# path/filename; false = no MODE to check |
|
390
|
|
|
|
|
|
|
# Returns: nothing |
|
391
|
|
|
|
|
|
|
################################################################################ |
|
392
|
|
|
|
|
|
|
sub fix_filename { |
|
393
|
72
|
|
|
72
|
1
|
94
|
my Proc::Daemon $self = shift; |
|
394
|
72
|
|
|
|
|
142
|
my $key = shift; |
|
395
|
72
|
|
|
|
|
99
|
my $var = $self->{ $key }; |
|
396
|
72
|
50
|
|
|
|
456
|
my $mode = ( shift ) ? ( $var =~ s/^([\+\<\>\-\|]+)// ? $1 : ( $key eq 'child_STDIN' ? '<' : '+>' ) ) : ''; |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
# add path to filename |
|
399
|
72
|
100
|
66
|
|
|
528
|
if ( $var =~ s/^\.\/// || $var !~ /\// ) { |
|
400
|
|
|
|
|
|
|
$var = $self->{work_dir} =~ /\/$/ ? |
|
401
|
54
|
50
|
|
|
|
215
|
$self->{work_dir} . $var : $self->{work_dir} . '/' . $var; |
|
402
|
|
|
|
|
|
|
} |
|
403
|
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
# If the file was already in use, modify it with '_number': |
|
405
|
|
|
|
|
|
|
# filename_X | filename_X.ext |
|
406
|
72
|
100
|
|
|
|
230
|
if ( $self->{memory}{ $key }{ $var } ) { |
|
407
|
18
|
|
|
|
|
150
|
$var =~ s/([^\/]+)$//; |
|
408
|
18
|
|
|
|
|
66
|
my @i = split( /\./, $1 ); |
|
409
|
18
|
50
|
|
|
|
66
|
my $j = $#i ? $#i - 1 : 0; |
|
410
|
|
|
|
|
|
|
|
|
411
|
18
|
|
50
|
|
|
138
|
$self->{memory}{ "$key\_num" } ||= 0; |
|
412
|
18
|
|
|
|
|
228
|
$i[ $j ] =~ s/_$self->{memory}{ "$key\_num" }$//; |
|
413
|
18
|
|
|
|
|
42
|
$self->{memory}{ "$key\_num" }++; |
|
414
|
18
|
|
|
|
|
42
|
$i[ $j ] .= '_' . $self->{memory}{ "$key\_num" }; |
|
415
|
18
|
|
|
|
|
54
|
$var .= join( '.', @i ); |
|
416
|
|
|
|
|
|
|
} |
|
417
|
|
|
|
|
|
|
|
|
418
|
72
|
|
|
|
|
197
|
$self->{memory}{ $key }{ $var } = 1; |
|
419
|
72
|
|
|
|
|
208
|
$self->{ $key } = $mode . $var; |
|
420
|
|
|
|
|
|
|
|
|
421
|
72
|
|
|
|
|
118
|
return; |
|
422
|
|
|
|
|
|
|
} |
|
423
|
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
################################################################################ |
|
426
|
|
|
|
|
|
|
# Fork(): Retries to fork over 30 seconds if possible to fork at all and |
|
427
|
|
|
|
|
|
|
# if necessary. |
|
428
|
|
|
|
|
|
|
# Returns the child PID to the parent process and 0 to the child process. |
|
429
|
|
|
|
|
|
|
# If the fork is unsuccessful it Cs and returns C. |
|
430
|
|
|
|
|
|
|
################################################################################ |
|
431
|
|
|
|
|
|
|
sub Fork { |
|
432
|
34
|
|
|
34
|
1
|
65
|
my $pid; |
|
433
|
34
|
|
|
|
|
59
|
my $loop = 0; |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
FORK: { |
|
436
|
34
|
50
|
|
|
|
49
|
if ( defined( $pid = fork ) ) { |
|
|
34
|
|
|
|
|
23367
|
|
|
437
|
34
|
|
|
|
|
902
|
return $pid; |
|
438
|
|
|
|
|
|
|
} |
|
439
|
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
# EAGAIN - fork cannot allocate sufficient memory to copy the parent's |
|
441
|
|
|
|
|
|
|
# page tables and allocate a task structure for the child. |
|
442
|
|
|
|
|
|
|
# ENOMEM - fork failed to allocate the necessary kernel structures |
|
443
|
|
|
|
|
|
|
# because memory is tight. |
|
444
|
|
|
|
|
|
|
# Last the loop after 30 seconds |
|
445
|
0
|
0
|
0
|
|
|
0
|
if ( $loop < 6 && ( $! == POSIX::EAGAIN() || $! == POSIX::ENOMEM() ) ) { |
|
|
|
|
0
|
|
|
|
|
|
446
|
0
|
|
|
|
|
0
|
$loop++; sleep 5; redo FORK; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
447
|
|
|
|
|
|
|
} |
|
448
|
|
|
|
|
|
|
} |
|
449
|
|
|
|
|
|
|
|
|
450
|
0
|
|
|
|
|
0
|
warn "Can't fork: $!"; |
|
451
|
|
|
|
|
|
|
|
|
452
|
0
|
|
|
|
|
0
|
return undef; |
|
453
|
|
|
|
|
|
|
} |
|
454
|
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
################################################################################ |
|
457
|
|
|
|
|
|
|
# OpenMax( [ NUMBER ] ) |
|
458
|
|
|
|
|
|
|
# Returns the maximum number of possible file descriptors. If sysconf() |
|
459
|
|
|
|
|
|
|
# does not give me a valid value, I return NUMBER (default is 64). |
|
460
|
|
|
|
|
|
|
################################################################################ |
|
461
|
|
|
|
|
|
|
sub OpenMax { |
|
462
|
10
|
|
|
10
|
1
|
338
|
my $openmax = POSIX::sysconf( &POSIX::_SC_OPEN_MAX ); |
|
463
|
|
|
|
|
|
|
|
|
464
|
10
|
50
|
33
|
|
|
471
|
return ( ! defined( $openmax ) || $openmax < 0 ) ? |
|
|
|
|
0
|
|
|
|
|
|
465
|
|
|
|
|
|
|
( shift || 64 ) : $openmax; |
|
466
|
|
|
|
|
|
|
} |
|
467
|
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
################################################################################ |
|
470
|
|
|
|
|
|
|
# Check if the (daemon) process is alive: |
|
471
|
|
|
|
|
|
|
# Status( [ number or string ] ) |
|
472
|
|
|
|
|
|
|
# |
|
473
|
|
|
|
|
|
|
# Examples: |
|
474
|
|
|
|
|
|
|
# $object->Status() - Tries to get the PID out of the settings in new() and checks it. |
|
475
|
|
|
|
|
|
|
# $object->Status( 12345 ) - Number of PID to check. |
|
476
|
|
|
|
|
|
|
# $object->Status( './pid.txt' ) - Path to file containing one PID to check. |
|
477
|
|
|
|
|
|
|
# $object->Status( 'perl /home/my_perl_daemon.pl' ) - Command line entry of the |
|
478
|
|
|
|
|
|
|
# running program to check. Requires Proc::ProcessTable to work. |
|
479
|
|
|
|
|
|
|
# |
|
480
|
|
|
|
|
|
|
# Returns the PID (alive) or 0 (dead). |
|
481
|
|
|
|
|
|
|
################################################################################ |
|
482
|
|
|
|
|
|
|
sub Status { |
|
483
|
101
|
|
|
101
|
1
|
77039194
|
my Proc::Daemon $self = shift; |
|
484
|
101
|
|
|
|
|
352
|
my $pid = shift; |
|
485
|
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
# Get the process ID. |
|
487
|
101
|
|
|
|
|
633
|
( $pid, undef ) = $self->get_pid( $pid ); |
|
488
|
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
# Return if no PID was found. |
|
490
|
101
|
50
|
|
|
|
460
|
return 0 if ! $pid; |
|
491
|
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
# The kill(2) system call will check whether it's possible to send |
|
493
|
|
|
|
|
|
|
# a signal to the pid (that means, to be brief, that the process |
|
494
|
|
|
|
|
|
|
# is owned by the same user, or we are the super-user). This is a |
|
495
|
|
|
|
|
|
|
# useful way to check that a child process is alive (even if only |
|
496
|
|
|
|
|
|
|
# as a zombie) and hasn't changed its UID. |
|
497
|
101
|
100
|
|
|
|
1794
|
return ( kill( 0, $pid ) ? $pid : 0 ); |
|
498
|
|
|
|
|
|
|
} |
|
499
|
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
################################################################################ |
|
502
|
|
|
|
|
|
|
# Kill the (daemon) process: |
|
503
|
|
|
|
|
|
|
# Kill_Daemon( [ number or string [, SIGNAL ] ] ) |
|
504
|
|
|
|
|
|
|
# |
|
505
|
|
|
|
|
|
|
# Examples: |
|
506
|
|
|
|
|
|
|
# $object->Kill_Daemon() - Tries to get the PID out of the settings in new() and kill it. |
|
507
|
|
|
|
|
|
|
# $object->Kill_Daemon( 12345, 'TERM' ) - Number of PID to kill with signal 'TERM'. The |
|
508
|
|
|
|
|
|
|
# names or numbers of the signals are the ones listed out by kill -l on your system. |
|
509
|
|
|
|
|
|
|
# $object->Kill_Daemon( './pid.txt' ) - Path to file containing one PID to kill. |
|
510
|
|
|
|
|
|
|
# $object->Kill_Daemon( 'perl /home/my_perl_daemon.pl' ) - Command line entry of the |
|
511
|
|
|
|
|
|
|
# running program to kill. Requires Proc::ProcessTable to work. |
|
512
|
|
|
|
|
|
|
# |
|
513
|
|
|
|
|
|
|
# Returns the number of processes successfully killed, |
|
514
|
|
|
|
|
|
|
# which mostly is not the same as the PID number. |
|
515
|
|
|
|
|
|
|
################################################################################ |
|
516
|
|
|
|
|
|
|
sub Kill_Daemon { |
|
517
|
4
|
|
|
4
|
1
|
2003474
|
my Proc::Daemon $self = shift; |
|
518
|
4
|
|
|
|
|
12
|
my $pid = shift; |
|
519
|
4
|
|
50
|
|
|
68
|
my $signal = shift || 'KILL'; |
|
520
|
4
|
|
|
|
|
8
|
my $pidfile; |
|
521
|
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
# Get the process ID. |
|
523
|
4
|
|
|
|
|
20
|
( $pid, $pidfile ) = $self->get_pid( $pid ); |
|
524
|
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
# Return if no PID was found. |
|
526
|
4
|
50
|
|
|
|
20
|
return 0 if ! $pid; |
|
527
|
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
# Kill the process. |
|
529
|
4
|
|
|
|
|
162
|
my $killed = kill( $signal, $pid ); |
|
530
|
|
|
|
|
|
|
|
|
531
|
4
|
50
|
33
|
|
|
64
|
if ( $killed && $pidfile ) { |
|
532
|
|
|
|
|
|
|
# Set PID in pid file to '0'. |
|
533
|
4
|
50
|
|
|
|
432
|
if ( open( my $FH_PIDFILE, "+>", $pidfile ) ) { |
|
534
|
4
|
|
|
|
|
34
|
print $FH_PIDFILE '0'; |
|
535
|
4
|
|
|
|
|
174
|
close $FH_PIDFILE; |
|
536
|
|
|
|
|
|
|
} |
|
537
|
0
|
|
|
|
|
0
|
else { warn "Can not open pidfile (pid_file => '$pidfile'): $!" } |
|
538
|
|
|
|
|
|
|
} |
|
539
|
|
|
|
|
|
|
|
|
540
|
4
|
|
|
|
|
22
|
return $killed; |
|
541
|
|
|
|
|
|
|
} |
|
542
|
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
################################################################################ |
|
545
|
|
|
|
|
|
|
# Return the PID of a process: |
|
546
|
|
|
|
|
|
|
# get_pid( number or string ) |
|
547
|
|
|
|
|
|
|
# |
|
548
|
|
|
|
|
|
|
# Examples: |
|
549
|
|
|
|
|
|
|
# $object->get_pid() - Tries to get the PID out of the settings in new(). |
|
550
|
|
|
|
|
|
|
# $object->get_pid( 12345 ) - Number of PID to return. |
|
551
|
|
|
|
|
|
|
# $object->get_pid( './pid.txt' ) - Path to file containing the PID. |
|
552
|
|
|
|
|
|
|
# $object->get_pid( 'perl /home/my_perl_daemon.pl' ) - Command line entry of |
|
553
|
|
|
|
|
|
|
# the running program. Requires Proc::ProcessTable to work. |
|
554
|
|
|
|
|
|
|
# |
|
555
|
|
|
|
|
|
|
# Returns an array with ( 'the PID | ', 'the pid_file | ' ) |
|
556
|
|
|
|
|
|
|
################################################################################ |
|
557
|
|
|
|
|
|
|
sub get_pid { |
|
558
|
115
|
|
|
115
|
1
|
5160
|
my Proc::Daemon $self = shift; |
|
559
|
115
|
|
100
|
|
|
713
|
my $string = shift || ''; |
|
560
|
115
|
|
|
|
|
165
|
my ( $pid, $pidfile ); |
|
561
|
|
|
|
|
|
|
|
|
562
|
115
|
100
|
|
|
|
397
|
if ( $string ) { |
|
563
|
|
|
|
|
|
|
# $string is already a PID. |
|
564
|
111
|
100
|
|
|
|
2090
|
if ( $string =~ /^(\d+)$/ ) { |
|
|
|
50
|
|
|
|
|
|
|
565
|
97
|
|
|
|
|
622
|
$pid = $1; # untaint |
|
566
|
|
|
|
|
|
|
} |
|
567
|
|
|
|
|
|
|
# Open the pidfile and get the PID from it. |
|
568
|
|
|
|
|
|
|
elsif ( open( my $FH_MEMORY, "<", $string ) ) { |
|
569
|
14
|
|
|
|
|
229
|
$pid = <$FH_MEMORY>; |
|
570
|
14
|
|
|
|
|
143
|
close $FH_MEMORY; |
|
571
|
|
|
|
|
|
|
|
|
572
|
14
|
50
|
|
|
|
81
|
die "I found no valid PID ('$pid') in the pidfile: '$string'" if $pid =~ /\D/s; |
|
573
|
14
|
|
|
|
|
120
|
$pid = ($pid =~ /^(\d+)$/)[0]; # untaint |
|
574
|
|
|
|
|
|
|
|
|
575
|
14
|
|
|
|
|
76
|
$pidfile = $string; |
|
576
|
|
|
|
|
|
|
} |
|
577
|
|
|
|
|
|
|
# Get the PID by the system process table. |
|
578
|
|
|
|
|
|
|
else { |
|
579
|
0
|
|
|
|
|
0
|
$pid = $self->get_pid_by_proc_table_attr( 'cmndline', $string ); |
|
580
|
|
|
|
|
|
|
} |
|
581
|
|
|
|
|
|
|
} |
|
582
|
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
# Try to get the PID out of the new() settings. |
|
585
|
115
|
100
|
|
|
|
339
|
if ( ! $pid ) { |
|
586
|
|
|
|
|
|
|
# Try to get the PID out of the 'pid_file' setting. |
|
587
|
4
|
50
|
33
|
|
|
226
|
if ( $self->{pid_file} && open( my $FH_MEMORY, "<", $self->{pid_file} ) ) { |
|
588
|
4
|
|
|
|
|
50
|
$pid = <$FH_MEMORY>; |
|
589
|
4
|
|
|
|
|
38
|
close $FH_MEMORY; |
|
590
|
|
|
|
|
|
|
|
|
591
|
4
|
50
|
33
|
|
|
64
|
if ($pid && $pid =~ /^(\d+)$/) { |
|
592
|
4
|
|
|
|
|
18
|
$pid = $1; # untaint |
|
593
|
4
|
|
|
|
|
18
|
$pidfile = $self->{pid_file}; |
|
594
|
|
|
|
|
|
|
} else { |
|
595
|
0
|
|
|
|
|
0
|
$pid = undef; |
|
596
|
|
|
|
|
|
|
} |
|
597
|
|
|
|
|
|
|
} |
|
598
|
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
# Try to get the PID out of the system process |
|
600
|
|
|
|
|
|
|
# table by the 'exec_command' setting. |
|
601
|
4
|
0
|
33
|
|
|
26
|
if ( ! $pid && $self->{exec_command} ) { |
|
602
|
0
|
|
|
|
|
0
|
$pid = $self->get_pid_by_proc_table_attr( 'cmndline', $self->{exec_command} ); |
|
603
|
|
|
|
|
|
|
} |
|
604
|
|
|
|
|
|
|
} |
|
605
|
|
|
|
|
|
|
|
|
606
|
115
|
|
|
|
|
707
|
return ( $pid, $pidfile ); |
|
607
|
|
|
|
|
|
|
} |
|
608
|
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
################################################################################ |
|
611
|
|
|
|
|
|
|
# This sub requires the Proc::ProcessTable module to be installed!!! |
|
612
|
|
|
|
|
|
|
# |
|
613
|
|
|
|
|
|
|
# Search for the PID of a process in the process table: |
|
614
|
|
|
|
|
|
|
# $object->get_pid_by_proc_table_attr( 'unix_process_table_attribute', 'string that must match' ) |
|
615
|
|
|
|
|
|
|
# |
|
616
|
|
|
|
|
|
|
# unix_process_table_attribute examples: |
|
617
|
|
|
|
|
|
|
# For more see the README.... files at http://search.cpan.org/~durist/Proc-ProcessTable/ |
|
618
|
|
|
|
|
|
|
# uid - UID of process |
|
619
|
|
|
|
|
|
|
# pid - process ID |
|
620
|
|
|
|
|
|
|
# ppid - parent process ID |
|
621
|
|
|
|
|
|
|
# fname - file name |
|
622
|
|
|
|
|
|
|
# state - state of process |
|
623
|
|
|
|
|
|
|
# cmndline - full command line of process |
|
624
|
|
|
|
|
|
|
# cwd - current directory of process |
|
625
|
|
|
|
|
|
|
# |
|
626
|
|
|
|
|
|
|
# Example: |
|
627
|
|
|
|
|
|
|
# get_pid_by_proc_table_attr( 'cmndline', 'perl /home/my_perl_daemon.pl' ) |
|
628
|
|
|
|
|
|
|
# |
|
629
|
|
|
|
|
|
|
# Returns the process PID on success, otherwise . |
|
630
|
|
|
|
|
|
|
################################################################################ |
|
631
|
|
|
|
|
|
|
sub get_pid_by_proc_table_attr { |
|
632
|
4
|
|
|
4
|
1
|
12007882
|
my Proc::Daemon $self = shift; |
|
633
|
4
|
|
|
|
|
20
|
my ( $command, $match ) = @_; |
|
634
|
4
|
|
|
|
|
10
|
my $pid; |
|
635
|
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
# eval - Module may not be installed |
|
637
|
4
|
|
|
|
|
18
|
eval { |
|
638
|
4
|
|
|
|
|
4104
|
require Proc::ProcessTable; |
|
639
|
|
|
|
|
|
|
|
|
640
|
4
|
|
|
|
|
43780
|
my $table = Proc::ProcessTable->new()->table; |
|
641
|
|
|
|
|
|
|
|
|
642
|
4
|
|
|
|
|
15250
|
foreach ( @$table ) { |
|
643
|
|
|
|
|
|
|
# fix for Proc::ProcessTable: under some conditions $_->cmndline |
|
644
|
|
|
|
|
|
|
# returns with space and/or other characters at the end |
|
645
|
44
|
100
|
|
|
|
1048
|
next unless $_->$command =~ /^$match\s*$/; |
|
646
|
2
|
|
|
|
|
62
|
$pid = $_->pid; |
|
647
|
2
|
|
|
|
|
112
|
last; |
|
648
|
|
|
|
|
|
|
} |
|
649
|
|
|
|
|
|
|
}; |
|
650
|
|
|
|
|
|
|
|
|
651
|
4
|
50
|
|
|
|
188
|
warn "- Problem in get_pid_by_proc_table_attr( '$command', '$match' ):\n $@ You may not use a command line entry to get the PID of your process.\n This function requires Proc::ProcessTable (http://search.cpan.org/~durist/Proc-ProcessTable/) to work.\n" if $@; |
|
652
|
|
|
|
|
|
|
|
|
653
|
4
|
|
|
|
|
22
|
return $pid; |
|
654
|
|
|
|
|
|
|
} |
|
655
|
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
1; |