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; |