line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Daemon::Control; |
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
700846
|
use strict; |
|
2
|
|
|
|
|
10
|
|
|
2
|
|
|
|
|
148
|
|
4
|
2
|
|
|
2
|
|
18
|
use warnings; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
108
|
|
5
|
2
|
|
|
2
|
|
2379
|
use POSIX qw(_exit setsid setuid setgid getuid getgid); |
|
2
|
|
|
|
|
18638
|
|
|
2
|
|
|
|
|
13
|
|
6
|
2
|
|
|
2
|
|
2713
|
use File::Spec; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
47
|
|
7
|
2
|
|
|
2
|
|
9
|
use File::Path qw( make_path ); |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
114
|
|
8
|
2
|
|
|
2
|
|
9
|
use Cwd 'abs_path'; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
287
|
|
9
|
|
|
|
|
|
|
require 5.008001; # Supporting 5.8.1+ |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our $VERSION = '0.001008'; # 0.1.8 |
12
|
|
|
|
|
|
|
$VERSION = eval $VERSION; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
my @accessors = qw( |
15
|
|
|
|
|
|
|
pid color_map name program program_args directory quiet |
16
|
|
|
|
|
|
|
path scan_name stdout_file stderr_file pid_file fork data |
17
|
|
|
|
|
|
|
lsb_start lsb_stop lsb_sdesc lsb_desc redirect_before_fork init_config |
18
|
|
|
|
|
|
|
kill_timeout umask resource_dir help init_code |
19
|
|
|
|
|
|
|
prereq_no_process foreground reload_signal stop_signals |
20
|
|
|
|
|
|
|
); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
my $cmd_opt = "[start|stop|restart|reload|status|foreground|show_warnings|get_init_file|help]"; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# Accessor building |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
for my $method ( @accessors ) { |
27
|
|
|
|
|
|
|
my $accessor = sub { |
28
|
24
|
|
|
24
|
|
31
|
my $self = shift; |
29
|
24
|
100
|
|
|
|
46
|
$self->{$method} = shift if @_; |
30
|
24
|
|
|
|
|
231
|
return $self->{$method}; |
31
|
|
|
|
|
|
|
}; |
32
|
|
|
|
|
|
|
{ |
33
|
2
|
|
|
2
|
|
9
|
no strict 'refs'; |
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
22956
|
|
34
|
|
|
|
|
|
|
*$method = $accessor; |
35
|
|
|
|
|
|
|
} |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# As a result of not using a real object system for |
39
|
|
|
|
|
|
|
# this, I don't get after user => sub { } style things, |
40
|
|
|
|
|
|
|
# so I'm making my own triggers for user and group. |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub user { |
43
|
3
|
|
|
3
|
1
|
5
|
my $self = shift; |
44
|
|
|
|
|
|
|
|
45
|
3
|
50
|
|
|
|
8
|
if ( @_ ) { |
46
|
0
|
|
|
|
|
0
|
$self->{user} = shift; |
47
|
0
|
|
|
|
|
0
|
delete $self->{uid}; |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
3
|
|
|
|
|
74
|
return $self->{user}; |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub group { |
54
|
4
|
|
|
4
|
1
|
8
|
my $self = shift; |
55
|
|
|
|
|
|
|
|
56
|
4
|
50
|
|
|
|
10
|
if ( @_ ) { |
57
|
0
|
|
|
|
|
0
|
$self->{group} = shift; |
58
|
0
|
|
|
|
|
0
|
delete $self->{gid}; |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
4
|
|
|
|
|
79
|
return $self->{group}; |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub uid { |
65
|
1
|
|
|
1
|
1
|
897
|
my $self = shift; |
66
|
|
|
|
|
|
|
|
67
|
1
|
50
|
|
|
|
5
|
return $self->{uid} = shift if @_; |
68
|
|
|
|
|
|
|
|
69
|
1
|
50
|
|
|
|
8
|
$self->_set_uid_from_name unless exists $self->{uid}; |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
return $self->{uid} |
72
|
0
|
|
|
|
|
0
|
} |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub gid { |
75
|
1
|
|
|
1
|
1
|
646
|
my $self = shift; |
76
|
|
|
|
|
|
|
|
77
|
1
|
50
|
|
|
|
7
|
return $self->{gid} = shift if @_; |
78
|
|
|
|
|
|
|
|
79
|
1
|
50
|
|
|
|
7
|
$self->_set_gid_from_name unless exists $self->{gid}; |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
return $self->{gid} |
82
|
0
|
|
|
|
|
0
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub new { |
85
|
1
|
|
|
1
|
0
|
886
|
my ( $class, @in ) = @_; |
86
|
|
|
|
|
|
|
|
87
|
1
|
50
|
|
|
|
7
|
my $args = ref $in[0] eq 'HASH' ? $in[0] : { @in }; |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
# Create the object with defaults. |
90
|
1
|
|
|
|
|
15
|
my $self = bless { |
91
|
|
|
|
|
|
|
color_map => { red => 31, green => 32 }, |
92
|
|
|
|
|
|
|
redirect_before_fork => 1, |
93
|
|
|
|
|
|
|
kill_timeout => 1, |
94
|
|
|
|
|
|
|
quiet => 0, |
95
|
|
|
|
|
|
|
umask => 0, |
96
|
|
|
|
|
|
|
foreground => 0, |
97
|
|
|
|
|
|
|
reload_signal => 'HUP', |
98
|
|
|
|
|
|
|
stop_signals => [ qw(TERM TERM INT KILL) ], |
99
|
|
|
|
|
|
|
}, $class; |
100
|
|
|
|
|
|
|
|
101
|
1
|
|
|
|
|
3
|
for my $accessor ( @accessors, qw(uid gid user group) ) { |
102
|
33
|
100
|
|
|
|
66
|
if ( exists $args->{$accessor} ) { |
103
|
13
|
|
|
|
|
33
|
$self->{$accessor} = delete $args->{$accessor}; |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# Shortcut caused by setting foreground or using the ENV to do it. |
108
|
1
|
50
|
33
|
|
|
5
|
if ( ( $self->foreground == 1 ) || ( $ENV{DC_FOREGROUND} ) ) { |
109
|
0
|
|
|
|
|
0
|
$self->fork( 0 ); |
110
|
0
|
|
|
|
|
0
|
$self->quiet( 1 ); |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
1
|
50
|
|
|
|
5
|
die "Unknown arguments to the constructor: " . join( " ", keys %$args ) |
114
|
|
|
|
|
|
|
if keys( %$args ); |
115
|
|
|
|
|
|
|
|
116
|
1
|
|
|
|
|
4
|
return $self; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
sub with_plugins { |
120
|
0
|
|
|
0
|
1
|
0
|
my ( $class, @in ) = @_; |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# ->with_plugins()->new is just ->new... |
123
|
0
|
0
|
|
|
|
0
|
return $class unless @in; |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# Make sure we have Role::Tiny installed. |
126
|
0
|
|
|
|
|
0
|
local $@; |
127
|
0
|
|
|
|
|
0
|
eval "require Role::Tiny"; |
128
|
0
|
0
|
|
|
|
0
|
if ( $@ ) { |
129
|
0
|
|
|
|
|
0
|
die "Error: Role::Tiny is required for with_plugins to function.\n"; |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
# Take an array or arrayref as an argument |
133
|
|
|
|
|
|
|
# and mutate it into a list like this: |
134
|
|
|
|
|
|
|
# 'Module' -> Becomes -> 'Root::Module' |
135
|
|
|
|
|
|
|
# '+Module' -> Becomes -> 'Module' |
136
|
|
|
|
|
|
|
my @plugins = map { |
137
|
0
|
0
|
|
|
|
0
|
substr( $_, 0, 1 ) eq '+' |
138
|
|
|
|
|
|
|
? substr( $_, 1 ) |
139
|
|
|
|
|
|
|
: "Daemon::Control::Plugin::$_" |
140
|
0
|
0
|
|
|
|
0
|
} ref $in[0] eq 'ARRAY' ? @{ $in[0] } : @in; |
|
0
|
|
|
|
|
0
|
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
# Compose the plugins into our class, and return for the user |
144
|
|
|
|
|
|
|
# to call ->new(). |
145
|
0
|
|
|
|
|
0
|
return Role::Tiny->create_class_with_roles( $class, @plugins ); |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# Set the uid, triggered from getting the uid if the user has changed. |
149
|
|
|
|
|
|
|
sub _set_uid_from_name { |
150
|
1
|
|
|
1
|
|
2
|
my ( $self ) = @_; |
151
|
1
|
50
|
|
|
|
4
|
return unless defined $self->user; |
152
|
|
|
|
|
|
|
|
153
|
1
|
|
|
|
|
3
|
my $uid = getpwnam( $self->user ); |
154
|
1
|
50
|
|
|
|
7
|
die "Error: Couldn't get uid for non-existent user " . $self->user |
155
|
|
|
|
|
|
|
unless defined $uid; |
156
|
0
|
|
|
|
|
0
|
$self->trace( "Set UID => $uid" ); |
157
|
0
|
|
|
|
|
0
|
$self->uid( $uid ); |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
# Set the uid, triggered from getting the gid if the group has changed. |
161
|
|
|
|
|
|
|
sub _set_gid_from_name { |
162
|
1
|
|
|
1
|
|
3
|
my ( $self ) = @_; |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
# Grab the GID if we have a UID but no GID. |
165
|
1
|
50
|
33
|
|
|
3
|
if ( !defined $self->group && defined $self->uid ) { |
166
|
0
|
|
|
|
|
0
|
my ( $gid ) = ( (getpwuid( $self->uid ))[3] ); |
167
|
0
|
|
|
|
|
0
|
$self->gid( $gid ); |
168
|
0
|
|
|
|
|
0
|
$self->trace( "Implicit GID => $gid" ); |
169
|
0
|
|
|
|
|
0
|
return $gid; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
1
|
50
|
|
|
|
4
|
return unless defined $self->group; |
173
|
|
|
|
|
|
|
|
174
|
1
|
|
|
|
|
2
|
my $gid = getgrnam( $self->group ); |
175
|
1
|
50
|
|
|
|
8
|
die "Error: Couldn't get gid for non-existent group " . $self->group |
176
|
|
|
|
|
|
|
unless defined $gid; |
177
|
0
|
|
|
|
|
0
|
$self->trace( "Set GID => $gid" ); |
178
|
0
|
|
|
|
|
0
|
$self->gid( $gid ); |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
sub redirect_filehandles { |
183
|
0
|
|
|
0
|
0
|
0
|
my ( $self ) = @_; |
184
|
|
|
|
|
|
|
|
185
|
0
|
0
|
|
|
|
0
|
if ( $self->stdout_file ) { |
186
|
0
|
|
|
|
|
0
|
my $file = $self->stdout_file; |
187
|
0
|
0
|
|
|
|
0
|
$file = $file eq '/dev/null' ? File::Spec->devnull : $file; |
188
|
|
|
|
|
|
|
|
189
|
0
|
0
|
|
|
|
0
|
if ( ref $file eq 'ARRAY' ) { |
190
|
0
|
|
|
|
|
0
|
my $mode = shift @$file; |
191
|
0
|
0
|
|
|
|
0
|
open STDOUT, $mode, @$file ? @$file : () |
|
|
0
|
|
|
|
|
|
192
|
|
|
|
|
|
|
or die "Failed to open STDOUT with args $mode @$file: $!"; |
193
|
|
|
|
|
|
|
|
194
|
0
|
|
|
|
|
0
|
$self->trace("STDOUT redirected to open(STDOUT $mode @$file)"); |
195
|
|
|
|
|
|
|
} |
196
|
|
|
|
|
|
|
else { |
197
|
0
|
0
|
|
|
|
0
|
open STDOUT, ">>", $file |
198
|
|
|
|
|
|
|
or die "Failed to open STDOUT to $file: $!"; |
199
|
0
|
|
|
|
|
0
|
$self->trace( "STDOUT redirected to $file" ); |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
} |
202
|
0
|
0
|
|
|
|
0
|
if ( $self->stderr_file ) { |
203
|
0
|
|
|
|
|
0
|
my $file = $self->stderr_file; |
204
|
0
|
0
|
|
|
|
0
|
$file = $file eq '/dev/null' ? File::Spec->devnull : $file; |
205
|
|
|
|
|
|
|
|
206
|
0
|
0
|
|
|
|
0
|
if ( ref $file eq 'ARRAY' ) { |
207
|
0
|
|
|
|
|
0
|
my $mode = shift @$file; |
208
|
0
|
0
|
|
|
|
0
|
open STDERR, $mode, @$file ? @$file : () |
|
|
0
|
|
|
|
|
|
209
|
|
|
|
|
|
|
or die "Failed to open STDERR with args $mode @$file: $!"; |
210
|
|
|
|
|
|
|
|
211
|
0
|
|
|
|
|
0
|
$self->trace("STDERR redirected to open(STDERR $mode @$file)"); |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
else { |
214
|
0
|
0
|
|
|
|
0
|
open STDERR, ">>", $file |
215
|
|
|
|
|
|
|
or die "Failed to open STDERR to $file: $!"; |
216
|
0
|
|
|
|
|
0
|
$self->trace("STDERR redirected to $file"); |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub _create_resource_dir { |
222
|
0
|
|
|
0
|
|
0
|
my ( $self ) = @_; |
223
|
0
|
|
|
|
|
0
|
$self->_create_dir($self->resource_dir); |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub _create_dir { |
227
|
0
|
|
|
0
|
|
0
|
my ( $self, $dir ) = @_; |
228
|
|
|
|
|
|
|
|
229
|
0
|
0
|
|
|
|
0
|
return 0 unless defined $dir; |
230
|
0
|
0
|
|
|
|
0
|
return 1 unless length($dir); |
231
|
|
|
|
|
|
|
|
232
|
0
|
0
|
|
|
|
0
|
if ( -d $dir ) { |
233
|
0
|
|
|
|
|
0
|
$self->trace( "Dir exists (" . $dir . ") - no need to create" ); |
234
|
0
|
|
|
|
|
0
|
return 1; |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
0
|
|
|
|
|
0
|
my ( $created ) = make_path( |
238
|
|
|
|
|
|
|
$dir, |
239
|
|
|
|
|
|
|
{ |
240
|
|
|
|
|
|
|
uid => $self->uid, |
241
|
|
|
|
|
|
|
group => $self->gid, |
242
|
|
|
|
|
|
|
error => \my $errors, |
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
); |
245
|
|
|
|
|
|
|
|
246
|
0
|
0
|
|
|
|
0
|
if ( @$errors ) { |
247
|
0
|
|
|
|
|
0
|
for my $error ( @$errors ) { |
248
|
0
|
|
|
|
|
0
|
my ( $file, $msg ) = %$error; |
249
|
0
|
|
|
|
|
0
|
die "Error creating $file: $msg"; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
0
|
0
|
|
|
|
0
|
if ( $created eq $dir ) { |
254
|
0
|
|
|
|
|
0
|
$self->trace( "Created dir (" . $dir . ")" ); |
255
|
0
|
|
|
|
|
0
|
return 1; |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
0
|
|
|
|
|
0
|
$self->trace( "_create_dir() for $dir failed and I don't know why" ); |
259
|
0
|
|
|
|
|
0
|
return 0; |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
sub _double_fork { |
263
|
0
|
|
|
0
|
|
0
|
my ( $self ) = @_; |
264
|
0
|
|
|
|
|
0
|
my $pid = fork(); |
265
|
|
|
|
|
|
|
|
266
|
0
|
|
|
|
|
0
|
$self->trace( "_double_fork()" ); |
267
|
0
|
0
|
|
|
|
0
|
if ( $pid == 0 ) { # Child, launch the process here. |
|
|
0
|
|
|
|
|
|
268
|
0
|
|
|
|
|
0
|
setsid(); # Become the process leader. |
269
|
0
|
|
|
|
|
0
|
my $new_pid = fork(); |
270
|
0
|
0
|
|
|
|
0
|
if ( $new_pid == 0 ) { # Our double fork. |
|
|
0
|
|
|
|
|
|
271
|
|
|
|
|
|
|
|
272
|
0
|
0
|
|
|
|
0
|
if ( $self->gid ) { |
273
|
0
|
|
|
|
|
0
|
setgid( $self->gid ); |
274
|
0
|
|
|
|
|
0
|
$self->trace( "setgid(" . $self->gid . ")" ); |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
0
|
0
|
|
|
|
0
|
if ( $self->uid ) { |
278
|
0
|
|
|
|
|
0
|
setuid( $self->uid ); |
279
|
|
|
|
|
|
|
|
280
|
0
|
|
0
|
|
|
0
|
$ENV{USER} = $self->user || getpwuid($self->uid); |
281
|
0
|
|
|
|
|
0
|
$ENV{HOME} = ((getpwuid($self->uid))[7]); |
282
|
|
|
|
|
|
|
|
283
|
0
|
|
|
|
|
0
|
$self->trace( "setuid(" . $self->uid . ")" ); |
284
|
0
|
|
|
|
|
0
|
$self->trace( "\$ENV{USER} => " . $ENV{USER} ); |
285
|
0
|
|
|
|
|
0
|
$self->trace( "\$ENV{HOME} => " . $ENV{HOME} ); |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
|
288
|
0
|
0
|
|
|
|
0
|
if ( $self->umask ) { |
289
|
0
|
|
|
|
|
0
|
umask( $self->umask); |
290
|
0
|
|
|
|
|
0
|
$self->trace( "umask(" . $self->umask . ")" ); |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
0
|
|
|
|
|
0
|
open( STDIN, "<", File::Spec->devnull ); |
294
|
|
|
|
|
|
|
|
295
|
0
|
0
|
|
|
|
0
|
if ( $self->redirect_before_fork ) { |
296
|
0
|
|
|
|
|
0
|
$self->redirect_filehandles; |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
|
299
|
0
|
|
|
|
|
0
|
$self->_launch_program; |
300
|
|
|
|
|
|
|
} elsif ( not defined $new_pid ) { |
301
|
0
|
|
|
|
|
0
|
warn "Cannot fork: $!"; |
302
|
|
|
|
|
|
|
} else { |
303
|
0
|
|
|
|
|
0
|
$self->pid( $new_pid ); |
304
|
0
|
|
|
|
|
0
|
$self->trace("Set PID => $new_pid" ); |
305
|
0
|
|
|
|
|
0
|
$self->write_pid; |
306
|
0
|
|
|
|
|
0
|
_exit 0; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
} elsif ( not defined $pid ) { # We couldn't fork. =( |
309
|
0
|
|
|
|
|
0
|
warn "Cannot fork: $!"; |
310
|
|
|
|
|
|
|
} else { # In the parent, $pid = child's PID, return it. |
311
|
0
|
|
|
|
|
0
|
waitpid( $pid, 0 ); |
312
|
|
|
|
|
|
|
} |
313
|
0
|
|
|
|
|
0
|
return $self; |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
|
316
|
0
|
|
|
0
|
|
0
|
sub _foreground { shift->_launch_program } |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
sub _fork { |
319
|
0
|
|
|
0
|
|
0
|
my ( $self ) = @_; |
320
|
0
|
|
|
|
|
0
|
my $pid = fork(); |
321
|
|
|
|
|
|
|
|
322
|
0
|
|
|
|
|
0
|
$self->trace( "_fork()" ); |
323
|
0
|
0
|
|
|
|
0
|
if ( $pid == 0 ) { # Child, launch the process here. |
|
|
0
|
|
|
|
|
|
324
|
0
|
|
|
|
|
0
|
$self->_launch_program; |
325
|
|
|
|
|
|
|
} elsif ( not defined $pid ) { |
326
|
0
|
|
|
|
|
0
|
warn "Cannot fork: $!"; |
327
|
|
|
|
|
|
|
} else { # In the parent, $pid = child's PID, return it. |
328
|
0
|
|
|
|
|
0
|
$self->pid( $pid ); |
329
|
0
|
|
|
|
|
0
|
$self->trace("Set PID => $pid" ); |
330
|
0
|
|
|
|
|
0
|
$self->write_pid; |
331
|
|
|
|
|
|
|
} |
332
|
0
|
|
|
|
|
0
|
return $self; |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
sub _launch_program { |
336
|
0
|
|
|
0
|
|
0
|
my ($self) = @_; |
337
|
|
|
|
|
|
|
|
338
|
0
|
0
|
|
|
|
0
|
if ( $self->directory ) { |
339
|
0
|
|
|
|
|
0
|
chdir( $self->directory ); |
340
|
0
|
|
|
|
|
0
|
$self->trace( "chdir(" . $self->directory . ")" ); |
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
|
343
|
0
|
0
|
|
|
|
0
|
my @args = @{$self->program_args || [ ]}; |
|
0
|
|
|
|
|
0
|
|
344
|
|
|
|
|
|
|
|
345
|
0
|
0
|
|
|
|
0
|
if ( ref $self->program eq 'CODE' ) { |
346
|
0
|
|
|
|
|
0
|
$self->program->( $self, @args ); |
347
|
|
|
|
|
|
|
} else { |
348
|
0
|
0
|
|
|
|
0
|
exec ( $self->program, @args ) |
349
|
|
|
|
|
|
|
or die "Failed to exec " . $self->program . " " |
350
|
|
|
|
|
|
|
. join( " ", @args ) . ": $!"; |
351
|
|
|
|
|
|
|
} |
352
|
0
|
|
|
|
|
0
|
return 0; |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
sub write_pid { |
356
|
0
|
|
|
0
|
1
|
0
|
my ( $self ) = @_; |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
# Create the PID file as the user we currently are, |
359
|
|
|
|
|
|
|
# and change the permissions to our target UID/GID. |
360
|
|
|
|
|
|
|
|
361
|
0
|
|
|
|
|
0
|
$self->_write_pid; |
362
|
|
|
|
|
|
|
|
363
|
0
|
0
|
0
|
|
|
0
|
if ( $self->uid && $self->gid ) { |
364
|
0
|
|
|
|
|
0
|
chown $self->uid, $self->gid, $self->pid_file; |
365
|
0
|
|
|
|
|
0
|
$self->trace("PID => chown(" . $self->uid . ", " . $self->gid .")"); |
366
|
|
|
|
|
|
|
} |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
sub _write_pid { |
370
|
0
|
|
|
0
|
|
0
|
my ( $self ) = @_; |
371
|
|
|
|
|
|
|
|
372
|
0
|
|
|
|
|
0
|
my ($volume, $dir, $file) = File::Spec->splitpath($self->pid_file); |
373
|
0
|
0
|
|
|
|
0
|
return 0 if not $self->_create_dir($dir); |
374
|
|
|
|
|
|
|
|
375
|
0
|
0
|
|
|
|
0
|
open my $sf, ">", $self->pid_file |
376
|
|
|
|
|
|
|
or die "Failed to write " . $self->pid_file . ": $!"; |
377
|
0
|
|
|
|
|
0
|
print $sf $self->pid; |
378
|
0
|
|
|
|
|
0
|
close $sf; |
379
|
0
|
|
|
|
|
0
|
$self->trace( "Wrote pid (" . $self->pid . ") to pid file (" . $self->pid_file . ")" ); |
380
|
0
|
|
|
|
|
0
|
return $self; |
381
|
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
sub read_pid { |
384
|
0
|
|
|
0
|
1
|
0
|
my ( $self ) = @_; |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
# If we don't have a PID file, we're going to set it |
387
|
|
|
|
|
|
|
# to 0 -- this will prevent killing normal processes, |
388
|
|
|
|
|
|
|
# and make is_running return false. |
389
|
0
|
0
|
|
|
|
0
|
if ( ! -f $self->pid_file ) { |
390
|
0
|
|
|
|
|
0
|
$self->pid( 0 ); |
391
|
0
|
|
|
|
|
0
|
return 0; |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
|
394
|
0
|
0
|
|
|
|
0
|
open my $lf, "<", $self->pid_file |
395
|
|
|
|
|
|
|
or die "Failed to read " . $self->pid_file . ": $!"; |
396
|
0
|
|
|
|
|
0
|
my $pid = do { local $/; <$lf> }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
397
|
0
|
|
|
|
|
0
|
close $lf; |
398
|
0
|
|
|
|
|
0
|
$self->pid( $pid ); |
399
|
0
|
|
|
|
|
0
|
return $pid; |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
sub pid_running { |
403
|
0
|
|
|
0
|
0
|
0
|
my ( $self, $pid ) = @_; |
404
|
|
|
|
|
|
|
|
405
|
0
|
|
0
|
|
|
0
|
$pid ||= $self->read_pid; |
406
|
|
|
|
|
|
|
|
407
|
0
|
0
|
|
|
|
0
|
return 0 unless $self->pid >= 1; |
408
|
0
|
0
|
|
|
|
0
|
return 0 unless kill 0, $self->pid; |
409
|
|
|
|
|
|
|
|
410
|
0
|
0
|
|
|
|
0
|
if ( $self->scan_name ) { |
411
|
0
|
0
|
|
|
|
0
|
open my $lf, "-|", "ps", "-p", $self->pid, "-o", "command=" |
412
|
|
|
|
|
|
|
or die "Failed to get pipe to ps for scan_name."; |
413
|
0
|
|
|
|
|
0
|
while ( my $line = <$lf> ) { |
414
|
0
|
0
|
|
|
|
0
|
return 1 if $line =~ $self->scan_name; |
415
|
|
|
|
|
|
|
} |
416
|
0
|
|
|
|
|
0
|
return 0; |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
# Scan name wasn't used, testing normal PID. |
419
|
0
|
|
|
|
|
0
|
return kill 0, $self->pid; |
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
sub process_running { |
423
|
0
|
|
|
0
|
0
|
0
|
my ( $self, $pattern ) = @_; |
424
|
|
|
|
|
|
|
|
425
|
0
|
0
|
|
|
|
0
|
my $psopt = $^O =~ m/bsd$/ ? '-ax' : '-u ' . $self->user; |
426
|
0
|
|
|
|
|
0
|
my $ps = `LC_ALL=C command ps $psopt -o pid,args`; |
427
|
0
|
|
|
|
|
0
|
$ps =~ s/^\s+//mg; |
428
|
0
|
|
|
|
|
0
|
my @pids; |
429
|
0
|
|
|
|
|
0
|
for my $line (split /\n/, $ps) |
430
|
|
|
|
|
|
|
{ |
431
|
0
|
0
|
|
|
|
0
|
next if $line =~ m/^\D/; |
432
|
0
|
|
|
|
|
0
|
my ($pid, $command, $args) = split /\s+/, $line, 3; |
433
|
|
|
|
|
|
|
|
434
|
0
|
0
|
|
|
|
0
|
next if $pid eq $$; |
435
|
0
|
0
|
0
|
|
|
0
|
push @pids, $pid |
|
|
|
0
|
|
|
|
|
436
|
|
|
|
|
|
|
if $command =~ $pattern |
437
|
|
|
|
|
|
|
or defined $args and $args =~ $pattern; |
438
|
|
|
|
|
|
|
} |
439
|
0
|
|
|
|
|
0
|
return @pids; |
440
|
|
|
|
|
|
|
} |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
sub pretty_print { |
443
|
0
|
|
|
0
|
1
|
0
|
my ( $self, $message, $color ) = @_; |
444
|
|
|
|
|
|
|
|
445
|
0
|
0
|
|
|
|
0
|
return if $self->quiet; |
446
|
|
|
|
|
|
|
|
447
|
0
|
|
0
|
|
|
0
|
$color ||= "green"; # Green is no color. |
448
|
0
|
|
0
|
|
|
0
|
my $code = $self->color_map->{$color} ||= "32"; # Green is invalid. |
449
|
0
|
|
|
|
|
0
|
local $| = 1; |
450
|
0
|
|
|
|
|
0
|
printf( "%-49s %30s\n", $self->name, "\033[$code" ."m[$message]\033[0m" ); |
451
|
|
|
|
|
|
|
} |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
# Callable Functions |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
sub do_foreground { |
456
|
0
|
|
|
0
|
1
|
0
|
my ( $self ) = @_; |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
# Short cut to... |
459
|
0
|
|
|
|
|
0
|
$self->fork( 0 ); |
460
|
0
|
|
|
|
|
0
|
$self->quiet( 1 ); |
461
|
0
|
|
|
|
|
0
|
return $self->do_start; |
462
|
|
|
|
|
|
|
} |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
sub do_start { |
465
|
0
|
|
|
0
|
1
|
0
|
my ( $self ) = @_; |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
# Optionally check if a process is already running with the same name |
468
|
0
|
0
|
|
|
|
0
|
if ($self->prereq_no_process) |
469
|
|
|
|
|
|
|
{ |
470
|
0
|
|
|
|
|
0
|
my $program = $self->program; |
471
|
0
|
0
|
|
|
|
0
|
my $pattern = $self->prereq_no_process eq '1' |
472
|
|
|
|
|
|
|
? qr/\b${program}\b/ |
473
|
|
|
|
|
|
|
: $self->prereq_no_process; |
474
|
0
|
|
|
|
|
0
|
my @pids = $self->process_running($pattern); |
475
|
0
|
0
|
|
|
|
0
|
if (@pids) |
476
|
|
|
|
|
|
|
{ |
477
|
0
|
|
|
|
|
0
|
$self->pretty_print( 'Duplicate Running? (pid ' . join(', ', @pids) . ')', "red" ); |
478
|
0
|
|
|
|
|
0
|
return 1; |
479
|
|
|
|
|
|
|
} |
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
# Make sure the PID file exists. |
483
|
0
|
0
|
|
|
|
0
|
if ( ! -f $self->pid_file ) { |
484
|
0
|
|
|
|
|
0
|
$self->pid( 0 ); # Make PID invalid. |
485
|
0
|
|
|
|
|
0
|
$self->write_pid(); |
486
|
|
|
|
|
|
|
} |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
# Duplicate Check |
489
|
0
|
|
|
|
|
0
|
$self->read_pid; |
490
|
0
|
0
|
0
|
|
|
0
|
if ( $self->pid && $self->pid_running ) { |
491
|
0
|
|
|
|
|
0
|
$self->pretty_print( "Duplicate Running", "red" ); |
492
|
0
|
|
|
|
|
0
|
return 1; |
493
|
|
|
|
|
|
|
} |
494
|
|
|
|
|
|
|
|
495
|
0
|
|
|
|
|
0
|
$self->_create_resource_dir; |
496
|
|
|
|
|
|
|
|
497
|
0
|
0
|
|
|
|
0
|
$self->fork( 2 ) unless defined $self->fork; |
498
|
0
|
0
|
|
|
|
0
|
$self->_double_fork if $self->fork == 2; |
499
|
0
|
0
|
|
|
|
0
|
$self->_fork if $self->fork == 1; |
500
|
0
|
0
|
|
|
|
0
|
$self->_foreground if $self->fork == 0; |
501
|
0
|
|
|
|
|
0
|
$self->pretty_print( "Started" ); |
502
|
0
|
|
|
|
|
0
|
return 0; |
503
|
|
|
|
|
|
|
} |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
sub do_show_warnings { |
506
|
1
|
|
|
1
|
0
|
1054
|
my ( $self ) = @_; |
507
|
|
|
|
|
|
|
|
508
|
1
|
50
|
|
|
|
4
|
if ( ! $self->fork ) { |
509
|
1
|
|
|
|
|
5
|
warn "Fork undefined. Defaulting to fork => 2.\n"; |
510
|
|
|
|
|
|
|
} |
511
|
|
|
|
|
|
|
|
512
|
1
|
50
|
|
|
|
5
|
if ( ! $self->stdout_file ) { |
513
|
0
|
|
|
|
|
0
|
warn "stdout_file undefined. Will not redirect file handle.\n"; |
514
|
|
|
|
|
|
|
} |
515
|
|
|
|
|
|
|
|
516
|
1
|
50
|
|
|
|
4
|
if ( ! $self->stderr_file ) { |
517
|
0
|
|
|
|
|
0
|
warn "stderr_file undefined. Will not redirect file handle.\n"; |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
} |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
sub do_stop { |
522
|
0
|
|
|
0
|
1
|
0
|
my ( $self ) = @_; |
523
|
|
|
|
|
|
|
|
524
|
0
|
|
|
|
|
0
|
$self->read_pid; |
525
|
0
|
|
|
|
|
0
|
my $start_pid = $self->pid; |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
# Probably don't want to send anything to init(1). |
528
|
0
|
0
|
|
|
|
0
|
return 1 unless $start_pid > 1; |
529
|
|
|
|
|
|
|
|
530
|
0
|
0
|
|
|
|
0
|
if ( $self->pid_running($start_pid) ) { |
531
|
|
|
|
|
|
|
SIGNAL: |
532
|
0
|
|
|
|
|
0
|
foreach my $signal (@{ $self->stop_signals }) { |
|
0
|
|
|
|
|
0
|
|
533
|
0
|
|
|
|
|
0
|
$self->trace( "Sending $signal signal to pid $start_pid..." ); |
534
|
0
|
|
|
|
|
0
|
kill $signal => $start_pid; |
535
|
|
|
|
|
|
|
|
536
|
0
|
|
|
|
|
0
|
for (1..$self->kill_timeout) |
537
|
|
|
|
|
|
|
{ |
538
|
|
|
|
|
|
|
# abort early if the process is now stopped |
539
|
0
|
|
|
|
|
0
|
$self->trace("checking if pid $start_pid is still running..."); |
540
|
0
|
0
|
|
|
|
0
|
last if not $self->pid_running($start_pid); |
541
|
0
|
|
|
|
|
0
|
sleep 1; |
542
|
|
|
|
|
|
|
} |
543
|
0
|
0
|
|
|
|
0
|
last unless $self->pid_running($start_pid); |
544
|
|
|
|
|
|
|
} |
545
|
0
|
0
|
|
|
|
0
|
if ( $self->pid_running($start_pid) ) { |
546
|
0
|
|
|
|
|
0
|
$self->pretty_print( "Failed to Stop", "red" ); |
547
|
0
|
|
|
|
|
0
|
return 1; |
548
|
|
|
|
|
|
|
} |
549
|
0
|
|
|
|
|
0
|
$self->pretty_print( "Stopped" ); |
550
|
|
|
|
|
|
|
} else { |
551
|
0
|
|
|
|
|
0
|
$self->pretty_print( "Not Running", "red" ); |
552
|
|
|
|
|
|
|
} |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
# Clean up the PID file on stop, unless the pid |
555
|
|
|
|
|
|
|
# doesn't match $start_pid (perhaps a standby |
556
|
|
|
|
|
|
|
# worker stepped in to take over from the one |
557
|
|
|
|
|
|
|
# that was just terminated). |
558
|
|
|
|
|
|
|
|
559
|
0
|
0
|
|
|
|
0
|
if ( $self->pid_file ) { |
560
|
0
|
0
|
|
|
|
0
|
unlink($self->pid_file) if $self->read_pid == $start_pid; |
561
|
|
|
|
|
|
|
} |
562
|
0
|
|
|
|
|
0
|
return 0; |
563
|
|
|
|
|
|
|
} |
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
sub do_restart { |
566
|
0
|
|
|
0
|
1
|
0
|
my ( $self ) = @_; |
567
|
0
|
|
|
|
|
0
|
$self->read_pid; |
568
|
|
|
|
|
|
|
|
569
|
0
|
0
|
|
|
|
0
|
if ( $self->pid_running ) { |
570
|
0
|
|
|
|
|
0
|
$self->do_stop; |
571
|
|
|
|
|
|
|
} |
572
|
0
|
|
|
|
|
0
|
$self->do_start; |
573
|
0
|
|
|
|
|
0
|
return 0; |
574
|
|
|
|
|
|
|
} |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
sub do_status { |
577
|
0
|
|
|
0
|
1
|
0
|
my ( $self ) = @_; |
578
|
0
|
|
|
|
|
0
|
$self->read_pid; |
579
|
|
|
|
|
|
|
|
580
|
0
|
0
|
0
|
|
|
0
|
if ( $self->pid && $self->pid_running ) { |
581
|
0
|
|
|
|
|
0
|
$self->pretty_print( "Running" ); |
582
|
0
|
|
|
|
|
0
|
return 0; |
583
|
|
|
|
|
|
|
} else { |
584
|
0
|
|
|
|
|
0
|
$self->pretty_print( "Not Running", "red" ); |
585
|
0
|
|
|
|
|
0
|
return 3; |
586
|
|
|
|
|
|
|
} |
587
|
|
|
|
|
|
|
} |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
sub do_reload { |
590
|
0
|
|
|
0
|
1
|
0
|
my ( $self ) = @_; |
591
|
0
|
|
|
|
|
0
|
$self->read_pid; |
592
|
|
|
|
|
|
|
|
593
|
0
|
0
|
0
|
|
|
0
|
if ( $self->pid && $self->pid_running ) { |
594
|
0
|
|
|
|
|
0
|
kill $self->reload_signal, $self->pid; |
595
|
0
|
|
|
|
|
0
|
$self->pretty_print( "Reloaded" ); |
596
|
0
|
|
|
|
|
0
|
return 0; |
597
|
|
|
|
|
|
|
} else { |
598
|
0
|
|
|
|
|
0
|
$self->pretty_print( "Not Running", "red" ); |
599
|
0
|
|
|
|
|
0
|
return 1; |
600
|
|
|
|
|
|
|
} |
601
|
|
|
|
|
|
|
} |
602
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
sub do_get_init_file { |
604
|
1
|
|
|
1
|
1
|
904
|
shift->dump_init_script; |
605
|
1
|
|
|
|
|
2
|
return 0; |
606
|
|
|
|
|
|
|
} |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
sub do_help { |
609
|
1
|
|
|
1
|
0
|
2027
|
my ( $self ) = @_; |
610
|
|
|
|
|
|
|
|
611
|
1
|
|
|
|
|
7
|
print "Syntax: $0 $cmd_opt\n\n"; |
612
|
1
|
50
|
|
|
|
4
|
print $self->help if $self->help; |
613
|
1
|
|
|
|
|
3
|
return 0; |
614
|
|
|
|
|
|
|
} |
615
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
sub dump_init_script { |
617
|
1
|
|
|
1
|
1
|
3
|
my ( $self ) = @_; |
618
|
1
|
50
|
|
|
|
5
|
if ( ! $self->data ) { |
619
|
1
|
|
|
|
|
2
|
my $data; |
620
|
1
|
|
|
|
|
7
|
while ( my $line = <DATA> ) { |
621
|
26
|
100
|
|
|
|
47
|
last if $line =~ /^__END__$/; |
622
|
25
|
|
|
|
|
71
|
$data .= $line; |
623
|
|
|
|
|
|
|
} |
624
|
1
|
|
|
|
|
3
|
$self->data( $data ); |
625
|
|
|
|
|
|
|
} |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
# So, instead of expanding run_template to use a real DSL |
628
|
|
|
|
|
|
|
# or making TT a dependancy, I'm just going to fake template |
629
|
|
|
|
|
|
|
# IF logic. |
630
|
1
|
50
|
|
|
|
5
|
my $init_source_file = $self->init_config |
631
|
|
|
|
|
|
|
? $self->run_template( |
632
|
|
|
|
|
|
|
'[ -r [% FILE %] ] && . [% FILE %]', |
633
|
|
|
|
|
|
|
{ FILE => $self->init_config } ) |
634
|
|
|
|
|
|
|
: ""; |
635
|
|
|
|
|
|
|
|
636
|
1
|
50
|
50
|
|
|
4
|
$self->data( $self->run_template( |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
637
|
|
|
|
|
|
|
$self->data, |
638
|
|
|
|
|
|
|
{ |
639
|
|
|
|
|
|
|
HEADER => 'Generated at ' . scalar(localtime) |
640
|
|
|
|
|
|
|
. ' with Daemon::Control ' . ($self->VERSION || 'DEV'), |
641
|
|
|
|
|
|
|
NAME => $self->name ? $self->name : "", |
642
|
|
|
|
|
|
|
REQUIRED_START => $self->lsb_start ? $self->lsb_start : "", |
643
|
|
|
|
|
|
|
REQUIRED_STOP => $self->lsb_stop ? $self->lsb_stop : "", |
644
|
|
|
|
|
|
|
SHORT_DESCRIPTION => $self->lsb_sdesc ? $self->lsb_sdesc : "", |
645
|
|
|
|
|
|
|
DESCRIPTION => $self->lsb_desc ? $self->lsb_desc : "", |
646
|
|
|
|
|
|
|
SCRIPT => $self->path ? $self->path : abs_path($0), |
647
|
|
|
|
|
|
|
INIT_SOURCE_FILE => $init_source_file, |
648
|
|
|
|
|
|
|
INIT_CODE_BLOCK => $self->init_code ? $self->init_code : "", |
649
|
|
|
|
|
|
|
} |
650
|
|
|
|
|
|
|
)); |
651
|
1
|
|
|
|
|
6
|
print $self->data; |
652
|
|
|
|
|
|
|
} |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
sub run_template { |
655
|
1
|
|
|
1
|
0
|
2
|
my ( $self, $content, $config ) = @_; |
656
|
|
|
|
|
|
|
|
657
|
1
|
|
|
|
|
29
|
$content =~ s/\[% (.*?) %\]/$config->{$1}/g; |
658
|
|
|
|
|
|
|
|
659
|
1
|
|
|
|
|
4
|
return $content; |
660
|
|
|
|
|
|
|
} |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
sub run_command { |
665
|
0
|
|
|
0
|
1
|
|
my ( $self, $arg ) = @_; |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
# Error Checking. |
668
|
0
|
0
|
|
|
|
|
if ( ! $self->program ) { |
669
|
0
|
|
|
|
|
|
die "Error: program must be defined."; |
670
|
|
|
|
|
|
|
} |
671
|
0
|
0
|
|
|
|
|
if ( ! $self->pid_file ) { |
672
|
0
|
|
|
|
|
|
die "Error: pid_file must be defined."; |
673
|
|
|
|
|
|
|
} |
674
|
0
|
0
|
|
|
|
|
if ( ! $self->name ) { |
675
|
0
|
|
|
|
|
|
die "Error: name must be defined."; |
676
|
|
|
|
|
|
|
} |
677
|
|
|
|
|
|
|
|
678
|
0
|
|
0
|
|
|
|
my $called_with = $arg || "help"; |
679
|
0
|
|
|
|
|
|
$called_with =~ s/^[-]+//g; # Allow people to do --command too. |
680
|
|
|
|
|
|
|
|
681
|
0
|
0
|
|
|
|
|
my $action = "do_" . ($called_with ? $called_with : "" ); |
682
|
|
|
|
|
|
|
|
683
|
0
|
|
|
|
|
|
my $allowed_actions = "Must be called with an action: $cmd_opt"; |
684
|
|
|
|
|
|
|
|
685
|
0
|
0
|
|
|
|
|
if ( $self->can($action) ) { |
|
|
0
|
|
|
|
|
|
686
|
0
|
|
|
|
|
|
return $self->$action; |
687
|
|
|
|
|
|
|
} elsif ( ! $called_with ) { |
688
|
0
|
|
|
|
|
|
die $allowed_actions |
689
|
|
|
|
|
|
|
} else { |
690
|
0
|
|
|
|
|
|
die "Error: undefined action $called_with. $allowed_actions"; |
691
|
|
|
|
|
|
|
} |
692
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
} |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
# Application Code. |
696
|
|
|
|
|
|
|
sub run { |
697
|
0
|
|
|
0
|
1
|
|
exit shift->run_command( @ARGV ); |
698
|
|
|
|
|
|
|
} |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
sub trace { |
701
|
0
|
|
|
0
|
0
|
|
my ( $self, $message ) = @_; |
702
|
|
|
|
|
|
|
|
703
|
0
|
0
|
|
|
|
|
return unless $ENV{DC_TRACE}; |
704
|
|
|
|
|
|
|
|
705
|
0
|
0
|
|
|
|
|
print "[TRACE] $message\n" if $ENV{DC_TRACE} == 1; |
706
|
0
|
0
|
|
|
|
|
print STDERR "[TRACE] $message\n" if $ENV{DC_TRACE} == 2; |
707
|
|
|
|
|
|
|
} |
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
1; |
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
__DATA__ |
712
|
|
|
|
|
|
|
#!/bin/sh |
713
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
# [% HEADER %] |
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
### BEGIN INIT INFO |
717
|
|
|
|
|
|
|
# Provides: [% NAME %] |
718
|
|
|
|
|
|
|
# Required-Start: [% REQUIRED_START %] |
719
|
|
|
|
|
|
|
# Required-Stop: [% REQUIRED_STOP %] |
720
|
|
|
|
|
|
|
# Default-Start: 2 3 4 5 |
721
|
|
|
|
|
|
|
# Default-Stop: 0 1 6 |
722
|
|
|
|
|
|
|
# Short-Description: [% SHORT_DESCRIPTION %] |
723
|
|
|
|
|
|
|
# Description: [% DESCRIPTION %] |
724
|
|
|
|
|
|
|
### END INIT INFO` |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
[% INIT_SOURCE_FILE %] |
727
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
[% INIT_CODE_BLOCK %] |
729
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
if [ -x [% SCRIPT %] ]; |
731
|
|
|
|
|
|
|
then |
732
|
|
|
|
|
|
|
[% SCRIPT %] $1 |
733
|
|
|
|
|
|
|
else |
734
|
|
|
|
|
|
|
echo "Required program [% SCRIPT %] not found!" |
735
|
|
|
|
|
|
|
exit 1; |
736
|
|
|
|
|
|
|
fi |
737
|
|
|
|
|
|
|
__END__ |
738
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
=encoding utf8 |
740
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
=head1 NAME |
742
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
Daemon::Control - Create init scripts in Perl |
744
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
=head1 DESCRIPTION |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
Daemon::Control provides a library for creating init scripts in perl. |
748
|
|
|
|
|
|
|
Your perl script just needs to set the accessors for what and how you |
749
|
|
|
|
|
|
|
want something to run and the library takes care of the rest. |
750
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
You can launch programs through the shell (C</usr/sbin/my_program>) or |
752
|
|
|
|
|
|
|
launch Perl code itself into a daemon mode. Single and double fork |
753
|
|
|
|
|
|
|
methods are supported, and in double-fork mode all the things you would |
754
|
|
|
|
|
|
|
expect such as reopening STDOUT/STDERR, switching UID/GID etc are supported. |
755
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
=head1 SYNOPSIS |
757
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
Write a program that describes the daemon: |
759
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
#!/usr/bin/perl |
761
|
|
|
|
|
|
|
use warnings; |
762
|
|
|
|
|
|
|
use strict; |
763
|
|
|
|
|
|
|
use Daemon::Control; |
764
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
exit Daemon::Control->new( |
766
|
|
|
|
|
|
|
name => "My Daemon", |
767
|
|
|
|
|
|
|
lsb_start => '$syslog $remote_fs', |
768
|
|
|
|
|
|
|
lsb_stop => '$syslog', |
769
|
|
|
|
|
|
|
lsb_sdesc => 'My Daemon Short', |
770
|
|
|
|
|
|
|
lsb_desc => 'My Daemon controls the My Daemon daemon.', |
771
|
|
|
|
|
|
|
path => '/home/symkat/etc/init.d/program', |
772
|
|
|
|
|
|
|
|
773
|
|
|
|
|
|
|
program => '/home/symkat/bin/program', |
774
|
|
|
|
|
|
|
program_args => [ '-a', 'orange', '--verbose' ], |
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
pid_file => '/tmp/mydaemon.pid', |
777
|
|
|
|
|
|
|
stderr_file => '/tmp/mydaemon.out', |
778
|
|
|
|
|
|
|
stdout_file => '/tmp/mydaemon.out', |
779
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
fork => 2, |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
)->run; |
783
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
By default C<run> will use @ARGV for the action, and exit with an LSB compatible |
785
|
|
|
|
|
|
|
exit code. For finer control, you can use C<run_command>, which will return |
786
|
|
|
|
|
|
|
the exit code, and accepts the action as an argument. This enables more programatic |
787
|
|
|
|
|
|
|
control, as well as running multiple instances of L<Daemon::Control> from one script. |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
my $daemon = Daemon::Control->new( |
790
|
|
|
|
|
|
|
... |
791
|
|
|
|
|
|
|
); |
792
|
|
|
|
|
|
|
my $exit = $daemon->run_command(âstartâ); |
793
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
You can then call the program: |
795
|
|
|
|
|
|
|
|
796
|
|
|
|
|
|
|
/home/symkat/etc/init.d/program start |
797
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
You can also make an LSB compatible init script: |
799
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
/home/symkat/etc/init.d/program get_init_file > /etc/init.d/program |
801
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
|
804
|
|
|
|
|
|
|
=head1 CONSTRUCTOR |
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
The constructor takes the following arguments as a list or a hash ref. |
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
=head2 name |
809
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
The name of the program the daemon is controlling. This will be used in |
811
|
|
|
|
|
|
|
status messages "name [Started]" and the name for the LSB init script |
812
|
|
|
|
|
|
|
that is generated. |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
=head2 program |
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
This can be a coderef or the path to a shell program that is to be run. |
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
$daemon->program( sub { ... } ); |
819
|
|
|
|
|
|
|
|
820
|
|
|
|
|
|
|
$daemon->program( "/usr/sbin/http" ); |
821
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
=head2 program_args |
823
|
|
|
|
|
|
|
|
824
|
|
|
|
|
|
|
This is an array ref of the arguments for the program. In the context |
825
|
|
|
|
|
|
|
of a coderef being executed this will be given to the coderef as @_, |
826
|
|
|
|
|
|
|
the Daemon::Control instance that called the coderef will be passed |
827
|
|
|
|
|
|
|
as the first arguments. Your arguments start at $_[1]. |
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
In the context of a shell program, it will be given as arguments to |
830
|
|
|
|
|
|
|
be executed. |
831
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
$daemon->program_args( [ 'foo', 'bar' ] ); |
833
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
$daemon->program_args( [ '--switch', 'argument' ] ); |
835
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
=head2 user |
837
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
When set, the username supplied to this accessor will be used to set |
839
|
|
|
|
|
|
|
the UID attribute. When this is used, C<uid> will be changed from |
840
|
|
|
|
|
|
|
its initial settings if you set it (which you shouldn't, since you're |
841
|
|
|
|
|
|
|
using usernames instead of UIDs). See L</uid> for setting numerical |
842
|
|
|
|
|
|
|
user ids. |
843
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
$daemon->user('www-data'); |
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
=head2 group |
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
When set, the groupname supplied to this accessor will be used to set |
849
|
|
|
|
|
|
|
the GID attribute. When this is used, C<gid> will be changed from |
850
|
|
|
|
|
|
|
its initial settings if you set it (which you shouldn't, since you're |
851
|
|
|
|
|
|
|
using groupnames instead of GIDs). See L</gid> for setting numerical |
852
|
|
|
|
|
|
|
group ids. |
853
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
$daemon->group('www-data'); |
855
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
=head2 uid |
857
|
|
|
|
|
|
|
|
858
|
|
|
|
|
|
|
If provided, the UID that the program will drop to when forked. This is |
859
|
|
|
|
|
|
|
ONLY supported in double-fork mode and will only work if you are running |
860
|
|
|
|
|
|
|
as root. Accepts numeric UID. For usernames please see L</user>. |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
$daemon->uid( 1001 ); |
863
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
=head2 gid |
865
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
If provided, the GID that the program will drop to when forked. This is |
867
|
|
|
|
|
|
|
ONLY supported in double-fork mode and will only work if you are running |
868
|
|
|
|
|
|
|
as root. Accepts numeric GID, for groupnames please see L</group>. |
869
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
$daemon->gid( 1001 ); |
871
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
=head2 umask |
873
|
|
|
|
|
|
|
|
874
|
|
|
|
|
|
|
If provided, the umask of the daemon will be set to the umask provided, |
875
|
|
|
|
|
|
|
note that the umask must be in oct. By default the umask will not be |
876
|
|
|
|
|
|
|
changed. |
877
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
$daemon->umask( 022 ); |
879
|
|
|
|
|
|
|
|
880
|
|
|
|
|
|
|
Or: |
881
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
$daemon->umask( oct("022") ); |
883
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
=head2 directory |
885
|
|
|
|
|
|
|
|
886
|
|
|
|
|
|
|
If provided, chdir to this directory before execution. |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
=head2 path |
889
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
The path of the script you are using Daemon::Control in. This will be used in |
891
|
|
|
|
|
|
|
the LSB file generation to point it to the location of the script. If this is |
892
|
|
|
|
|
|
|
not provided, the absolute path of $0 will be used. |
893
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
=head2 init_config |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
The name of the init config file to load. When provided your init script will |
897
|
|
|
|
|
|
|
source this file to include the environment variables. This is useful for setting |
898
|
|
|
|
|
|
|
a C<PERL5LIB> and such things. |
899
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
$daemon->init_config( "/etc/default/my_program" ); |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
If you are using perlbrew, you probably want to set your init_config to |
903
|
|
|
|
|
|
|
C<$ENV{PERLBREW_ROOT} . '/etc/bashrc'>. |
904
|
|
|
|
|
|
|
|
905
|
|
|
|
|
|
|
=head2 init_code |
906
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
When given, whatever text is in this field will be dumped directly into |
908
|
|
|
|
|
|
|
the generated init file. |
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
$daemon->init_code( "Arbitrary code goes here." ) |
911
|
|
|
|
|
|
|
|
912
|
|
|
|
|
|
|
=head2 help |
913
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
Any text in this accessor will be printed when the script is called |
915
|
|
|
|
|
|
|
with the argument C<--help> or <help>. |
916
|
|
|
|
|
|
|
|
917
|
|
|
|
|
|
|
$daemon->help( "Read The Friendly Source." ); |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
=head2 redirect_before_fork |
920
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
By default this is set to true. STDOUT will be redirected to C<stdout_file>, |
922
|
|
|
|
|
|
|
and STDERR will be redirected to C<stderr_file>. Setting this to 0 will disable |
923
|
|
|
|
|
|
|
redirecting before a double fork. This is useful when you are using a code |
924
|
|
|
|
|
|
|
reference and would like to leave the filehandles alone until you're in control. |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
Call C<< ->redirect_filehandles >> on the Daemon::Control instance your coderef is |
927
|
|
|
|
|
|
|
passed to redirect the filehandles. |
928
|
|
|
|
|
|
|
|
929
|
|
|
|
|
|
|
=head2 stdout_file |
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
If provided stdout will be redirected to the given file. This is only supported |
932
|
|
|
|
|
|
|
in double fork mode. |
933
|
|
|
|
|
|
|
|
934
|
|
|
|
|
|
|
$daemon->stdout_file( "/tmp/mydaemon.stdout" ); |
935
|
|
|
|
|
|
|
|
936
|
|
|
|
|
|
|
Alternatively, you can specify an arrayref of arguments to C<open()>: |
937
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
$daemon->stdout_file( [ '>', '/tmp/overwrite-every-run' ] ); |
939
|
|
|
|
|
|
|
$daemon->stdout_file( [ '|-', 'my_pipe_program', '-a foo' ] ); |
940
|
|
|
|
|
|
|
|
941
|
|
|
|
|
|
|
=head2 stderr_file |
942
|
|
|
|
|
|
|
|
943
|
|
|
|
|
|
|
If provided stderr will be redirected to the given file. This is only supported |
944
|
|
|
|
|
|
|
in double fork mode. |
945
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
$daemon->stderr_file( "/tmp/mydaemon.stderr" ); |
947
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
Alternatively, you can specify an arrayref of arguments to C<open()>: |
949
|
|
|
|
|
|
|
|
950
|
|
|
|
|
|
|
$daemon->stderr_file( [ '>', '/tmp/overwrite-every-run' ] ); |
951
|
|
|
|
|
|
|
$daemon->stderr_file( [ '|-', 'my_pipe_program', '-a foo' ] ); |
952
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
=head2 pid_file |
954
|
|
|
|
|
|
|
|
955
|
|
|
|
|
|
|
The location of the PID file to use. Warning: if using single-fork mode, it is |
956
|
|
|
|
|
|
|
recommended to set this to the file which the daemon launching in single-fork |
957
|
|
|
|
|
|
|
mode will put its PID. Failure to follow this will most likely result in status, |
958
|
|
|
|
|
|
|
stop, and restart not working. |
959
|
|
|
|
|
|
|
|
960
|
|
|
|
|
|
|
$daemon->pid_file( "/var/run/mydaemon/mydaemon.pid" ); |
961
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
=head2 resource_dir |
963
|
|
|
|
|
|
|
|
964
|
|
|
|
|
|
|
This directory will be created, and chowned to the user/group provided in |
965
|
|
|
|
|
|
|
C<user>, and C<group>. |
966
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
$daemon->resource_dir( "/var/run/mydaemon" ); |
968
|
|
|
|
|
|
|
|
969
|
|
|
|
|
|
|
=head2 prereq_no_process -- EXPERIMENTAL |
970
|
|
|
|
|
|
|
|
971
|
|
|
|
|
|
|
This option is EXPERIMENTAL and defaults to OFF. |
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
If this is set, then the C<ps> list will be checked at startup for any |
974
|
|
|
|
|
|
|
processes that look like the daemon to be started. By default the pattern used |
975
|
|
|
|
|
|
|
is C<< /\b<program name>\b/ >>, but you can pass an override regexp in this field |
976
|
|
|
|
|
|
|
instead (to use the default pattern, just pass C<< prereq_no_process => 1 >>). |
977
|
|
|
|
|
|
|
If matching processes are found, those pids are output, and the daemon will not |
978
|
|
|
|
|
|
|
start. |
979
|
|
|
|
|
|
|
|
980
|
|
|
|
|
|
|
This may produce some false positives on your system, depending on what else is |
981
|
|
|
|
|
|
|
running on your system, but it may still be of some use, e.g. if you seem to |
982
|
|
|
|
|
|
|
have daemons left running where the associated pid file is getting deleted |
983
|
|
|
|
|
|
|
somehow. |
984
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
=head2 fork |
986
|
|
|
|
|
|
|
|
987
|
|
|
|
|
|
|
The mode to use for fork. By default a double-fork will be used. |
988
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
In double-fork, uid, gid, std*_file, and a number of other things are |
990
|
|
|
|
|
|
|
supported. A traditional double-fork is used and setsid is called. |
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
In single-fork none of the above are called, and it is the responsibility |
993
|
|
|
|
|
|
|
of whatever you're forking to reopen files, associate with the init process |
994
|
|
|
|
|
|
|
and do all that fun stuff. This mode is recommended when the program you want |
995
|
|
|
|
|
|
|
to control has its own daemonizing code. It is important to note that the PID |
996
|
|
|
|
|
|
|
file should be set to whatever PID file is used by the daemon. |
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
In no-fork mode, C<fork(0)>, the program is run in the foreground. By default |
999
|
|
|
|
|
|
|
quiet is still turned off, so status updates will be shown on the screen such |
1000
|
|
|
|
|
|
|
as that the daemon started. A shortcut to turn status off and go into foreground |
1001
|
|
|
|
|
|
|
mode is C<foreground> being set to 1, or C<DC_FOREGROUND> being set as an |
1002
|
|
|
|
|
|
|
environment variable. Additionally, calling C<foreground> instead of C<start> will |
1003
|
|
|
|
|
|
|
override the forking mode at run-time. |
1004
|
|
|
|
|
|
|
|
1005
|
|
|
|
|
|
|
$daemon->fork( 0 ); |
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
$daemon->fork( 1 ); |
1008
|
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
|
$daemon->fork( 2 ); # Default |
1010
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
=head2 scan_name |
1012
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
This provides an extra check to see if the program is running. Normally |
1014
|
|
|
|
|
|
|
we only check that the PID listed in the PID file is running. When given |
1015
|
|
|
|
|
|
|
a regular expression, we will also match the name of the program as shown |
1016
|
|
|
|
|
|
|
in ps. |
1017
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
$daemon->scan_name( qr|mydaemon| ); |
1019
|
|
|
|
|
|
|
|
1020
|
|
|
|
|
|
|
=head2 kill_timeout |
1021
|
|
|
|
|
|
|
|
1022
|
|
|
|
|
|
|
This provides an amount of time in seconds between kill signals being |
1023
|
|
|
|
|
|
|
sent to the daemon. This value should be increased if your daemon has |
1024
|
|
|
|
|
|
|
a longer shutdown period. By default 1 second is used. |
1025
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
$daemon->kill_timeout( 7 ); |
1027
|
|
|
|
|
|
|
|
1028
|
|
|
|
|
|
|
=head2 lsb_start |
1029
|
|
|
|
|
|
|
|
1030
|
|
|
|
|
|
|
The value of this string is used for the 'Required-Start' value of |
1031
|
|
|
|
|
|
|
the generated LSB init script. See L<http://wiki.debian.org/LSBInitScripts> |
1032
|
|
|
|
|
|
|
for more information. |
1033
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
$daemon->lsb_start( '$remote_fs $syslog' ); |
1035
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
=head2 lsb_stop |
1037
|
|
|
|
|
|
|
|
1038
|
|
|
|
|
|
|
The value of this string is used for the 'Required-Stop' value of |
1039
|
|
|
|
|
|
|
the generated LSB init script. See L<http://wiki.debian.org/LSBInitScripts> |
1040
|
|
|
|
|
|
|
for more information. |
1041
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
$daemon->lsb_stop( '$remote_fs $syslog' ); |
1043
|
|
|
|
|
|
|
|
1044
|
|
|
|
|
|
|
=head2 lsb_sdesc |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
The value of this string is used for the 'Short-Description' value of |
1047
|
|
|
|
|
|
|
the generated LSB init script. See L<http://wiki.debian.org/LSBInitScripts> |
1048
|
|
|
|
|
|
|
for more information. |
1049
|
|
|
|
|
|
|
|
1050
|
|
|
|
|
|
|
$daemon->lsb_sdesc( 'My program...' ); |
1051
|
|
|
|
|
|
|
|
1052
|
|
|
|
|
|
|
=head2 lsb_desc |
1053
|
|
|
|
|
|
|
|
1054
|
|
|
|
|
|
|
The value of this string is used for the 'Description' value of |
1055
|
|
|
|
|
|
|
the generated LSB init script. See L<http://wiki.debian.org/LSBInitScripts> |
1056
|
|
|
|
|
|
|
for more information. |
1057
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
$daemon->lsb_desc( 'My program controls a thing that does a thing.' ); |
1059
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
=head2 quiet |
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
If this boolean flag is set to a true value all output from the init script |
1063
|
|
|
|
|
|
|
(NOT your daemon) to STDOUT will be suppressed. |
1064
|
|
|
|
|
|
|
|
1065
|
|
|
|
|
|
|
$daemon->quiet( 1 ); |
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
=head2 reload_signal |
1068
|
|
|
|
|
|
|
|
1069
|
|
|
|
|
|
|
The signal to send to the daemon when reloading it. |
1070
|
|
|
|
|
|
|
Default signal is C<HUP>. |
1071
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
=head2 stop_signals |
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
An array ref of signals that should be tried (in order) when |
1075
|
|
|
|
|
|
|
stopping the daemon. |
1076
|
|
|
|
|
|
|
Default signals are C<TERM>, C<TERM>, C<INT> and C<KILL> (yes, C<TERM> |
1077
|
|
|
|
|
|
|
is tried twice). |
1078
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
=head1 PLUGINS |
1080
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
Daemon Control supports a simple plugin system using L<Role::Tiny>. |
1082
|
|
|
|
|
|
|
|
1083
|
|
|
|
|
|
|
=head2 with_plugins |
1084
|
|
|
|
|
|
|
|
1085
|
|
|
|
|
|
|
With plugins adds the plugins to Daemon::Control. |
1086
|
|
|
|
|
|
|
|
1087
|
|
|
|
|
|
|
Daemon::Control->with_plugins( qw( MyFirstPlugin +MySecondPlugin) )->new( |
1088
|
|
|
|
|
|
|
... |
1089
|
|
|
|
|
|
|
); |
1090
|
|
|
|
|
|
|
|
1091
|
|
|
|
|
|
|
Note: |
1092
|
|
|
|
|
|
|
|
1093
|
|
|
|
|
|
|
MyFirstPlugin will load Daemon::Control::Plugin::MyFirstPlugin |
1094
|
|
|
|
|
|
|
|
1095
|
|
|
|
|
|
|
+MySecondPlugin will load MySecondPlugin |
1096
|
|
|
|
|
|
|
|
1097
|
|
|
|
|
|
|
|
1098
|
|
|
|
|
|
|
=head2 Writing A Plugin |
1099
|
|
|
|
|
|
|
|
1100
|
|
|
|
|
|
|
Your plugin should use the name Daemon::Control::Plugin::YourModuleName and |
1101
|
|
|
|
|
|
|
YourModuleName should reasonably match the effect your plugin has on |
1102
|
|
|
|
|
|
|
Daemon::Control. |
1103
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
You can replace Daemon::Control methods by writing your own and using |
1105
|
|
|
|
|
|
|
Role::Tiny within your class to allow it to be composed into Daemon::Control. |
1106
|
|
|
|
|
|
|
|
1107
|
|
|
|
|
|
|
The default Daemon::Control ships with no dependancies and supports Perl |
1108
|
|
|
|
|
|
|
5.8.1+, to use the plugin system your module MUST declare dependency on |
1109
|
|
|
|
|
|
|
L<Role::Tiny> and if you wish to use the C<around>, C<before> and C<after> |
1110
|
|
|
|
|
|
|
your module MUST declare dependance on L<Class::Method::Modifiers> in your |
1111
|
|
|
|
|
|
|
package. |
1112
|
|
|
|
|
|
|
|
1113
|
|
|
|
|
|
|
=head1 METHODS |
1114
|
|
|
|
|
|
|
|
1115
|
|
|
|
|
|
|
=head2 run_command |
1116
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
This function will process an action on the Daemon::Control instance. |
1118
|
|
|
|
|
|
|
Valid arguments are those which a C<do_> method exists for, such as |
1119
|
|
|
|
|
|
|
B<start>, B<stop>, B<restart>. Returns the LSB exit code for the |
1120
|
|
|
|
|
|
|
action processed. |
1121
|
|
|
|
|
|
|
|
1122
|
|
|
|
|
|
|
=head2 run |
1123
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
This will make your program act as an init file, accepting input from |
1125
|
|
|
|
|
|
|
the command line. Run will exit with 0 for success and uses LSB exit |
1126
|
|
|
|
|
|
|
codes. As such no code should be used after ->run is called. Any code |
1127
|
|
|
|
|
|
|
in your file should be before this. This is a shortcut for |
1128
|
|
|
|
|
|
|
|
1129
|
|
|
|
|
|
|
exit Daemon::Control->new(...)->run_command( @ARGV ); |
1130
|
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
=head2 do_start |
1132
|
|
|
|
|
|
|
|
1133
|
|
|
|
|
|
|
Is called when start is given as an argument. Starts the forking and |
1134
|
|
|
|
|
|
|
exits. Called by: |
1135
|
|
|
|
|
|
|
|
1136
|
|
|
|
|
|
|
/usr/bin/my_program_launcher.pl start |
1137
|
|
|
|
|
|
|
|
1138
|
|
|
|
|
|
|
=head2 do_foreground |
1139
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
Is called when B<foreground> is given as an argument. Starts the |
1141
|
|
|
|
|
|
|
program or code reference and stays in the foreground -- no forking |
1142
|
|
|
|
|
|
|
is done, regardless of the compile-time arguments. Additionally, |
1143
|
|
|
|
|
|
|
turns C<quiet> on to avoid showing L<Daemon::Control> output. |
1144
|
|
|
|
|
|
|
|
1145
|
|
|
|
|
|
|
/usr/bin/my_program_launcher.pl foreground |
1146
|
|
|
|
|
|
|
|
1147
|
|
|
|
|
|
|
=head2 do_stop |
1148
|
|
|
|
|
|
|
|
1149
|
|
|
|
|
|
|
Is called when stop is given as an argument. Stops the running program |
1150
|
|
|
|
|
|
|
if it can. Called by: |
1151
|
|
|
|
|
|
|
|
1152
|
|
|
|
|
|
|
/usr/bin/my_program_launcher.pl stop |
1153
|
|
|
|
|
|
|
|
1154
|
|
|
|
|
|
|
=head2 do_restart |
1155
|
|
|
|
|
|
|
|
1156
|
|
|
|
|
|
|
Is called when restart is given as an argument. Calls do_stop and do_start. |
1157
|
|
|
|
|
|
|
Called by: |
1158
|
|
|
|
|
|
|
|
1159
|
|
|
|
|
|
|
/usr/bin/my_program_launcher.pl restart |
1160
|
|
|
|
|
|
|
|
1161
|
|
|
|
|
|
|
=head2 do_reload |
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
Is called when reload is given as an argument. Sends the signal |
1164
|
|
|
|
|
|
|
C<reload_signal> to the daemon. |
1165
|
|
|
|
|
|
|
|
1166
|
|
|
|
|
|
|
/usr/bin/my_program_launcher.pl reload |
1167
|
|
|
|
|
|
|
|
1168
|
|
|
|
|
|
|
=head2 do_status |
1169
|
|
|
|
|
|
|
|
1170
|
|
|
|
|
|
|
Is called when status is given as an argument. Displays the status of the |
1171
|
|
|
|
|
|
|
program, basic on the PID file. Called by: |
1172
|
|
|
|
|
|
|
|
1173
|
|
|
|
|
|
|
/usr/bin/my_program_launcher.pl status |
1174
|
|
|
|
|
|
|
|
1175
|
|
|
|
|
|
|
=head2 do_get_init_file |
1176
|
|
|
|
|
|
|
|
1177
|
|
|
|
|
|
|
Is called when get_init_file is given as an argument. Dumps an LSB |
1178
|
|
|
|
|
|
|
compatible init file, for use in /etc/init.d/. Called by: |
1179
|
|
|
|
|
|
|
|
1180
|
|
|
|
|
|
|
/usr/bin/my_program_launcher.pl get_init_file |
1181
|
|
|
|
|
|
|
|
1182
|
|
|
|
|
|
|
=head2 pretty_print |
1183
|
|
|
|
|
|
|
|
1184
|
|
|
|
|
|
|
This is used to display status to the user. It accepts a message and a color. |
1185
|
|
|
|
|
|
|
It will default to green text, if no color is explicitly given. Only supports |
1186
|
|
|
|
|
|
|
red and green. |
1187
|
|
|
|
|
|
|
|
1188
|
|
|
|
|
|
|
$daemon->pretty_print( "My Status", "red" ); |
1189
|
|
|
|
|
|
|
|
1190
|
|
|
|
|
|
|
=head2 write_pid |
1191
|
|
|
|
|
|
|
|
1192
|
|
|
|
|
|
|
This will write the PID to the file in pid_file. |
1193
|
|
|
|
|
|
|
|
1194
|
|
|
|
|
|
|
=head2 read_pid |
1195
|
|
|
|
|
|
|
|
1196
|
|
|
|
|
|
|
This will read the PID from the file in pid_file and set it in pid. |
1197
|
|
|
|
|
|
|
|
1198
|
|
|
|
|
|
|
=head2 pid |
1199
|
|
|
|
|
|
|
|
1200
|
|
|
|
|
|
|
An accessor for the PID. Set by read_pid, or when the program is started. |
1201
|
|
|
|
|
|
|
|
1202
|
|
|
|
|
|
|
=head2 dump_init_script |
1203
|
|
|
|
|
|
|
|
1204
|
|
|
|
|
|
|
A function to dump the LSB compatible init script. Used by do_get_init_file. |
1205
|
|
|
|
|
|
|
|
1206
|
|
|
|
|
|
|
=head1 AUTHOR |
1207
|
|
|
|
|
|
|
|
1208
|
|
|
|
|
|
|
Kaitlyn Parkhurst (SymKat) I<E<lt>symkat@symkat.comE<gt>> ( Blog: L<http://symkat.com/> ) |
1209
|
|
|
|
|
|
|
|
1210
|
|
|
|
|
|
|
=head2 CONTRIBUTORS |
1211
|
|
|
|
|
|
|
|
1212
|
|
|
|
|
|
|
=over 4 |
1213
|
|
|
|
|
|
|
|
1214
|
|
|
|
|
|
|
=item * Matt S. Trout (mst) I<E<lt>mst@shadowcat.co.ukE<gt>> |
1215
|
|
|
|
|
|
|
|
1216
|
|
|
|
|
|
|
=item * Mike Doherty (doherty) I<E<lt>doherty@cpan.orgE<gt>> |
1217
|
|
|
|
|
|
|
|
1218
|
|
|
|
|
|
|
=item * Karen Etheridge (ether) I<E<lt>ether@cpan.orgE<gt>> |
1219
|
|
|
|
|
|
|
|
1220
|
|
|
|
|
|
|
=item * Ãvar Arnfjörð Bjarmason (avar) I<E<lt>avar@cpan.orgE<gt>> |
1221
|
|
|
|
|
|
|
|
1222
|
|
|
|
|
|
|
=item * Kieren Diment I<E<lt>zarquon@cpan.org<gt>> |
1223
|
|
|
|
|
|
|
|
1224
|
|
|
|
|
|
|
=item * Mark Curtis I<E<lt>mark.curtis@affinitylive.com<gt>> |
1225
|
|
|
|
|
|
|
|
1226
|
|
|
|
|
|
|
=item * Zoffix Znet I<E<lt>zoffix@cpan.org<gt>> |
1227
|
|
|
|
|
|
|
|
1228
|
|
|
|
|
|
|
=back |
1229
|
|
|
|
|
|
|
|
1230
|
|
|
|
|
|
|
=head2 SPONSORS |
1231
|
|
|
|
|
|
|
|
1232
|
|
|
|
|
|
|
Parts of this code were paid for by |
1233
|
|
|
|
|
|
|
|
1234
|
|
|
|
|
|
|
=over 4 |
1235
|
|
|
|
|
|
|
|
1236
|
|
|
|
|
|
|
=item (mt) Media Temple L<http://www.mediatemple.net> |
1237
|
|
|
|
|
|
|
|
1238
|
|
|
|
|
|
|
=back |
1239
|
|
|
|
|
|
|
|
1240
|
|
|
|
|
|
|
=head1 COPYRIGHT |
1241
|
|
|
|
|
|
|
|
1242
|
|
|
|
|
|
|
Copyright (c) 2012 the Daemon::Control L</AUTHOR>, L</CONTRIBUTORS>, and L</SPONSORS> as listed above. |
1243
|
|
|
|
|
|
|
|
1244
|
|
|
|
|
|
|
=head1 LICENSE |
1245
|
|
|
|
|
|
|
|
1246
|
|
|
|
|
|
|
This library is free software and may be distributed under the same terms as perl itself. |
1247
|
|
|
|
|
|
|
|
1248
|
|
|
|
|
|
|
=head2 AVAILABILITY |
1249
|
|
|
|
|
|
|
|
1250
|
|
|
|
|
|
|
The most current version of Daemon::Control can be found at L<https://github.com/symkat/Daemon-Control> |