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