processwanker 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Manifest +34 -0
- data/README +11 -0
- data/Rakefile +13 -0
- data/bin/pw +5 -0
- data/lib/config/config.rb +96 -0
- data/lib/config/config_auth.rb +208 -0
- data/lib/config/config_client.rb +75 -0
- data/lib/config/config_client_cluster.rb +66 -0
- data/lib/config/config_client_clusters.rb +62 -0
- data/lib/config/config_client_host.rb +152 -0
- data/lib/config/config_daemon.rb +94 -0
- data/lib/config/config_daemon_service.rb +84 -0
- data/lib/config/config_daemon_service_dependency.rb +59 -0
- data/lib/config/config_daemon_services.rb +89 -0
- data/lib/config/config_hook.rb +40 -0
- data/lib/config/config_node.rb +160 -0
- data/lib/config/config_smtp.rb +103 -0
- data/lib/events.rb +224 -0
- data/lib/log.rb +88 -0
- data/lib/net/net_api.rb +189 -0
- data/lib/net/net_client.rb +107 -0
- data/lib/net/net_connection.rb +167 -0
- data/lib/net/net_server.rb +232 -0
- data/lib/net/net_server_client.rb +84 -0
- data/lib/net/net_util.rb +205 -0
- data/lib/process_util.rb +216 -0
- data/lib/pw_app.rb +557 -0
- data/lib/service.rb +512 -0
- data/lib/service_classes/dummy_service.rb +88 -0
- data/lib/service_classes/pid_service.rb +126 -0
- data/lib/service_classes/process_service.rb +218 -0
- data/lib/service_classes/upstart_service.rb +103 -0
- data/lib/service_mgr.rb +226 -0
- data/lib/util.rb +31 -0
- data/processwanker.gemspec +36 -0
- data.tar.gz.sig +0 -0
- metadata +157 -0
- metadata.gz.sig +0 -0
data/lib/service.rb
ADDED
@@ -0,0 +1,512 @@
|
|
1
|
+
############################################################################
|
2
|
+
#
|
3
|
+
# service.rb
|
4
|
+
#
|
5
|
+
# class representing a running service
|
6
|
+
#
|
7
|
+
############################################################################
|
8
|
+
|
9
|
+
require 'process_util'
|
10
|
+
require 'log'
|
11
|
+
require 'events'
|
12
|
+
|
13
|
+
module ProcessWanker
|
14
|
+
|
15
|
+
class Service
|
16
|
+
|
17
|
+
include Log
|
18
|
+
|
19
|
+
############################################################################
|
20
|
+
#
|
21
|
+
# current state
|
22
|
+
#
|
23
|
+
############################################################################
|
24
|
+
|
25
|
+
attr_accessor :params
|
26
|
+
attr_accessor :want_state
|
27
|
+
attr_accessor :last_action_time
|
28
|
+
attr_accessor :current_state
|
29
|
+
attr_accessor :prev_state
|
30
|
+
attr_accessor :last_transition_time
|
31
|
+
attr_accessor :attempt_count
|
32
|
+
attr_accessor :last_fail_time
|
33
|
+
attr_accessor :show_state
|
34
|
+
attr_accessor :dependencies
|
35
|
+
attr_accessor :suppress
|
36
|
+
attr_accessor :ignore
|
37
|
+
attr_accessor :config_node
|
38
|
+
attr_accessor :want_state_mode
|
39
|
+
attr_accessor :stable
|
40
|
+
|
41
|
+
############################################################################
|
42
|
+
#
|
43
|
+
# initialize
|
44
|
+
#
|
45
|
+
# iparams is a hash containing:
|
46
|
+
#
|
47
|
+
# :name name of service (unique to this machine)
|
48
|
+
#
|
49
|
+
# :tags array of tags
|
50
|
+
# :group_name group name
|
51
|
+
# :min_action_delay_secs minimum delay between (automatic) actions
|
52
|
+
# :start_grace_secs delay between successive start attempts
|
53
|
+
# :stop_grace_secs delay between stop attempts
|
54
|
+
# :stable_secs seconds the process must be in desired state to be considered stable
|
55
|
+
# :fail_trigger_count number of transitions to trigger failing
|
56
|
+
# :fail_suppress_secs seconds to delay actions after failing detected
|
57
|
+
# :initial_state (defaults to current state) :up or :down
|
58
|
+
#
|
59
|
+
############################################################################
|
60
|
+
|
61
|
+
def initialize(iparams)
|
62
|
+
|
63
|
+
# extract params
|
64
|
+
extract_params(
|
65
|
+
iparams,
|
66
|
+
[
|
67
|
+
:name,
|
68
|
+
:tags,
|
69
|
+
:group_name,
|
70
|
+
:min_action_delay_secs,
|
71
|
+
:start_grace_secs,
|
72
|
+
:stop_grace_secs,
|
73
|
+
:stable_secs,
|
74
|
+
:fail_trigger_count,
|
75
|
+
:fail_suppress_secs,
|
76
|
+
:initial_state,
|
77
|
+
:dependencies,
|
78
|
+
:log_file,
|
79
|
+
])
|
80
|
+
|
81
|
+
# warn about extra params
|
82
|
+
iparams.keys.each do |k|
|
83
|
+
warn "warning: ignoring unrecognized parameter: #{k.to_s}"
|
84
|
+
end
|
85
|
+
|
86
|
+
# apply defaults
|
87
|
+
@params={
|
88
|
+
:min_action_delay_secs => 1,
|
89
|
+
:stable_secs => 20,
|
90
|
+
:fail_trigger_count => 5,
|
91
|
+
:fail_suppress_secs => 300,
|
92
|
+
:group_name => "default",
|
93
|
+
:start_grace_secs => 5,
|
94
|
+
:stop_grace_secs => 5,
|
95
|
+
:dependencies => []
|
96
|
+
}.merge(@params)
|
97
|
+
|
98
|
+
@params[:tags] ||= []
|
99
|
+
|
100
|
+
# convert necessary things to symbols
|
101
|
+
@params[:initial_state] = @params[:initial_state].to_sym if(@params[:initial_state])
|
102
|
+
|
103
|
+
# set state values
|
104
|
+
@last_action_time=Time.at(0)
|
105
|
+
@last_action=nil
|
106
|
+
@current_state=safe_do_ping()
|
107
|
+
@want_state=@params[:initial_state] || @current_state
|
108
|
+
@prev_state=safe_do_ping()
|
109
|
+
@last_transition_time=Time.at(0)
|
110
|
+
@attempt_count=0
|
111
|
+
@last_fail_time=Time.at(0)
|
112
|
+
@show_state=""
|
113
|
+
@suppress=false
|
114
|
+
@want_state_mode=:boot
|
115
|
+
@stable=false
|
116
|
+
|
117
|
+
# register with the manager
|
118
|
+
ServiceMgr::register_service(self)
|
119
|
+
end
|
120
|
+
|
121
|
+
############################################################################
|
122
|
+
#
|
123
|
+
#
|
124
|
+
#
|
125
|
+
############################################################################
|
126
|
+
|
127
|
+
def validate_params()
|
128
|
+
raise "no name provided" if(!params[:name])
|
129
|
+
@params.keys.each do |k|
|
130
|
+
if(!keys.include?(k))
|
131
|
+
warn "warning: unrecognized parameter #{k.to_s} ignored"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
############################################################################
|
137
|
+
#
|
138
|
+
#
|
139
|
+
#
|
140
|
+
############################################################################
|
141
|
+
|
142
|
+
def extract_params(params,keys)
|
143
|
+
@params ||= {}
|
144
|
+
keys.each do |k|
|
145
|
+
@params[k]=params[k] if(params.has_key?(k))
|
146
|
+
params.delete(k)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
############################################################################
|
151
|
+
#
|
152
|
+
# return the host-wide unique name of the service
|
153
|
+
#
|
154
|
+
############################################################################
|
155
|
+
|
156
|
+
def name
|
157
|
+
@params[:name]
|
158
|
+
end
|
159
|
+
|
160
|
+
############################################################################
|
161
|
+
#
|
162
|
+
# return the name of the group this process belongs to
|
163
|
+
#
|
164
|
+
############################################################################
|
165
|
+
|
166
|
+
def group_name
|
167
|
+
@params[:group_name]
|
168
|
+
end
|
169
|
+
|
170
|
+
############################################################################
|
171
|
+
#
|
172
|
+
# start the service. should not block for a considerable amount of time
|
173
|
+
#
|
174
|
+
############################################################################
|
175
|
+
|
176
|
+
def do_start(attempt_ct)
|
177
|
+
raise "method not defined in base class"
|
178
|
+
end
|
179
|
+
|
180
|
+
############################################################################
|
181
|
+
#
|
182
|
+
# stop the service - should not block for a considerable amount of time
|
183
|
+
#
|
184
|
+
############################################################################
|
185
|
+
|
186
|
+
def do_stop(attempt_ct)
|
187
|
+
raise "method not defined in base class"
|
188
|
+
end
|
189
|
+
|
190
|
+
############################################################################
|
191
|
+
#
|
192
|
+
# return state (:up, :down)
|
193
|
+
#
|
194
|
+
############################################################################
|
195
|
+
|
196
|
+
def do_ping
|
197
|
+
raise "method not defined in base class"
|
198
|
+
end
|
199
|
+
|
200
|
+
############################################################################
|
201
|
+
#
|
202
|
+
# resolve dependencies through name lookup
|
203
|
+
#
|
204
|
+
############################################################################
|
205
|
+
|
206
|
+
def resolve_dependencies
|
207
|
+
|
208
|
+
@dependencies=[]
|
209
|
+
params[:dependencies].each do |dep|
|
210
|
+
ServiceMgr::instance.match_services(dep.service).each do |k,v|
|
211
|
+
@dependencies << { :service => v, :dep => dep }
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
############################################################################
|
217
|
+
#
|
218
|
+
# safe, exception-catching methods
|
219
|
+
#
|
220
|
+
############################################################################
|
221
|
+
|
222
|
+
def safe_do(name)
|
223
|
+
ProcessWanker::with_logged_rescue("#{name} - safe_do") do
|
224
|
+
yield
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def safe_do_start(attempt_ct)
|
229
|
+
safe_do("#{name}:do_start") { do_start(attempt_ct) }
|
230
|
+
end
|
231
|
+
|
232
|
+
def safe_do_stop(attempt_ct)
|
233
|
+
safe_do("#{name}:do_start") { do_stop(attempt_ct) }
|
234
|
+
end
|
235
|
+
|
236
|
+
def safe_do_ping()
|
237
|
+
p=:down
|
238
|
+
safe_do("#{name}:do_start") { p=do_ping }
|
239
|
+
p
|
240
|
+
end
|
241
|
+
|
242
|
+
############################################################################
|
243
|
+
#
|
244
|
+
# main logic
|
245
|
+
#
|
246
|
+
############################################################################
|
247
|
+
|
248
|
+
def tick
|
249
|
+
|
250
|
+
#
|
251
|
+
# get current time
|
252
|
+
#
|
253
|
+
|
254
|
+
now=Time.now
|
255
|
+
|
256
|
+
#
|
257
|
+
# get current state, check for change, record transition time
|
258
|
+
#
|
259
|
+
|
260
|
+
state = safe_do_ping()
|
261
|
+
if(@current_state != state)
|
262
|
+
@prev_state = @current_state
|
263
|
+
@last_transition_time = now
|
264
|
+
@current_state = state
|
265
|
+
@stable = false
|
266
|
+
@show_state = state.to_s
|
267
|
+
end
|
268
|
+
|
269
|
+
#
|
270
|
+
# handle special :restart case
|
271
|
+
#
|
272
|
+
|
273
|
+
want=@want_state
|
274
|
+
if(want == :restart)
|
275
|
+
if(@current_state == :down)
|
276
|
+
want = :up
|
277
|
+
@want_state = :up
|
278
|
+
@last_action_time = Time.now
|
279
|
+
else
|
280
|
+
want = :down
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
#
|
285
|
+
# check dependencies
|
286
|
+
#
|
287
|
+
|
288
|
+
deps_ok=true
|
289
|
+
@dependencies.each do |d|
|
290
|
+
s=d[:service]
|
291
|
+
if(s.current_state != :up)
|
292
|
+
deps_ok=false
|
293
|
+
next
|
294
|
+
end
|
295
|
+
tt=now - s.last_transition_time
|
296
|
+
if(tt < d[:dep].up_for)
|
297
|
+
deps_ok=false
|
298
|
+
end
|
299
|
+
end
|
300
|
+
@suppress=(!deps_ok) && (@want_state != :down)
|
301
|
+
if(@suppress)
|
302
|
+
want = :down
|
303
|
+
end
|
304
|
+
|
305
|
+
#
|
306
|
+
# have we been in the same state for a while?
|
307
|
+
#
|
308
|
+
|
309
|
+
stabilized=false
|
310
|
+
elapsed = now - @last_transition_time
|
311
|
+
if(!@stable && elapsed >= @params[:stable_secs])
|
312
|
+
stabilized=true
|
313
|
+
@stable=true
|
314
|
+
end
|
315
|
+
|
316
|
+
#
|
317
|
+
# are we in the desired state?
|
318
|
+
#
|
319
|
+
|
320
|
+
if(@current_state == want)
|
321
|
+
|
322
|
+
# did we just stabilize?
|
323
|
+
if(stabilized)
|
324
|
+
|
325
|
+
@attempt_count = 0
|
326
|
+
@show_state = @current_state.to_s + " [stable]"
|
327
|
+
|
328
|
+
# was this request part of a user request? if not, notify
|
329
|
+
if(@want_state_mode == :none && want == :up)
|
330
|
+
Event::dispatch("restarted",self)
|
331
|
+
end
|
332
|
+
|
333
|
+
# clear request mode
|
334
|
+
@want_state_mode=:none
|
335
|
+
end
|
336
|
+
|
337
|
+
# nothing more to do
|
338
|
+
return
|
339
|
+
end
|
340
|
+
|
341
|
+
#
|
342
|
+
# are we ignoring the process?
|
343
|
+
#
|
344
|
+
|
345
|
+
if(want == :ignore)
|
346
|
+
@show_state = "#{@current_state.to_s} (ignored)"
|
347
|
+
return
|
348
|
+
end
|
349
|
+
|
350
|
+
#
|
351
|
+
# is it too soon to do anything?
|
352
|
+
#
|
353
|
+
|
354
|
+
proposed_action = { :up => :start , :down => :stop }[want]
|
355
|
+
return if(!check_action_delay(now,proposed_action))
|
356
|
+
|
357
|
+
#
|
358
|
+
# actually attempt to cause a change
|
359
|
+
#
|
360
|
+
|
361
|
+
# update state
|
362
|
+
@attempt_count=0 if(proposed_action != @last_action)
|
363
|
+
@last_action=proposed_action
|
364
|
+
@last_action_time=now
|
365
|
+
|
366
|
+
# check for failing
|
367
|
+
if(@attempt_count >= @params[:fail_trigger_count])
|
368
|
+
info("#{self.name} has now had #{@attempt_count} attempts. considering it failed.")
|
369
|
+
|
370
|
+
@show_state = "failing(#{proposed_action})"
|
371
|
+
@last_fail_time = now
|
372
|
+
@attempt_count = 0 # reset for next time
|
373
|
+
|
374
|
+
Event::dispatch("fail-#{proposed_action.to_s}",self)
|
375
|
+
|
376
|
+
return
|
377
|
+
end
|
378
|
+
|
379
|
+
# was this request part of a user request? if not, notify
|
380
|
+
if(@want_state_mode == :none && proposed_action == :start && @attempt_count==0)
|
381
|
+
Event::dispatch("restarting",self)
|
382
|
+
end
|
383
|
+
|
384
|
+
# do it
|
385
|
+
@show_state = "#{proposed_action} [#{@attempt_count}]"
|
386
|
+
if(proposed_action == :start)
|
387
|
+
|
388
|
+
Event::dispatch("pre-launch",self)
|
389
|
+
|
390
|
+
info("calling do_start for #{self.name}")
|
391
|
+
safe_do_start(@attempt_count)
|
392
|
+
|
393
|
+
else
|
394
|
+
|
395
|
+
info("calling do_stop for #{self.name}")
|
396
|
+
safe_do_stop(@attempt_count)
|
397
|
+
|
398
|
+
end
|
399
|
+
@attempt_count += 1
|
400
|
+
|
401
|
+
end
|
402
|
+
|
403
|
+
############################################################################
|
404
|
+
#
|
405
|
+
# check the various timers, and see if we're allowed to take action
|
406
|
+
# on a specific service at this point...
|
407
|
+
#
|
408
|
+
############################################################################
|
409
|
+
|
410
|
+
def check_action_delay(now,proposed_action)
|
411
|
+
|
412
|
+
elapsed=now - @last_action_time
|
413
|
+
|
414
|
+
# check general-purpose between-action-delay
|
415
|
+
return(false) if(elapsed < @params[:min_action_delay_secs])
|
416
|
+
|
417
|
+
if(proposed_action == @last_action)
|
418
|
+
|
419
|
+
# check grace periods
|
420
|
+
return(false) if(@last_action == :start && elapsed < @params[:start_grace_secs])
|
421
|
+
return(false) if(@last_action == :stop && elapsed < @params[:stop_grace_secs])
|
422
|
+
|
423
|
+
# check failing suppression
|
424
|
+
since_fail=now - @last_fail_time
|
425
|
+
return(false) if(since_fail < @params[:fail_suppress_secs])
|
426
|
+
end
|
427
|
+
|
428
|
+
true
|
429
|
+
end
|
430
|
+
|
431
|
+
############################################################################
|
432
|
+
#
|
433
|
+
# set want state in response to a user request - clear all delay state,
|
434
|
+
# start with a clean slate.
|
435
|
+
#
|
436
|
+
############################################################################
|
437
|
+
|
438
|
+
def set_want_state(state)
|
439
|
+
@want_state = state
|
440
|
+
@want_state_mode = :user
|
441
|
+
@attempt_count = 0
|
442
|
+
@last_action_time = Time.at(0)
|
443
|
+
@last_fail_time = Time.at(0)
|
444
|
+
if(@want_state != @current_state)
|
445
|
+
@show_state = "received #{state.inspect}"
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
############################################################################
|
450
|
+
#
|
451
|
+
#
|
452
|
+
#
|
453
|
+
############################################################################
|
454
|
+
|
455
|
+
def matches_spec(spec)
|
456
|
+
|
457
|
+
# ensure it's in array form
|
458
|
+
spec=spec.split(",")
|
459
|
+
|
460
|
+
# check for inversion on first item
|
461
|
+
if(spec.first[0..0]=="~")
|
462
|
+
# insert implicit "all" at front
|
463
|
+
spec=["all"] + spec
|
464
|
+
end
|
465
|
+
|
466
|
+
matches=false
|
467
|
+
spec.each do |p|
|
468
|
+
matches = matches_single(p,matches)
|
469
|
+
end
|
470
|
+
matches
|
471
|
+
|
472
|
+
end
|
473
|
+
|
474
|
+
############################################################################
|
475
|
+
#
|
476
|
+
#
|
477
|
+
#
|
478
|
+
############################################################################
|
479
|
+
|
480
|
+
def matches_single(p,prev)
|
481
|
+
|
482
|
+
if(p == "all")
|
483
|
+
return(true)
|
484
|
+
elsif(p[0..0] == "/")
|
485
|
+
r=Regexp.new(p.split("/")[1])
|
486
|
+
return(true) if(group_name =~ r)
|
487
|
+
return(true) if(name =~ r)
|
488
|
+
elsif(p[0..0] == "~")
|
489
|
+
return(prev && !matches_single(p[1..-1],false))
|
490
|
+
elsif(p[0..3] == "tag:")
|
491
|
+
tag=p[4..-1]
|
492
|
+
return(true) if(params[:tags] && params[:tags].include?(tag))
|
493
|
+
elsif(p == name)
|
494
|
+
return(true)
|
495
|
+
elsif(p == group_name)
|
496
|
+
return(true)
|
497
|
+
end
|
498
|
+
|
499
|
+
prev
|
500
|
+
end
|
501
|
+
|
502
|
+
|
503
|
+
############################################################################
|
504
|
+
#
|
505
|
+
#
|
506
|
+
#
|
507
|
+
############################################################################
|
508
|
+
|
509
|
+
|
510
|
+
end
|
511
|
+
|
512
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
############################################################################
|
2
|
+
#
|
3
|
+
# dummy_service.rb
|
4
|
+
#
|
5
|
+
# class representing a fake service
|
6
|
+
#
|
7
|
+
############################################################################
|
8
|
+
|
9
|
+
require 'service'
|
10
|
+
require 'digest/md5'
|
11
|
+
require 'etc'
|
12
|
+
require 'process_service'
|
13
|
+
require 'process_util'
|
14
|
+
|
15
|
+
module ProcessWanker
|
16
|
+
|
17
|
+
class DummyService < Service
|
18
|
+
include Log
|
19
|
+
|
20
|
+
############################################################################
|
21
|
+
#
|
22
|
+
#
|
23
|
+
#
|
24
|
+
############################################################################
|
25
|
+
|
26
|
+
def self.nice_name
|
27
|
+
"dummy_service"
|
28
|
+
end
|
29
|
+
|
30
|
+
############################################################################
|
31
|
+
#
|
32
|
+
#
|
33
|
+
#
|
34
|
+
############################################################################
|
35
|
+
|
36
|
+
def initialize(iparams)
|
37
|
+
@state=(iparams[:initial_state] || :down).to_sym
|
38
|
+
super(iparams)
|
39
|
+
end
|
40
|
+
|
41
|
+
############################################################################
|
42
|
+
#
|
43
|
+
# start
|
44
|
+
#
|
45
|
+
############################################################################
|
46
|
+
|
47
|
+
def do_start(attempt_count)
|
48
|
+
debug("do_start #{self.name}")
|
49
|
+
@state=:up
|
50
|
+
end
|
51
|
+
|
52
|
+
############################################################################
|
53
|
+
#
|
54
|
+
# stop
|
55
|
+
#
|
56
|
+
############################################################################
|
57
|
+
|
58
|
+
def do_stop(attempt_count)
|
59
|
+
debug("do_stop #{self.name}")
|
60
|
+
@state=:down
|
61
|
+
end
|
62
|
+
|
63
|
+
############################################################################
|
64
|
+
#
|
65
|
+
# ping
|
66
|
+
#
|
67
|
+
# return run state of process
|
68
|
+
#
|
69
|
+
############################################################################
|
70
|
+
|
71
|
+
def do_ping
|
72
|
+
@state
|
73
|
+
end
|
74
|
+
|
75
|
+
############################################################################
|
76
|
+
#
|
77
|
+
#
|
78
|
+
#
|
79
|
+
############################################################################
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
ServiceMgr::register_service_class(DummyService)
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
|
@@ -0,0 +1,126 @@
|
|
1
|
+
############################################################################
|
2
|
+
#
|
3
|
+
# process_service.rb
|
4
|
+
#
|
5
|
+
# class representing a service that is a command-line launchable process
|
6
|
+
#
|
7
|
+
############################################################################
|
8
|
+
|
9
|
+
require 'service'
|
10
|
+
require 'digest/md5'
|
11
|
+
require 'etc'
|
12
|
+
require 'process_service'
|
13
|
+
require 'process_util'
|
14
|
+
|
15
|
+
module ProcessWanker
|
16
|
+
|
17
|
+
class PIDService < ProcessService
|
18
|
+
|
19
|
+
############################################################################
|
20
|
+
#
|
21
|
+
#
|
22
|
+
#
|
23
|
+
############################################################################
|
24
|
+
|
25
|
+
def self.nice_name
|
26
|
+
"pid_service"
|
27
|
+
end
|
28
|
+
|
29
|
+
############################################################################
|
30
|
+
#
|
31
|
+
# iparams is a hash containing:
|
32
|
+
#
|
33
|
+
# :start_cmd
|
34
|
+
# :pid_file
|
35
|
+
# :start_dir (optional)
|
36
|
+
# :run_user (optional)
|
37
|
+
# :soft_kill_limit (optional)
|
38
|
+
#
|
39
|
+
# plus anything to be passed to Service
|
40
|
+
#
|
41
|
+
############################################################################
|
42
|
+
|
43
|
+
def initialize(iparams)
|
44
|
+
|
45
|
+
# extract parameters
|
46
|
+
extract_params(
|
47
|
+
iparams,
|
48
|
+
[
|
49
|
+
:pid_file,
|
50
|
+
])
|
51
|
+
|
52
|
+
raise "service has no pid_file" if(!@params[:pid_file])
|
53
|
+
|
54
|
+
super(iparams)
|
55
|
+
end
|
56
|
+
|
57
|
+
############################################################################
|
58
|
+
#
|
59
|
+
# stop
|
60
|
+
#
|
61
|
+
# stop the process (either with -TERM or -KILL)
|
62
|
+
#
|
63
|
+
############################################################################
|
64
|
+
|
65
|
+
def do_stop(attempt_count)
|
66
|
+
info("do_stop[#{attempt_count}] for #{self.inspect}")
|
67
|
+
|
68
|
+
kl=@params[:soft_kill_limit]
|
69
|
+
mode = (kl && attempt_count >= kl) ? :hard : :soft
|
70
|
+
|
71
|
+
if(mode == :soft)
|
72
|
+
if(params[:stop_cmd])
|
73
|
+
system(params[:stop_cmd])
|
74
|
+
return
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
ProcessWanker::with_logged_rescue("PidServer::do_stop - reading pid file") do
|
79
|
+
pid = File.read(@params[:pid_file]).strip.to_i
|
80
|
+
Process.kill({ :hard => "KILL", :soft => "TERM" }[mode],pid)
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
############################################################################
|
86
|
+
#
|
87
|
+
# ping
|
88
|
+
#
|
89
|
+
# return run state of process
|
90
|
+
#
|
91
|
+
############################################################################
|
92
|
+
|
93
|
+
def do_ping
|
94
|
+
begin
|
95
|
+
pid = File.read(@params[:pid_file]).strip.to_i
|
96
|
+
return(:up) if(ProcessUtil::all_processes[pid])
|
97
|
+
rescue Exception => e
|
98
|
+
end
|
99
|
+
:down
|
100
|
+
end
|
101
|
+
|
102
|
+
############################################################################
|
103
|
+
#
|
104
|
+
# override the env_hash() method, to prevent our services being tagged
|
105
|
+
# in the same way process_services are.
|
106
|
+
#
|
107
|
+
############################################################################
|
108
|
+
|
109
|
+
def env_hash()
|
110
|
+
nil
|
111
|
+
end
|
112
|
+
|
113
|
+
############################################################################
|
114
|
+
#
|
115
|
+
#
|
116
|
+
#
|
117
|
+
############################################################################
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
ServiceMgr::register_service_class(PIDService)
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
|