| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
8
|
|
|
8
|
|
527078
|
use strict; |
|
|
8
|
|
|
|
|
11
|
|
|
|
8
|
|
|
|
|
193
|
|
|
2
|
8
|
|
|
8
|
|
23
|
use warnings; |
|
|
8
|
|
|
|
|
8
|
|
|
|
8
|
|
|
|
|
383
|
|
|
3
|
|
|
|
|
|
|
package MooseX::Daemonize; # git description: v0.20-8-g6d23389 |
|
4
|
|
|
|
|
|
|
# ABSTRACT: Role for daemonizing your Moose based application |
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '0.21'; |
|
7
|
|
|
|
|
|
|
|
|
8
|
8
|
|
|
8
|
|
1410
|
use Moose::Role; |
|
|
8
|
|
|
|
|
947678
|
|
|
|
8
|
|
|
|
|
32
|
|
|
9
|
8
|
|
|
8
|
|
30279
|
use MooseX::Types::Path::Class; |
|
|
8
|
|
|
|
|
2195731
|
|
|
|
8
|
|
|
|
|
64
|
|
|
10
|
8
|
|
|
8
|
|
5037
|
use File::Path qw(make_path); |
|
|
8
|
|
|
|
|
12
|
|
|
|
8
|
|
|
|
|
401
|
|
|
11
|
8
|
|
|
8
|
|
33
|
use namespace::autoclean; |
|
|
8
|
|
|
|
|
8
|
|
|
|
8
|
|
|
|
|
46
|
|
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
with 'MooseX::Daemonize::WithPidFile', |
|
14
|
|
|
|
|
|
|
'MooseX::Getopt'; |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub OK () { 0 } |
|
17
|
|
|
|
|
|
|
sub ERROR () { 1 } |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
has progname => ( |
|
20
|
|
|
|
|
|
|
metaclass => 'Getopt', |
|
21
|
|
|
|
|
|
|
isa => 'Str', |
|
22
|
|
|
|
|
|
|
is => 'ro', |
|
23
|
|
|
|
|
|
|
lazy => 1, |
|
24
|
|
|
|
|
|
|
required => 1, |
|
25
|
|
|
|
|
|
|
default => sub { |
|
26
|
|
|
|
|
|
|
( my $name = lc $_[0]->meta->name ) =~ s/::/_/g; |
|
27
|
|
|
|
|
|
|
return $name; |
|
28
|
|
|
|
|
|
|
}, |
|
29
|
|
|
|
|
|
|
documentation => 'the name of the daemon', |
|
30
|
|
|
|
|
|
|
); |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
has pidbase => ( |
|
33
|
|
|
|
|
|
|
metaclass => 'Getopt', |
|
34
|
|
|
|
|
|
|
isa => 'Path::Class::Dir', |
|
35
|
|
|
|
|
|
|
is => 'ro', |
|
36
|
|
|
|
|
|
|
coerce => 1, |
|
37
|
|
|
|
|
|
|
required => 1, |
|
38
|
|
|
|
|
|
|
lazy => 1, |
|
39
|
|
|
|
|
|
|
default => sub { Path::Class::Dir->new('', 'var', 'run') }, |
|
40
|
|
|
|
|
|
|
documentation => 'the base for our pid (default: /var/run)', |
|
41
|
|
|
|
|
|
|
); |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
has basedir => ( |
|
44
|
|
|
|
|
|
|
metaclass => 'Getopt', |
|
45
|
|
|
|
|
|
|
isa => 'Path::Class::Dir', |
|
46
|
|
|
|
|
|
|
is => 'ro', |
|
47
|
|
|
|
|
|
|
coerce => 1, |
|
48
|
|
|
|
|
|
|
required => 1, |
|
49
|
|
|
|
|
|
|
lazy => 1, |
|
50
|
|
|
|
|
|
|
default => sub { Path::Class::Dir->new('/') }, |
|
51
|
|
|
|
|
|
|
documentation => 'the directory to chdir to (default: /)', |
|
52
|
|
|
|
|
|
|
); |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
has foreground => ( |
|
55
|
|
|
|
|
|
|
metaclass => 'Getopt', |
|
56
|
|
|
|
|
|
|
cmd_aliases => 'f', |
|
57
|
|
|
|
|
|
|
isa => 'Bool', |
|
58
|
|
|
|
|
|
|
is => 'ro', |
|
59
|
|
|
|
|
|
|
default => sub { 0 }, |
|
60
|
|
|
|
|
|
|
documentation => 'if true, the process won\'t background', |
|
61
|
|
|
|
|
|
|
); |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
has stop_timeout => ( |
|
64
|
|
|
|
|
|
|
metaclass => 'Getopt', |
|
65
|
|
|
|
|
|
|
isa => 'Int', |
|
66
|
|
|
|
|
|
|
is => 'rw', |
|
67
|
|
|
|
|
|
|
default => sub { 2 }, |
|
68
|
|
|
|
|
|
|
documentation => 'number of seconds to wait for the process to stop, before trying harder to kill it (default: 2 s)', |
|
69
|
|
|
|
|
|
|
); |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
# internal book-keeping |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
has status_message => ( |
|
74
|
|
|
|
|
|
|
metaclass => 'NoGetopt', |
|
75
|
|
|
|
|
|
|
isa => 'Str', |
|
76
|
|
|
|
|
|
|
is => 'rw', |
|
77
|
|
|
|
|
|
|
clearer => 'clear_status_message', |
|
78
|
|
|
|
|
|
|
); |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
has exit_code => ( |
|
81
|
|
|
|
|
|
|
metaclass => 'NoGetopt', |
|
82
|
|
|
|
|
|
|
isa => 'Int', |
|
83
|
|
|
|
|
|
|
is => 'rw', |
|
84
|
|
|
|
|
|
|
clearer => 'clear_exit_code', |
|
85
|
|
|
|
|
|
|
); |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# methods ... |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
## PID file related stuff ... |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub init_pidfile { |
|
92
|
7
|
|
|
7
|
1
|
25
|
my $self = shift; |
|
93
|
7
|
|
|
|
|
222
|
my $file = $self->pidbase . '/' . $self->progname . '.pid'; |
|
94
|
|
|
|
|
|
|
|
|
95
|
7
|
100
|
|
|
|
208
|
if ( !-d $self->pidbase ) { |
|
96
|
3
|
|
|
|
|
228
|
make_path( $self->pidbase, { error => \my $err } ); |
|
97
|
3
|
50
|
|
|
|
828
|
if (@$err) { |
|
98
|
0
|
|
|
|
|
0
|
confess sprintf( "Cannot create pidbase directory '%s': %s", |
|
99
|
|
|
|
|
|
|
$self->pidbase, @$err ); |
|
100
|
|
|
|
|
|
|
} |
|
101
|
|
|
|
|
|
|
} |
|
102
|
|
|
|
|
|
|
|
|
103
|
7
|
100
|
|
|
|
624
|
confess "Cannot write to $file" unless (-e $file ? -w $file : -w $self->pidbase); |
|
|
|
50
|
|
|
|
|
|
|
104
|
7
|
|
|
|
|
456
|
MooseX::Daemonize::Pid::File->new( file => $file ); |
|
105
|
|
|
|
|
|
|
} |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# backwards compat, |
|
108
|
0
|
|
|
0
|
1
|
0
|
sub check { (shift)->pidfile->is_running } |
|
109
|
0
|
|
|
0
|
1
|
0
|
sub save_pid { (shift)->pidfile->write } |
|
110
|
0
|
|
|
0
|
1
|
0
|
sub remove_pid { (shift)->pidfile->remove } |
|
111
|
0
|
|
|
0
|
1
|
0
|
sub get_pid { (shift)->pidfile->pid } |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
## signal handling ... |
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
sub setup_signals { |
|
116
|
2
|
|
|
2
|
1
|
4
|
my $self = shift; |
|
117
|
2
|
|
|
2
|
|
76
|
$SIG{'INT'} = sub { $self->shutdown }; |
|
|
2
|
|
|
|
|
4568008
|
|
|
118
|
|
|
|
|
|
|
# I can't think of a sane default here really ... |
|
119
|
|
|
|
|
|
|
# $SIG{'HUP'} = sub { $self->handle_sighup }; |
|
120
|
|
|
|
|
|
|
} |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
sub shutdown { |
|
123
|
2
|
|
|
2
|
1
|
5
|
my $self = shift; |
|
124
|
2
|
50
|
|
|
|
88
|
$self->pidfile->remove if $self->pidfile->pid == $$; |
|
125
|
2
|
|
|
|
|
586
|
exit(0); |
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
## daemon control methods ... |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
sub start { |
|
131
|
6
|
|
|
6
|
1
|
390
|
my $self = shift; |
|
132
|
|
|
|
|
|
|
|
|
133
|
6
|
|
|
|
|
615
|
$self->clear_status_message; |
|
134
|
6
|
|
|
|
|
207
|
$self->clear_exit_code; |
|
135
|
|
|
|
|
|
|
|
|
136
|
6
|
50
|
|
|
|
201
|
if ($self->pidfile->is_running) { |
|
137
|
0
|
|
|
|
|
0
|
$self->exit_code($self->OK); |
|
138
|
0
|
|
|
|
|
0
|
$self->status_message('Daemon is already running with pid (' . $self->pidfile->pid . ')'); |
|
139
|
0
|
|
|
|
|
0
|
return !($self->exit_code); |
|
140
|
|
|
|
|
|
|
} |
|
141
|
|
|
|
|
|
|
|
|
142
|
6
|
50
|
|
|
|
510
|
if ($self->foreground) { |
|
143
|
0
|
|
|
|
|
0
|
$self->is_daemon(1); |
|
144
|
|
|
|
|
|
|
} |
|
145
|
|
|
|
|
|
|
else { |
|
146
|
6
|
|
|
|
|
30
|
eval { $self->daemonize }; |
|
|
6
|
|
|
|
|
33
|
|
|
147
|
4
|
50
|
|
|
|
336
|
if ($@) { |
|
148
|
0
|
|
|
|
|
0
|
$self->exit_code($self->ERROR); |
|
149
|
0
|
|
|
|
|
0
|
$self->status_message('Start failed : ' . $@); |
|
150
|
0
|
|
|
|
|
0
|
return !($self->exit_code); |
|
151
|
|
|
|
|
|
|
} |
|
152
|
|
|
|
|
|
|
} |
|
153
|
|
|
|
|
|
|
|
|
154
|
4
|
100
|
|
|
|
124
|
unless ($self->is_daemon) { |
|
155
|
2
|
|
|
|
|
68
|
$self->exit_code($self->OK); |
|
156
|
2
|
|
|
|
|
68
|
$self->status_message('Start succeeded'); |
|
157
|
2
|
|
|
|
|
50
|
return !($self->exit_code); |
|
158
|
|
|
|
|
|
|
} |
|
159
|
|
|
|
|
|
|
|
|
160
|
2
|
|
|
|
|
88
|
$self->pidfile->pid($$); |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# Change to basedir |
|
163
|
2
|
|
|
|
|
61
|
chdir $self->basedir; |
|
164
|
|
|
|
|
|
|
|
|
165
|
2
|
|
|
|
|
106
|
$self->pidfile->write; |
|
166
|
2
|
|
|
|
|
69
|
$self->setup_signals; |
|
167
|
2
|
|
|
|
|
12
|
return $$; |
|
168
|
|
|
|
|
|
|
} |
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
sub status { |
|
171
|
5
|
|
|
5
|
1
|
1220
|
my $self = shift; |
|
172
|
|
|
|
|
|
|
|
|
173
|
5
|
|
|
|
|
173
|
$self->clear_status_message; |
|
174
|
5
|
|
|
|
|
124
|
$self->clear_exit_code; |
|
175
|
|
|
|
|
|
|
|
|
176
|
5
|
100
|
|
|
|
108
|
if ($self->pidfile->is_running) { |
|
177
|
1
|
|
|
|
|
27
|
$self->exit_code($self->OK); |
|
178
|
1
|
|
|
|
|
24
|
$self->status_message('Daemon is running with pid (' . $self->pidfile->pid . ')'); |
|
179
|
|
|
|
|
|
|
} |
|
180
|
|
|
|
|
|
|
else { |
|
181
|
4
|
|
|
|
|
304
|
$self->exit_code($self->ERROR); |
|
182
|
4
|
|
|
|
|
84
|
$self->status_message('Daemon is not running with pid (' . $self->pidfile->pid . ')'); |
|
183
|
|
|
|
|
|
|
} |
|
184
|
|
|
|
|
|
|
|
|
185
|
5
|
|
|
|
|
102
|
return !($self->exit_code); |
|
186
|
|
|
|
|
|
|
} |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
sub restart { |
|
189
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
190
|
|
|
|
|
|
|
|
|
191
|
0
|
|
|
|
|
0
|
$self->clear_status_message; |
|
192
|
0
|
|
|
|
|
0
|
$self->clear_exit_code; |
|
193
|
|
|
|
|
|
|
|
|
194
|
0
|
0
|
|
|
|
0
|
unless ($self->stop) { |
|
195
|
0
|
|
|
|
|
0
|
$self->exit_code($self->ERROR); |
|
196
|
0
|
|
|
|
|
0
|
$self->status_message('Restart (Stop) failed : ' . $@); |
|
197
|
|
|
|
|
|
|
} |
|
198
|
|
|
|
|
|
|
|
|
199
|
0
|
0
|
|
|
|
0
|
unless ($self->start) { |
|
200
|
0
|
|
|
|
|
0
|
$self->exit_code($self->ERROR); |
|
201
|
0
|
|
|
|
|
0
|
$self->status_message('Restart (Start) failed : ' . $@); |
|
202
|
|
|
|
|
|
|
} |
|
203
|
|
|
|
|
|
|
|
|
204
|
0
|
0
|
|
|
|
0
|
if ($self->exit_code == $self->OK) { |
|
205
|
0
|
|
|
|
|
0
|
$self->exit_code($self->OK); |
|
206
|
0
|
|
|
|
|
0
|
$self->status_message("Restart successful"); |
|
207
|
|
|
|
|
|
|
} |
|
208
|
|
|
|
|
|
|
|
|
209
|
0
|
|
|
|
|
0
|
return !($self->exit_code); |
|
210
|
|
|
|
|
|
|
} |
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
# Make _kill *really* private |
|
213
|
|
|
|
|
|
|
my $_kill; |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
sub stop { |
|
216
|
5
|
|
|
5
|
1
|
3001454
|
my $self = shift; |
|
217
|
|
|
|
|
|
|
|
|
218
|
5
|
|
|
|
|
209
|
$self->clear_status_message; |
|
219
|
5
|
|
|
|
|
141
|
$self->clear_exit_code; |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
# if the pid is not running |
|
222
|
|
|
|
|
|
|
# then we don't need to stop |
|
223
|
|
|
|
|
|
|
# anything ... |
|
224
|
5
|
100
|
|
|
|
129
|
if ($self->pidfile->is_running) { |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
# if we are foreground, then |
|
227
|
|
|
|
|
|
|
# no need to try and kill |
|
228
|
|
|
|
|
|
|
# ourselves |
|
229
|
2
|
50
|
|
|
|
56
|
unless ($self->foreground) { |
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
# kill the process ... |
|
232
|
2
|
|
|
|
|
6
|
eval { $self->$_kill($self->pidfile->pid) }; |
|
|
2
|
|
|
|
|
47
|
|
|
233
|
|
|
|
|
|
|
# and complain if we can't ... |
|
234
|
2
|
50
|
|
|
|
13
|
if ($@) { |
|
235
|
0
|
|
|
|
|
0
|
$self->exit_code($self->ERROR); |
|
236
|
0
|
|
|
|
|
0
|
$self->status_message('Stop failed : ' . $@); |
|
237
|
|
|
|
|
|
|
} |
|
238
|
|
|
|
|
|
|
# or gloat if we succeed .. |
|
239
|
|
|
|
|
|
|
else { |
|
240
|
2
|
|
|
|
|
163
|
$self->exit_code($self->OK); |
|
241
|
2
|
|
|
|
|
55
|
$self->status_message('Stop succeeded'); |
|
242
|
|
|
|
|
|
|
} |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
} |
|
245
|
|
|
|
|
|
|
} |
|
246
|
|
|
|
|
|
|
else { |
|
247
|
|
|
|
|
|
|
# this just returns the OK |
|
248
|
|
|
|
|
|
|
# exit code for now, but |
|
249
|
|
|
|
|
|
|
# we should make this overridable |
|
250
|
3
|
|
|
|
|
183
|
$self->exit_code($self->OK); |
|
251
|
3
|
|
|
|
|
63
|
$self->status_message("Not running"); |
|
252
|
|
|
|
|
|
|
} |
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
# if we are returning to our script |
|
255
|
|
|
|
|
|
|
# then we actually need the opposite |
|
256
|
|
|
|
|
|
|
# of what the system/OS expects |
|
257
|
5
|
|
|
|
|
114
|
return !($self->exit_code); |
|
258
|
|
|
|
|
|
|
} |
|
259
|
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
$_kill = sub { |
|
261
|
|
|
|
|
|
|
my ( $self, $pid ) = @_; |
|
262
|
|
|
|
|
|
|
return unless $pid; |
|
263
|
|
|
|
|
|
|
unless ( CORE::kill 0 => $pid ) { |
|
264
|
|
|
|
|
|
|
# warn "$pid already appears dead."; |
|
265
|
|
|
|
|
|
|
return; |
|
266
|
|
|
|
|
|
|
} |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
if ( $pid eq $$ ) { |
|
269
|
|
|
|
|
|
|
die "$pid is us! Can't commit suicide."; |
|
270
|
|
|
|
|
|
|
} |
|
271
|
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
my $timeout = $self->stop_timeout; |
|
273
|
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
# kill 0 => $pid returns 0 if the process is dead |
|
275
|
|
|
|
|
|
|
# $!{EPERM} could also be true if we cant kill it (permission error) |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# Try SIGINT ... 2s ... SIGTERM ... 2s ... SIGKILL ... 3s ... UNDEAD! |
|
278
|
|
|
|
|
|
|
my $terminating_signal; |
|
279
|
|
|
|
|
|
|
for ( [ 2, $timeout ], [15, $timeout], [9, $timeout * 1.5] ) { |
|
280
|
|
|
|
|
|
|
my ($signal, $timeout) = @$_; |
|
281
|
|
|
|
|
|
|
$timeout = int $timeout; |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
CORE::kill($signal, $pid); |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
while ($timeout) { |
|
286
|
|
|
|
|
|
|
unless(CORE::kill 0 => $pid or $!{EPERM}) { |
|
287
|
|
|
|
|
|
|
$terminating_signal = $signal; |
|
288
|
|
|
|
|
|
|
last; |
|
289
|
|
|
|
|
|
|
} |
|
290
|
|
|
|
|
|
|
$timeout--; |
|
291
|
|
|
|
|
|
|
sleep(1) if $timeout; |
|
292
|
|
|
|
|
|
|
} |
|
293
|
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
last if $terminating_signal; |
|
295
|
|
|
|
|
|
|
} |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
if($terminating_signal) { |
|
298
|
|
|
|
|
|
|
if($terminating_signal == 9) { |
|
299
|
|
|
|
|
|
|
# clean up the pidfile ourselves iff we used -9 and it worked |
|
300
|
|
|
|
|
|
|
warn "Had to resort to 'kill -9' and it worked, wiping pidfile"; |
|
301
|
|
|
|
|
|
|
eval { $self->pidfile->remove }; |
|
302
|
|
|
|
|
|
|
if ($@) { |
|
303
|
|
|
|
|
|
|
warn "Could not remove pidfile (" |
|
304
|
|
|
|
|
|
|
. $self->pidfile->file |
|
305
|
|
|
|
|
|
|
. ") because : $!"; |
|
306
|
|
|
|
|
|
|
} |
|
307
|
|
|
|
|
|
|
} |
|
308
|
|
|
|
|
|
|
return; |
|
309
|
|
|
|
|
|
|
} |
|
310
|
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
# IF it is still running |
|
312
|
|
|
|
|
|
|
Carp::carp "$pid doesn't seem to want to die."; # AHH EVIL DEAD! |
|
313
|
|
|
|
|
|
|
}; |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
1; |
|
316
|
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
__END__ |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
=pod |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
=encoding UTF-8 |
|
322
|
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=head1 NAME |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
MooseX::Daemonize - Role for daemonizing your Moose based application |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
=head1 VERSION |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
version 0.21 |
|
330
|
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
package My::Daemon; |
|
334
|
|
|
|
|
|
|
use Moose; |
|
335
|
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
with qw(MooseX::Daemonize); |
|
337
|
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
# ... define your class .... |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
after start => sub { |
|
341
|
|
|
|
|
|
|
my $self = shift; |
|
342
|
|
|
|
|
|
|
return unless $self->is_daemon; |
|
343
|
|
|
|
|
|
|
# your daemon code here ... |
|
344
|
|
|
|
|
|
|
}; |
|
345
|
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
# then in your script ... |
|
347
|
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
my $daemon = My::Daemon->new_with_options(); |
|
349
|
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
my ($command) = @{$daemon->extra_argv} |
|
351
|
|
|
|
|
|
|
defined $command || die "No command specified"; |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
$daemon->start if $command eq 'start'; |
|
354
|
|
|
|
|
|
|
$daemon->status if $command eq 'status'; |
|
355
|
|
|
|
|
|
|
$daemon->restart if $command eq 'restart'; |
|
356
|
|
|
|
|
|
|
$daemon->stop if $command eq 'stop'; |
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
warn($daemon->status_message); |
|
359
|
|
|
|
|
|
|
exit($daemon->exit_code); |
|
360
|
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
362
|
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
Often you want to write a persistent daemon that has a pid file, and responds |
|
364
|
|
|
|
|
|
|
appropriately to Signals. This module provides a set of basic roles as an |
|
365
|
|
|
|
|
|
|
infrastructure to do that. |
|
366
|
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
=head1 WARNING |
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
The maintainers of this module now recommend using L<Daemon::Control> instead. |
|
370
|
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
=head1 CAVEATS |
|
372
|
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
When going into background MooseX::Daemonize closes all open file |
|
374
|
|
|
|
|
|
|
handles. This may interfere with you logging because it may also close the log |
|
375
|
|
|
|
|
|
|
file handle you want to write to. To prevent this you can either defer opening |
|
376
|
|
|
|
|
|
|
the log file until after start. Alternatively, use can use the |
|
377
|
|
|
|
|
|
|
'dont_close_all_files' option either from the command line or in your .sh |
|
378
|
|
|
|
|
|
|
script. |
|
379
|
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
Assuming you want to use Log::Log4perl for example you could expand the |
|
381
|
|
|
|
|
|
|
MooseX::Daemonize example above like this. |
|
382
|
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
after start => sub { |
|
384
|
|
|
|
|
|
|
my $self = shift; |
|
385
|
|
|
|
|
|
|
return unless $self->is_daemon; |
|
386
|
|
|
|
|
|
|
Log::Log4perl->init(\$log4perl_config); |
|
387
|
|
|
|
|
|
|
my $logger = Log::Log4perl->get_logger(); |
|
388
|
|
|
|
|
|
|
$logger->info("Daemon started"); |
|
389
|
|
|
|
|
|
|
# your daemon code here ... |
|
390
|
|
|
|
|
|
|
}; |
|
391
|
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
|
393
|
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
This list includes attributes brought in from other roles as well |
|
395
|
|
|
|
|
|
|
we include them here for ease of documentation. All of these attributes |
|
396
|
|
|
|
|
|
|
are settable though L<MooseX::Getopt>'s command line handling, with the |
|
397
|
|
|
|
|
|
|
exception of C<is_daemon>. |
|
398
|
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
=over |
|
400
|
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
=item I<progname Path::Class::Dir | Str> |
|
402
|
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
The name of our daemon, defaults to C<$package_name =~ s/::/_/>; |
|
404
|
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
=item I<pidbase Path::Class::Dir | Str> |
|
406
|
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
The base for our PID, defaults to C</var/run/> |
|
408
|
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
=item I<basedir Path::Class::Dir | Str> |
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
The directory we chdir to; defaults to C</>. |
|
412
|
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
=item I<pidfile MooseX::Daemonize::Pid::File | Str> |
|
414
|
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
The file we store our PID in, defaults to C<$pidbase/$progname.pid> |
|
416
|
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
=item I<foreground Bool> |
|
418
|
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
If true, the process won't background. Useful for debugging. This option can |
|
420
|
|
|
|
|
|
|
be set via Getopt's -f. |
|
421
|
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
=item I<no_double_fork Bool> |
|
423
|
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
If true, the process will not perform the typical double-fork, which is extra |
|
425
|
|
|
|
|
|
|
added protection from your process accidentally acquiring a controlling terminal. |
|
426
|
|
|
|
|
|
|
More information can be found by Googling "double fork daemonize". |
|
427
|
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
=item I<ignore_zombies Bool> |
|
429
|
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
If true, the process will not clean up zombie processes. |
|
431
|
|
|
|
|
|
|
Normally you don't want this. |
|
432
|
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
=item I<dont_close_all_files Bool> |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
If true, the objects open filehandles will not be closed when daemonized. |
|
436
|
|
|
|
|
|
|
Normally you don't want this. |
|
437
|
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
=item I<is_daemon Bool> |
|
439
|
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
If true, the process is the backgrounded daemon process, if false it is the |
|
441
|
|
|
|
|
|
|
parent process. This is useful for example in an C<after 'start' => sub { }> |
|
442
|
|
|
|
|
|
|
block. |
|
443
|
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
B<NOTE:> This option is explicitly B<not> available through L<MooseX::Getopt>. |
|
445
|
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
=item I<stop_timeout> |
|
447
|
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
Number of seconds to wait for the process to stop, before trying harder to kill |
|
449
|
|
|
|
|
|
|
it. Defaults to 2 seconds. |
|
450
|
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
=back |
|
452
|
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
These are the internal attributes, which are not available through MooseX::Getopt. |
|
454
|
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
=over 4 |
|
456
|
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
=item I<exit_code Int> |
|
458
|
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
=item I<status_message Str> |
|
460
|
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
=back |
|
462
|
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
=head1 METHODS |
|
464
|
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
=head2 Daemon Control Methods |
|
466
|
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
These methods can be used to control the daemon behavior. Every effort |
|
468
|
|
|
|
|
|
|
has been made to have these methods DWIM (Do What I Mean), so that you |
|
469
|
|
|
|
|
|
|
can focus on just writing the code for your daemon. |
|
470
|
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
Extending these methods is best done with the L<Moose> method modifiers, |
|
472
|
|
|
|
|
|
|
such as C<before>, C<after> and C<around>. |
|
473
|
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
=over 4 |
|
475
|
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
=item B<start> |
|
477
|
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
Setup a pidfile, fork, then setup the signal handlers. |
|
479
|
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
=item B<stop> |
|
481
|
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
Stop the process matching the pidfile, and unlinks the pidfile. |
|
483
|
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
=item B<restart> |
|
485
|
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
Literally this is: |
|
487
|
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
$self->stop(); |
|
489
|
|
|
|
|
|
|
$self->start(); |
|
490
|
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
=item B<status> |
|
492
|
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
=item B<shutdown> |
|
494
|
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
=back |
|
496
|
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
=head2 Pidfile Handling Methods |
|
498
|
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
=over 4 |
|
500
|
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
=item B<init_pidfile> |
|
502
|
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
This method will create a L<MooseX::Daemonize::Pid::File> object and tell |
|
504
|
|
|
|
|
|
|
it to store the PID in the file C<$pidbase/$progname.pid>. |
|
505
|
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
=item B<check> |
|
507
|
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
This checks to see if the daemon process is currently running by checking |
|
509
|
|
|
|
|
|
|
the pidfile. |
|
510
|
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
=item B<get_pid> |
|
512
|
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
Returns the PID of the daemon process. |
|
514
|
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
=item B<save_pid> |
|
516
|
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
Write the pidfile. |
|
518
|
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
=item B<remove_pid> |
|
520
|
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
Removes the pidfile. |
|
522
|
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
=back |
|
524
|
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
=head2 Signal Handling Methods |
|
526
|
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
=over 4 |
|
528
|
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
=item B<setup_signals> |
|
530
|
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
Setup the signal handlers, by default it only sets up handlers for SIGINT and |
|
532
|
|
|
|
|
|
|
SIGHUP. If you wish to add more signals just use the C<after> method modifier |
|
533
|
|
|
|
|
|
|
and add them. |
|
534
|
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
=item B<handle_sigint> |
|
536
|
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
Handle a INT signal, by default calls C<$self->stop()> |
|
538
|
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
=item B<handle_sighup> |
|
540
|
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
Handle a HUP signal. By default calls C<$self->restart()> |
|
542
|
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
=back |
|
544
|
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
=head2 Exit Code Methods |
|
546
|
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
These are overridable constant methods used for setting the exit code. |
|
548
|
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
=over 4 |
|
550
|
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
=item OK |
|
552
|
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
Returns 0. |
|
554
|
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
=item ERROR |
|
556
|
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
Returns 1. |
|
558
|
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
=back |
|
560
|
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
=head2 Introspection |
|
562
|
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
=over 4 |
|
564
|
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
=item meta() |
|
566
|
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
The C<meta()> method from L<Class::MOP::Class> |
|
568
|
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
=back |
|
570
|
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
=head1 DEPENDENCIES |
|
572
|
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
L<Moose>, L<MooseX::Getopt>, L<MooseX::Types::Path::Class> and L<POSIX> |
|
574
|
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
=head1 INCOMPATIBILITIES |
|
576
|
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
Obviously this will not work on Windows. |
|
578
|
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
580
|
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
L<Daemon::Control>, L<Proc::Daemon>, L<Daemon::Generic> |
|
582
|
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
=head1 THANKS |
|
584
|
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
Mike Boyko, Matt S. Trout, Stevan Little, Brandon Black, Ash Berlin and the |
|
586
|
|
|
|
|
|
|
#moose denizens |
|
587
|
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
Some bug fixes sponsored by Takkle Inc. |
|
589
|
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
=head1 SUPPORT |
|
591
|
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=MooseX-Daemonize> |
|
593
|
|
|
|
|
|
|
(or L<bug-MooseX-Daemonize@rt.cpan.org|mailto:bug-MooseX-Daemonize@rt.cpan.org>). |
|
594
|
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
There is also a mailing list available for users of this distribution, at |
|
596
|
|
|
|
|
|
|
L<http://lists.perl.org/list/moose.html>. |
|
597
|
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
There is also an irc channel available for users of this distribution, at |
|
599
|
|
|
|
|
|
|
L<C<#moose> on C<irc.perl.org>|irc://irc.perl.org/#moose>. |
|
600
|
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
=head1 AUTHORS |
|
602
|
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
=over 4 |
|
604
|
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
=item * |
|
606
|
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
Stevan Little <stevan.little@iinteractive.com> |
|
608
|
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
=item * |
|
610
|
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
Chris Prather <chris@prather.org> |
|
612
|
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
=back |
|
614
|
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
=head1 CONTRIBUTORS |
|
616
|
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
=for stopwords Karen Etheridge Michael Reddick Yuval Kogman Ash Berlin Brandon L Black David Steinbrunner Dave Rolsky Chisel Wright |
|
618
|
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
=over 4 |
|
620
|
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
=item * |
|
622
|
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
Karen Etheridge <ether@cpan.org> |
|
624
|
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
=item * |
|
626
|
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
Michael Reddick <michael.reddick@gmail.com> |
|
628
|
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
=item * |
|
630
|
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
Yuval Kogman <nothingmuch@woobling.org> |
|
632
|
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
=item * |
|
634
|
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
Ash Berlin <ash@cpan.org> |
|
636
|
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
=item * |
|
638
|
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
Brandon L Black <blblack@gmail.com> |
|
640
|
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
=item * |
|
642
|
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
David Steinbrunner <dsteinbrunner@pobox.com> |
|
644
|
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
=item * |
|
646
|
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
Dave Rolsky <autarch@urth.org> |
|
648
|
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
=item * |
|
650
|
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
Chisel Wright <chisel@chizography.net> |
|
652
|
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
=back |
|
654
|
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENCE |
|
656
|
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
This software is copyright (c) 2007 by Chris Prather. |
|
658
|
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
|
660
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
|
661
|
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
=cut |