daemons 1.0.10 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -1,4 +1,4 @@
1
- = Daemons Version 1.0.10
1
+ = Daemons Version 1.1.0
2
2
 
3
3
  (See Releases for release-specific information)
4
4
 
@@ -19,7 +19,7 @@ process.
19
19
 
20
20
  == Basic Usage
21
21
 
22
- You can use Daemons in four differet ways:
22
+ You can use Daemons in four different ways:
23
23
 
24
24
  === 1. Create wrapper scripts for your server scripts or applications
25
25
 
@@ -184,11 +184,12 @@ The RDoc documentation is also online at http://daemons.rubyforge.org
184
184
 
185
185
  == Author
186
186
 
187
- Written in 2005-2008 by Thomas Uehlinger <mailto:th.uehlinger@gmx.ch>.
187
+ Written 2005-2010 by Thomas Uehlinger <mailto:th.uehlinger@gmx.ch>.
188
+ Anonymous SVN checkout is available with "svn checkout http://daemons.rubyforge.org/svn/".
188
189
 
189
190
  == License
190
191
 
191
- Copyright (c) 2005-2008 Thomas Uehlinger
192
+ Copyright (c) 2005-2010 Thomas Uehlinger
192
193
 
193
194
  Permission is hereby granted, free of charge, to any person
194
195
  obtaining a copy of this software and associated documentation
data/Rakefile CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'rubygems'
2
- Gem::manage_gems
2
+ #Gem::manage_gems
3
3
 
4
4
  require 'rake/gempackagetask'
5
5
  #require 'rake/testtask'
@@ -68,6 +68,10 @@ end
68
68
 
69
69
  task :default => [:package]
70
70
 
71
+ desc 'Show information about the gem.'
72
+ task :debug_gem do
73
+ puts spec.to_ruby
74
+ end
71
75
 
72
76
  task :upload do
73
77
  sh "scp -r html/* uehli@rubyforge.org:/var/www/gforge-projects/daemons"
@@ -81,4 +85,4 @@ rd = Rake::RDocTask.new("rdoc") { |rdoc|
81
85
  rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README'
82
86
  rdoc.rdoc_files.include('README', 'TODO', 'Releases')
83
87
  rdoc.rdoc_files.include('lib/**/*.rb')
84
- }
88
+ }
data/Releases CHANGED
@@ -1,26 +1,51 @@
1
1
  = Daemons Release History
2
2
 
3
- == Release 1.0.10: November 16, 2007
3
+ == Release 1.1.0: June 20, 2010
4
+
5
+ * Honour the options[:app_name] in Daemons.daemonize (thanks to Ryan Tecco).
6
+ * Included a new option :stop_proc to specify a proc that will be called when a
7
+ daemonized process receives a request to stop (thanks to Dave Dupre).
8
+ * Only delete the pidfile if the current pid is the original pid (ghazel).
9
+ * Start when restart but no application running (pcreux).
10
+ * Silently continue if there is no pidfile (ghazel).
11
+ * We now per default wait for processes to stop and
12
+ kill them automatically it if they do not stop within a given time
13
+ (force_kill_waittime). Use the option --no_wait to not wait for processes to
14
+ stop.
15
+ * Set log files mode to 0644 (mikehale).
16
+ * Set pid file permissions to 0644 (mikehale).
17
+ * Added ability to change process uid/gid (mikehale).
18
+ * Fix for: If you happen to start a daemon from a process that has open file
19
+ descriptors these will stay open. As it is daemonize.rb only closes ruby IO
20
+ objects (thanks to Han Holl).
21
+ * New reload command (SIGHUP) (thanks to Michael Schuerig).
22
+
23
+ == Release 1.0.10: March 21, 2008
4
24
 
5
25
  * By default, we now delete stray pid-files (i.e. pid-files which result for
6
- example from a killed daemon) automatically. This function can be deactivated by
7
- passing :keep_pid_files => true as an option.
8
- * All pid files of :multiple daemons new get deleted correctly upon exit of the daemons (reported by Han Holl).
26
+ example from a killed daemon) automatically. This function can be deactivated
27
+ by passing :keep_pid_files => true as an option.
28
+ * All pid files of :multiple daemons new get deleted correctly upon exit of the
29
+ daemons (reported by Han Holl).
9
30
  * Use the signal 'KILL' instead of 'TERM' on Windows platforms.
10
- * Use exit! in trap('TERM') instead of exit when option :hard_exit is given (thanks to Han Holl).
31
+ * Use exit! in trap('TERM') instead of exit when option :hard_exit is given
32
+ (thanks to Han Holl).
11
33
  * Did some clarification on the exception log.
12
34
 
13
35
  == Release 1.0.9: October 29, 2007
14
36
 
15
- * fixed a severe bug in the new Pid.running? function: function returned true if the process did not exist (thanks to Jeremy Lawler).
37
+ * fixed a severe bug in the new Pid.running? function: function returned true if
38
+ the process did not exist (thanks to Jeremy Lawler).
16
39
 
17
40
  == Release 1.0.8: September 24, 2007
18
41
 
19
- * new Pid.running? function. Checking whether a process exists by sending signal '0' (thanks to Dru Nelson).
42
+ * new Pid.running? function. Checking whether a process exists by sending
43
+ signal '0' (thanks to Dru Nelson).
20
44
 
21
45
  == Release 1.0.7: July 7, 2007
22
46
 
23
- * Patch to fix wrong ARGV when using :exec (in def start_exec: Kernel.exec(script(), *(@app_argv || []))) (thanks to Alex McGuire).
47
+ * Patch to fix wrong ARGV when using :exec (in def start_exec:
48
+ Kernel.exec(script(), *(@app_argv || []))) (thanks to Alex McGuire).
24
49
 
25
50
  == Release 1.0.6: Mai 8, 2007
26
51
 
@@ -37,7 +62,8 @@
37
62
 
38
63
  * Document the :log_output option (thanks to Andrew Kuklewicz).
39
64
  * Set STDOUT.sync = true when redirecting to a logfile (thanks to Andrew Kuklewicz).
40
- * Should now run also correctly when there is no working 'ps ax' on the system (thanks to Daniel Kehoe).
65
+ * Should now run also correctly when there is no working 'ps ax' on the system
66
+ (thanks to Daniel Kehoe).
41
67
 
42
68
  == Release 1.0.3: November 1, 2006
43
69
 
data/TODO CHANGED
@@ -1,6 +1,2 @@
1
- * write the README (2005-02-07) *DONE*
2
- * write some real tests (2005-02-08)
3
- * document the new options (2005-03-14) *DONE*
4
- * start/stop with --force options (2005-04-05)
5
- * option to give some console output on start/stop commands (2005-04-05)
1
+ * put TODOS here
6
2
 
@@ -0,0 +1,19 @@
1
+ lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
2
+
3
+ if File.exist?(File.join(lib_dir, 'daemons.rb'))
4
+ $LOAD_PATH.unshift lib_dir
5
+ else
6
+ begin; require 'rubygems'; rescue ::Exception; end
7
+ end
8
+
9
+ require 'daemons'
10
+
11
+ options = {
12
+ #:mode => :exec,
13
+ :multiple => true,
14
+ :no_pidfiles => true,
15
+ :force_kill_waittime => 5
16
+ #:force_kill_waittime => -1 # do not wait before killing -9
17
+ }
18
+
19
+ Daemons.run(File.join(File.dirname(__FILE__), 'myserver_hanging.rb'), options)
File without changes
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ # This is myserver.rb, an example server that is to be controlled by daemons
5
+ # and that does nothing really useful at the moment.
6
+ #
7
+ # Don't run this script by yourself, it can be controlled by the ctrl*.rb scripts.
8
+
9
+ trap('TERM') {
10
+ puts "received TERM"
11
+
12
+ loop do
13
+ puts 'hanging!'
14
+ sleep(3)
15
+ end
16
+ }
17
+
18
+ loop do
19
+ puts 'ping from myserver.rb!'
20
+ sleep(3)
21
+ end
@@ -1,5 +1,8 @@
1
1
  require 'daemons/pidfile'
2
2
  require 'daemons/pidmem'
3
+ require 'daemons/change_privilege'
4
+
5
+ require 'timeout'
3
6
 
4
7
 
5
8
  module Daemons
@@ -29,8 +32,12 @@ module Daemons
29
32
 
30
33
  @dir_mode = @dir = @script = nil
31
34
 
35
+ @force_kill_waittime = @options[:force_kill_waittime] || 20
36
+
32
37
  unless @pid = pid
33
- if dir = pidfile_dir
38
+ if @options[:no_pidfiles]
39
+ @pid = PidMem.new
40
+ elsif dir = pidfile_dir
34
41
  @pid = PidFile.new(dir, @group.app_name, @group.multiple)
35
42
  else
36
43
  @pid = PidMem.new
@@ -38,6 +45,12 @@ module Daemons
38
45
  end
39
46
  end
40
47
 
48
+ def change_privilege
49
+ user = options[:user]
50
+ group = options[:group]
51
+ CurrentProcess.change_privilege(user, group) if user
52
+ end
53
+
41
54
  def script
42
55
  @script || @group.script
43
56
  end
@@ -46,13 +59,19 @@ module Daemons
46
59
  Pid.dir(@dir_mode || @group.dir_mode, @dir || @group.dir, @script || @group.script)
47
60
  end
48
61
 
62
+ def logdir
63
+ logdir = options[:log_dir]
64
+ unless logdir
65
+ logdir = options[:dir_mode] == :system ? '/var/log' : pidfile_dir
66
+ end
67
+ logdir
68
+ end
69
+
49
70
  def output_logfile
50
- logdir = options[:dir_mode] == :system ? '/var/log' : pidfile_dir
51
71
  (options[:log_output] && logdir) ? File.join(logdir, @group.app_name + '.output') : nil
52
72
  end
53
73
 
54
74
  def logfile
55
- logdir = options[:dir_mode] == :system ? '/var/log' : pidfile_dir
56
75
  logdir ? File.join(logdir, @group.app_name + '.log') : nil
57
76
  end
58
77
 
@@ -113,12 +132,11 @@ module Daemons
113
132
 
114
133
  # note that we cannot remove the pid file if we run in :ontop mode (i.e. 'ruby ctrl_exec.rb run')
115
134
  @pid.pid = Process.pid
116
-
135
+
117
136
  ENV['DAEMONS_ARGV'] = @controller_argv.join(' ')
118
137
  # haven't tested yet if this is really passed to the exec'd process...
119
138
 
120
-
121
-
139
+ started()
122
140
  Kernel.exec(script(), *(@app_argv || []))
123
141
  #Kernel.exec(script(), *ARGV)
124
142
  end
@@ -134,7 +152,7 @@ module Daemons
134
152
 
135
153
 
136
154
  # We need this to remove the pid-file if the applications exits by itself.
137
- # Note that <tt>at_text</tt> will only be run if the applications exits by calling
155
+ # Note that <tt>at_exit</tt> will only be run if the applications exits by calling
138
156
  # <tt>exit</tt>, and not if it calls <tt>exit!</tt> (so please don't call <tt>exit!</tt>
139
157
  # in your application!
140
158
  #
@@ -154,7 +172,15 @@ module Daemons
154
172
  # Note that the applications is not supposed to overwrite the signal handler for
155
173
  # 'TERM'.
156
174
  #
175
+ $daemons_stop_proc = options[:stop_proc]
157
176
  trap(SIGNAL) {
177
+ begin
178
+ if $daemons_stop_proc
179
+ $daemons_stop_proc.call
180
+ end
181
+ rescue ::Exception
182
+ end
183
+
158
184
  begin; @pid.cleanup; rescue ::Exception; end
159
185
  $daemons_sigterm = true
160
186
 
@@ -172,6 +198,7 @@ module Daemons
172
198
  ARGV.clear
173
199
  ARGV.concat @app_argv if @app_argv
174
200
 
201
+ started()
175
202
  # TODO: begin - rescue - end around this and exception logging
176
203
  load script()
177
204
  end
@@ -201,7 +228,15 @@ module Daemons
201
228
  # Note that the applications is not supposed to overwrite the signal handler for
202
229
  # 'TERM'.
203
230
  #
231
+ $daemons_stop_proc = options[:stop_proc]
204
232
  trap(SIGNAL) {
233
+ begin
234
+ if $daemons_stop_proc
235
+ $daemons_stop_proc.call
236
+ end
237
+ rescue ::Exception
238
+ end
239
+
205
240
  begin; @pid.cleanup; rescue ::Exception; end
206
241
  $daemons_sigterm = true
207
242
 
@@ -217,6 +252,7 @@ module Daemons
217
252
 
218
253
  unless options[:ontop]
219
254
  @pid.pid = Daemonize.call_as_daemon(myproc, output_logfile, @group.app_name)
255
+
220
256
  else
221
257
  Daemonize.simulate(output_logfile)
222
258
 
@@ -237,10 +273,13 @@ module Daemons
237
273
  # Process.detach(@pid.pid)
238
274
  # end
239
275
  end
276
+
277
+ started()
240
278
  end
241
279
 
242
280
 
243
281
  def start
282
+ change_privilege
244
283
  @group.create_monitor(@group.applications[0] || self) unless options[:ontop] # we don't monitor applications in the foreground
245
284
 
246
285
  case options[:mode]
@@ -258,6 +297,14 @@ module Daemons
258
297
  end
259
298
  end
260
299
 
300
+ def started
301
+ if pid = @pid.pid
302
+ puts "#{self.group.app_name}: process with pid #{pid} started."
303
+ STDOUT.flush
304
+ end
305
+ end
306
+
307
+
261
308
  # def run
262
309
  # if @group.controller.options[:exec]
263
310
  # run_via_exec()
@@ -274,6 +321,11 @@ module Daemons
274
321
  #
275
322
  # end
276
323
 
324
+ def reload
325
+ Process.kill('HUP', @pid.pid)
326
+ rescue
327
+ # ignore
328
+ end
277
329
 
278
330
  # This is a nice little function for debugging purposes:
279
331
  # In case a multi-threaded ruby script exits due to an uncaught exception
@@ -316,26 +368,70 @@ module Daemons
316
368
  end
317
369
 
318
370
 
319
- def stop
320
- if options[:force] and not running?
371
+ def stop(no_wait = false)
372
+ if not running?
321
373
  self.zap
322
374
  return
323
375
  end
324
376
 
377
+ pid = @pid.pid
378
+
325
379
  # Catch errors when trying to kill a process that doesn't
326
380
  # exist. This happens when the process quits and hasn't been
327
381
  # restarted by the monitor yet. By catching the error, we allow the
328
382
  # pid file clean-up to occur.
329
383
  begin
330
- Process.kill(SIGNAL, @pid.pid)
384
+ Process.kill(SIGNAL, pid)
331
385
  rescue Errno::ESRCH => e
332
- puts "#{e} #{@pid.pid}"
386
+ puts "#{e} #{pid}"
333
387
  puts "deleting pid-file."
334
388
  end
335
389
 
336
- # We try to remove the pid-files by ourselves, in case the application
337
- # didn't clean it up.
338
- begin; @pid.cleanup; rescue ::Exception; end
390
+ if not no_wait
391
+ if @force_kill_waittime > 0
392
+ puts "#{self.group.app_name}: trying to stop process with pid #{pid}..."
393
+ STDOUT.flush
394
+
395
+ begin
396
+ Timeout::timeout(@force_kill_waittime) {
397
+ while @pid.running?
398
+ sleep(0.2)
399
+ end
400
+ }
401
+ rescue Timeout::Error
402
+ puts "#{self.group.app_name}: process with pid #{pid} won't stop, we forcefully kill it..."
403
+ STDOUT.flush
404
+
405
+ begin
406
+ Process.kill('KILL', pid)
407
+ rescue Errno::ESRCH
408
+ end
409
+
410
+ begin
411
+ Timeout::timeout(20) {
412
+ while @pid.running?
413
+ sleep(1)
414
+ end
415
+ }
416
+ rescue Timeout::Error
417
+ puts "#{self.group.app_name}: unable to forcefully kill process with pid #{pid}."
418
+ STDOUT.flush
419
+ end
420
+ end
421
+ end
422
+
423
+
424
+ end
425
+
426
+ sleep(0.1)
427
+ unless @pid.running?
428
+ # We try to remove the pid-files by ourselves, in case the application
429
+ # didn't clean it up.
430
+ begin; @pid.cleanup; rescue ::Exception; end
431
+
432
+ puts "#{self.group.app_name}: process with pid #{pid} successfully stopped."
433
+ STDOUT.flush
434
+ end
339
435
 
340
436
  end
341
437
 
@@ -369,4 +465,4 @@ module Daemons
369
465
  end
370
466
  end
371
467
 
372
- end
468
+ end
@@ -42,6 +42,7 @@ module Daemons
42
42
  @dir = options[:dir] || ''
43
43
 
44
44
  @keep_pid_files = options[:keep_pid_files] || false
45
+ @no_pidfiles = options[:no_pidfiles] || false
45
46
 
46
47
  #@applications = find_applications(pidfile_dir())
47
48
  @applications = []
@@ -60,6 +61,41 @@ module Daemons
60
61
  end
61
62
 
62
63
  def find_applications(dir)
64
+ if @no_pidfiles
65
+ return find_applications_by_app_name(app_name)
66
+ else
67
+ return find_applications_by_pidfiles(dir)
68
+ end
69
+ end
70
+
71
+ # TODO: identifiy the monitor process
72
+ def find_applications_by_app_name(app_name)
73
+ pids = []
74
+
75
+ begin
76
+ x = `ps auxw | grep -v grep | awk '{print $2, $11, $12}' | grep #{app_name}`
77
+ if x && x.chomp!
78
+ processes = x.split(/\n/).compact
79
+ processes = processes.delete_if do |p|
80
+ pid, name, add = p.split(/\s/)
81
+ # We want to make sure that the first part of the process name matches
82
+ # so that app_name matches app_name_22
83
+
84
+ app_name != name[0..(app_name.length - 1)] and not add.include?(app_name)
85
+ end
86
+ pids = processes.map {|p| p.split(/\s/)[0].to_i}
87
+ end
88
+ rescue ::Exception
89
+ end
90
+
91
+ return pids.map {|f|
92
+ app = Application.new(self, {}, PidMem.existing(f))
93
+ setup_app(app)
94
+ app
95
+ }
96
+ end
97
+
98
+ def find_applications_by_pidfiles(dir)
63
99
  pid_files = PidFile.find_files(dir, app_name, ! @keep_pid_files)
64
100
 
65
101
  #pp pid_files
@@ -125,18 +161,24 @@ module Daemons
125
161
  }
126
162
  end
127
163
 
128
- def stop_all(force = false)
164
+ def stop_all(no_wait = false)
129
165
  @monitor.stop if @monitor
130
166
 
167
+ threads = []
168
+
131
169
  @applications.each {|a|
132
- if force
133
- begin; a.stop; rescue ::Exception; end
134
- else
135
- a.stop
170
+ threads << Thread.new do
171
+ a.stop(no_wait)
136
172
  end
137
173
  }
174
+
175
+ threads.each {|t| t.join}
138
176
  end
139
177
 
178
+ def reload_all
179
+ @applications.each {|a| a.reload}
180
+ end
181
+
140
182
  def zap_all
141
183
  @monitor.stop if @monitor
142
184
 
@@ -149,4 +191,4 @@ module Daemons
149
191
 
150
192
  end
151
193
 
152
- end
194
+ end
@@ -0,0 +1,19 @@
1
+ require 'daemons/etc_extension'
2
+
3
+ class CurrentProcess
4
+ def self.change_privilege(user, group=user)
5
+ puts "Changing process privilege to #{user}:#{group}"
6
+
7
+ uid, gid = Process.euid, Process.egid
8
+ target_uid = Etc.getpwnam(user).uid
9
+ target_gid = Etc.getgrnam(group).gid
10
+
11
+ if uid != target_uid || gid != target_gid
12
+ Process.initgroups(user, target_gid)
13
+ Process::GID.change_privilege(target_gid)
14
+ Process::UID.change_privilege(target_uid)
15
+ end
16
+ rescue Errno::EPERM => e
17
+ raise "Couldn't change user and group to #{user}:#{group}: #{e}"
18
+ end
19
+ end
@@ -26,6 +26,10 @@ module Daemons
26
26
  @options[:force] = t
27
27
  end
28
28
 
29
+ opts.on("-n", "--no_wait", "Do not wait for processes to stop") do |t|
30
+ @options[:no_wait] = t
31
+ end
32
+
29
33
  #opts.separator ""
30
34
  #opts.separator "Specific options:"
31
35
 
@@ -56,6 +60,7 @@ module Daemons
56
60
  @usage = <<END
57
61
  -t, --ontop Stay on top (does not daemonize)
58
62
  -f, --force Force operation
63
+ -n, --no_wait Do not wait for processes to stop
59
64
 
60
65
  Common options:
61
66
  -h, --help Show this message
@@ -92,8 +97,10 @@ END
92
97
  puts " start start an instance of the application"
93
98
  puts " stop stop all instances of the application"
94
99
  puts " restart stop all instances and restart them afterwards"
100
+ puts " reload send a SIGHUP to all instances of the application"
95
101
  puts " run start the application and stay on top"
96
102
  puts " zap set the application to a stopped state"
103
+ puts " status show status (PID) of application instances"
97
104
  puts
98
105
  puts "* and where <options> may contain several of the following:"
99
106
 
@@ -114,4 +121,4 @@ END
114
121
 
115
122
  end
116
123
 
117
- end
124
+ end
@@ -15,6 +15,7 @@ module Daemons
15
15
  'restart',
16
16
  'run',
17
17
  'zap',
18
+ 'reload',
18
19
  'status'
19
20
  ]
20
21
 
@@ -71,13 +72,18 @@ module Daemons
71
72
  @options[:ontop] ||= true
72
73
  @group.new_application.start
73
74
  when 'stop'
74
- @group.stop_all
75
+ @group.stop_all(@options[:no_wait])
75
76
  when 'restart'
76
77
  unless @group.applications.empty?
77
78
  @group.stop_all
78
- sleep 1
79
+ sleep(1)
79
80
  @group.start_all
81
+ else
82
+ puts "Warning: no instances running. Starting..."
83
+ @group.new_application.start
80
84
  end
85
+ when 'reload'
86
+ @group.reload_all
81
87
  when 'zap'
82
88
  @group.zap_all
83
89
  when 'status'
@@ -131,4 +137,4 @@ module Daemons
131
137
  end
132
138
  end
133
139
 
134
- end
140
+ end
@@ -186,6 +186,13 @@ module Daemonize
186
186
  end
187
187
  end
188
188
  end
189
+
190
+ ios = Array.new(8192){|i| IO.for_fd(i) rescue nil}.compact
191
+ ios.each do |io|
192
+ next if io.fileno < 3
193
+ io.close
194
+ end
195
+
189
196
 
190
197
  redirect_io(logfile_name)
191
198
 
@@ -247,6 +254,7 @@ module Daemonize
247
254
  if logfile_name
248
255
  begin
249
256
  STDOUT.reopen logfile_name, "a"
257
+ File.chmod(0644, logfile_name)
250
258
  STDOUT.sync = true
251
259
  rescue ::Exception
252
260
  begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end
@@ -0,0 +1,12 @@
1
+ require 'etc'
2
+
3
+ Etc.instance_eval do
4
+ def groupname(gid)
5
+ Etc.group {|e| return e.name if gid == e.gid }
6
+ nil
7
+ end
8
+ def username(uid)
9
+ Etc.passwd {|e| return e.name if uid == e.uid }
10
+ nil
11
+ end
12
+ end
@@ -116,7 +116,18 @@ module Daemons
116
116
 
117
117
 
118
118
  def stop
119
- begin; Process.kill(Application::SIGNAL, @pid.pid); rescue ::Exception; end
119
+ begin
120
+ pid = @pid.pid
121
+ Process.kill(Application::SIGNAL, pid)
122
+ Timeout::timeout(5) {
123
+ while Pid.running?(pid)
124
+ sleep(0.1)
125
+ end
126
+ }
127
+ rescue ::Exception => e
128
+ puts "#{e} #{pid}"
129
+ puts "deleting pid-file."
130
+ end
120
131
 
121
132
  # We try to remove the pid-files by ourselves, in case the application
122
133
  # didn't clean it up.
data/lib/daemons/pid.rb CHANGED
@@ -6,6 +6,8 @@ module Daemons
6
6
  class Pid
7
7
 
8
8
  def Pid.running?(pid)
9
+ return false unless pid
10
+
9
11
  # Check if process is in existence
10
12
  # The simplest way to do this is to send signal '0'
11
13
  # (which is a single system call) that doesn't actually
@@ -49,6 +51,7 @@ module Daemons
49
51
  # end
50
52
 
51
53
 
54
+
52
55
  # Returns the directory that should be used to write the pid file to
53
56
  # depending on the given mode.
54
57
  #
@@ -86,11 +89,16 @@ module Daemons
86
89
  def pid=(p)
87
90
  end
88
91
 
92
+ # Check whether the process is running
93
+ def running?
94
+ return Pid.running?(pid())
95
+ end
96
+
89
97
  # Cleanup method
90
98
  def cleanup
91
99
  end
92
100
 
93
- # Exists? method
101
+ # Exist? method
94
102
  def exist?
95
103
  true
96
104
  end
@@ -92,18 +92,23 @@ module Daemons
92
92
 
93
93
  def pid=(p)
94
94
  File.open(filename, 'w') {|f|
95
+ f.chmod(0644)
95
96
  f.puts p #Process.pid
96
97
  }
97
98
  end
98
99
 
99
100
  def cleanup
100
- File.delete(filename)
101
+ File.delete(filename) if pid == Process.pid
101
102
  end
102
103
 
103
104
  def pid
104
- File.open(filename) {|f|
105
- return f.gets.to_i
106
- }
105
+ begin
106
+ File.open(filename) {|f|
107
+ return f.gets.to_i
108
+ }
109
+ rescue ::Exception
110
+ return nil
111
+ end
107
112
  end
108
113
 
109
114
  end
@@ -5,6 +5,15 @@ module Daemons
5
5
 
6
6
  class PidMem < Pid
7
7
  attr_accessor :pid
8
+
9
+ def PidMem.existing(numeric_pid)
10
+ new_instance = PidMem.allocate
11
+
12
+ new_instance.instance_variable_set(:@pid, numeric_pid)
13
+
14
+ return new_instance
15
+ end
16
+
8
17
  end
9
18
 
10
19
  end
data/lib/daemons.rb CHANGED
@@ -12,6 +12,7 @@ require 'daemons/application'
12
12
  require 'daemons/application_group'
13
13
  require 'daemons/controller'
14
14
 
15
+ require 'timeout'
15
16
 
16
17
  # All functions and classes that Daemons provides reside in this module.
17
18
  #
@@ -65,7 +66,7 @@ require 'daemons/controller'
65
66
  #
66
67
  module Daemons
67
68
 
68
- VERSION = "1.0.10"
69
+ VERSION = "1.1.0"
69
70
 
70
71
  require 'daemons/daemonize'
71
72
 
@@ -106,6 +107,7 @@ module Daemons
106
107
  # <tt>:ontop</tt>:: When given (i.e. set to true), stay on top, i.e. do not daemonize the application
107
108
  # (but the pid-file and other things are written as usual)
108
109
  # <tt>:mode</tt>:: <tt>:load</tt> Load the script with <tt>Kernel.load</tt>;
110
+ # note that :stop_proc only works for the :load (and :proc) mode.
109
111
  # <tt>:exec</tt> Execute the script file with <tt>Kernel.exec</tt>
110
112
  # <tt>:backtrace</tt>:: Write a backtrace of the last exceptions to the file '[app_name].log' in the
111
113
  # pid-file directory if the application exits due to an uncaught exception
@@ -114,6 +116,8 @@ module Daemons
114
116
  # <tt>:keep_pid_files</tt>:: When given do not delete lingering pid-files (files for which the process is no longer running).
115
117
  # <tt>:hard_exit</tt>:: When given use exit! to end a daemons instead of exit (this will for example
116
118
  # not call at_exit handlers).
119
+ # <tt>:stop_proc</tt>:: A proc that will be called when the daemonized process receives a request to stop (works only for :load and :proc mode)
120
+ #
117
121
  # -----
118
122
  #
119
123
  # === Example:
@@ -158,6 +162,7 @@ module Daemons
158
162
  # +options+:: A hash that may contain one or more of the options listed in the documentation for Daemons.run
159
163
  #
160
164
  # A block must be given to this function. The block will be used as the :proc entry in the options hash.
165
+ #
161
166
  # -----
162
167
  #
163
168
  # === Example:
@@ -267,7 +272,7 @@ module Daemons
267
272
  # }
268
273
  #
269
274
  def daemonize(options = {})
270
- @group ||= ApplicationGroup.new('self', options)
275
+ @group ||= ApplicationGroup.new(options[:app_name] || 'self', options)
271
276
 
272
277
  @group.new_application(:mode => :none).start
273
278
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: daemons
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.10
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Uehlinger
@@ -9,11 +9,11 @@ autorequire: daemons
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-03-21 00:00:00 +01:00
12
+ date: 2010-06-20 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
16
- description: Daemons provides an easy way to wrap existing ruby scripts (for example a self-written server) to be run as a daemon and to be controlled by simple start/stop/restart commands. You can also call blocks as daemons and control them from the parent or just daemonize the current process. Besides this basic functionality, daemons offers many advanced features like exception backtracing and logging (in case your ruby script crashes) and monitoring and automatic restarting of your processes if they crash.
16
+ description: " Daemons provides an easy way to wrap existing ruby scripts (for example a self-written server) \n to be run as a daemon and to be controlled by simple start/stop/restart commands.\n \n You can also call blocks as daemons and control them from the parent or just daemonize the current\n process.\n \n Besides this basic functionality, daemons offers many advanced features like exception \n backtracing and logging (in case your ruby script crashes) and monitoring and automatic\n restarting of your processes if they crash.\n"
17
17
  email: th.uehlinger@gmx.ch
18
18
  executables: []
19
19
 
@@ -30,43 +30,46 @@ files:
30
30
  - README
31
31
  - LICENSE
32
32
  - setup.rb
33
- - lib/daemons/application.rb
33
+ - lib/daemons.rb
34
+ - lib/daemons/monitor.rb
34
35
  - lib/daemons/application_group.rb
36
+ - lib/daemons/etc_extension.rb
37
+ - lib/daemons/daemonize.rb
35
38
  - lib/daemons/cmdline.rb
36
39
  - lib/daemons/controller.rb
37
- - lib/daemons/daemonize.rb
38
- - lib/daemons/exceptions.rb
39
- - lib/daemons/monitor.rb
40
+ - lib/daemons/change_privilege.rb
41
+ - lib/daemons/application.rb
42
+ - lib/daemons/pidmem.rb
40
43
  - lib/daemons/pid.rb
41
44
  - lib/daemons/pidfile.rb
42
- - lib/daemons/pidmem.rb
43
- - lib/daemons.rb
44
- - examples/call
45
+ - lib/daemons/exceptions.rb
45
46
  - examples/call/call.rb
46
47
  - examples/call/call_monitor.rb
47
- - examples/daemonize
48
- - examples/daemonize/daemonize.rb
49
- - examples/run
50
- - examples/run/ctrl_crash.rb
51
- - examples/run/ctrl_exec.rb
52
- - examples/run/ctrl_exit.rb
53
- - examples/run/ctrl_keep_pid_files.rb
48
+ - examples/run/ctrl_normal.rb
54
49
  - examples/run/ctrl_monitor.rb
50
+ - examples/run/ctrl_proc.rb
55
51
  - examples/run/ctrl_multiple.rb
56
- - examples/run/ctrl_normal.rb
57
- - examples/run/ctrl_ontop.rb
58
52
  - examples/run/ctrl_optionparser.rb
59
- - examples/run/ctrl_proc.rb
60
- - examples/run/ctrl_proc.rb.output
61
- - examples/run/ctrl_proc_multiple.rb
62
- - examples/run/ctrl_proc_multiple.rb.output
63
- - examples/run/ctrl_proc_simple.rb
64
53
  - examples/run/myserver.rb
54
+ - examples/run/myserver_hanging.rb
55
+ - examples/run/ctrl_exit.rb
65
56
  - examples/run/myserver_crashing.rb
57
+ - examples/run/ctrl_proc_multiple.rb
58
+ - examples/run/ctrl_proc.rb.output
59
+ - examples/run/ctrl_keep_pid_files.rb
60
+ - examples/run/ctrl_proc_simple.rb
61
+ - examples/run/ctrl_ontop.rb
62
+ - examples/run/ctrl_crash.rb
63
+ - examples/run/ctrl_exec.rb
64
+ - examples/run/ctrl_hanging.rb
66
65
  - examples/run/myserver_crashing.rb.output
66
+ - examples/run/ctrl_proc_multiple.rb.output
67
67
  - examples/run/myserver_exiting.rb
68
+ - examples/daemonize/daemonize.rb
68
69
  has_rdoc: true
69
70
  homepage: http://daemons.rubyforge.org
71
+ licenses: []
72
+
70
73
  post_install_message:
71
74
  rdoc_options: []
72
75
 
@@ -87,9 +90,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
90
  requirements: []
88
91
 
89
92
  rubyforge_project: daemons
90
- rubygems_version: 1.0.1
93
+ rubygems_version: 1.3.5
91
94
  signing_key:
92
- specification_version: 2
95
+ specification_version: 3
93
96
  summary: A toolkit to create and control daemons in different ways
94
97
  test_files: []
95
98