mlanett-daemons 1.0.13 → 1.1.10.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/Gemfile.lock +12 -2
  2. data/LICENSE +1 -8
  3. data/README-mlanett.rdoc +8 -0
  4. data/{README → README.rdoc} +6 -15
  5. data/Releases +84 -9
  6. data/TODO +1 -5
  7. data/daemons.gemspec +1 -0
  8. data/examples/call/call.rb +1 -0
  9. data/examples/daemonize/daemonize.rb +10 -3
  10. data/examples/run/ctrl_hanging.rb +19 -0
  11. data/examples/run/ctrl_monitor_multiple.rb +18 -0
  12. data/examples/run/ctrl_normal.rb +0 -1
  13. data/examples/run/ctrl_proc.rb.output +20 -0
  14. data/examples/run/ctrl_proc_rand.rb +23 -0
  15. data/examples/run/ctrl_slowstop.rb +16 -0
  16. data/examples/run/myserver_crashing.rb +2 -2
  17. data/examples/run/myserver_hanging.rb +21 -0
  18. data/examples/run/myserver_slowstop.rb +21 -0
  19. data/lib/daemons.rb +38 -10
  20. data/lib/daemons/application.rb +131 -26
  21. data/lib/daemons/application_group.rb +58 -10
  22. data/lib/daemons/change_privilege.rb +19 -0
  23. data/lib/daemons/cmdline.rb +10 -6
  24. data/lib/daemons/controller.rb +5 -2
  25. data/lib/daemons/daemonize.rb +64 -150
  26. data/lib/daemons/etc_extension.rb +12 -0
  27. data/lib/daemons/exceptions.rb +3 -0
  28. data/lib/daemons/monitor.rb +27 -19
  29. data/lib/daemons/pid.rb +13 -14
  30. data/lib/daemons/pidfile.rb +14 -7
  31. data/lib/daemons/pidmem.rb +9 -0
  32. data/lib/daemons/version.rb +1 -1
  33. data/spec/pidfile_spec.rb +12 -0
  34. data/spec/spec_helper.rb +1 -0
  35. metadata +31 -47
  36. data/daemons.tmproj +0 -56
  37. data/examples/run/myserver_crashing.rb.output +0 -30
  38. data/html/classes/Daemonize.html +0 -497
  39. data/html/classes/Daemons.html +0 -683
  40. data/html/classes/Daemons/Application.html +0 -836
  41. data/html/classes/Daemons/ApplicationGroup.html +0 -508
  42. data/html/classes/Daemons/CmdException.html +0 -113
  43. data/html/classes/Daemons/Controller.html +0 -429
  44. data/html/classes/Daemons/Error.html +0 -113
  45. data/html/classes/Daemons/Exception.html +0 -111
  46. data/html/classes/Daemons/Monitor.html +0 -263
  47. data/html/classes/Daemons/Optparse.html +0 -244
  48. data/html/classes/Daemons/Pid.html +0 -339
  49. data/html/classes/Daemons/PidFile.html +0 -441
  50. data/html/classes/Daemons/PidMem.html +0 -126
  51. data/html/classes/Daemons/RuntimeException.html +0 -113
  52. data/html/classes/Daemons/SystemError.html +0 -163
  53. data/html/created.rid +0 -1
  54. data/html/files/README.html +0 -377
  55. data/html/files/Releases.html +0 -342
  56. data/html/files/TODO.html +0 -121
  57. data/html/files/lib/daemons/application_group_rb.html +0 -101
  58. data/html/files/lib/daemons/application_rb.html +0 -110
  59. data/html/files/lib/daemons/cmdline_rb.html +0 -101
  60. data/html/files/lib/daemons/controller_rb.html +0 -101
  61. data/html/files/lib/daemons/daemonize_rb.html +0 -207
  62. data/html/files/lib/daemons/exceptions_rb.html +0 -101
  63. data/html/files/lib/daemons/monitor_rb.html +0 -108
  64. data/html/files/lib/daemons/pid_rb.html +0 -108
  65. data/html/files/lib/daemons/pidfile_rb.html +0 -108
  66. data/html/files/lib/daemons/pidmem_rb.html +0 -108
  67. data/html/files/lib/daemons_rb.html +0 -117
  68. data/html/fr_class_index.html +0 -41
  69. data/html/fr_file_index.html +0 -40
  70. data/html/fr_method_index.html +0 -91
  71. data/html/index.html +0 -24
  72. data/html/rdoc-style.css +0 -208
  73. data/test/call_as_daemon.rb +0 -12
  74. data/test/tc_main.rb +0 -24
  75. data/test/test1.rb +0 -19
  76. data/test/testapp.rb +0 -11
@@ -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
@@ -105,12 +141,14 @@ module Daemons
105
141
  private :setup_app
106
142
 
107
143
  def create_monitor(an_app)
108
- return if @monitor
144
+ if @monitor and options[:monitor]
145
+ @monitor.stop
146
+ @monitor = nil
147
+ end
109
148
 
110
149
  if options[:monitor]
111
150
  @monitor = Monitor.new(an_app)
112
-
113
- @monitor.start(@applications)
151
+ @monitor.start(self)
114
152
  end
115
153
  end
116
154
 
@@ -125,18 +163,28 @@ module Daemons
125
163
  }
126
164
  end
127
165
 
128
- def stop_all(force = false)
129
- @monitor.stop if @monitor
166
+ def stop_all(no_wait = false)
167
+ if @monitor
168
+ @monitor.stop
169
+ @monitor = nil
170
+ setup
171
+ end
172
+
173
+ threads = []
130
174
 
131
175
  @applications.each {|a|
132
- if force
133
- begin; a.stop; rescue ::Exception; end
134
- else
135
- a.stop
176
+ threads << Thread.new do
177
+ a.stop(no_wait)
136
178
  end
137
179
  }
180
+
181
+ threads.each {|t| t.join}
138
182
  end
139
183
 
184
+ def reload_all
185
+ @applications.each {|a| a.reload}
186
+ end
187
+
140
188
  def zap_all
141
189
  @monitor.stop if @monitor
142
190
 
@@ -149,4 +197,4 @@ module Daemons
149
197
 
150
198
  end
151
199
 
152
- end
200
+ 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
@@ -10,10 +10,8 @@ module Daemons
10
10
  @options = {}
11
11
 
12
12
  @opts = OptionParser.new do |opts|
13
- #opts.banner = "Usage: example.rb [options]"
14
13
  opts.banner = ""
15
14
 
16
- # Boolean switch.
17
15
  # opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
18
16
  # @options[:verbose] = v
19
17
  # end
@@ -26,6 +24,10 @@ module Daemons
26
24
  @options[:force] = t
27
25
  end
28
26
 
27
+ opts.on("-n", "--no_wait", "Do not wait for processes to stop") do |t|
28
+ @options[:no_wait] = t
29
+ end
30
+
29
31
  #opts.separator ""
30
32
  #opts.separator "Specific options:"
31
33
 
@@ -33,8 +35,7 @@ module Daemons
33
35
  opts.separator ""
34
36
  opts.separator "Common options:"
35
37
 
36
- # No argument, shows at tail. This will print an options summary.
37
- # Try it and see!
38
+ # No argument, shows at tail. This will print an options summary
38
39
  opts.on_tail("-h", "--help", "Show this message") do
39
40
  #puts opts
40
41
  #@usage =
@@ -43,7 +44,7 @@ module Daemons
43
44
  exit
44
45
  end
45
46
 
46
- # Another typical switch to print the version.
47
+ # Switch to print the version.
47
48
  opts.on_tail("--version", "Show version") do
48
49
  puts "daemons version #{Daemons::VERSION}"
49
50
  exit
@@ -56,6 +57,7 @@ module Daemons
56
57
  @usage = <<END
57
58
  -t, --ontop Stay on top (does not daemonize)
58
59
  -f, --force Force operation
60
+ -n, --no_wait Do not wait for processes to stop
59
61
 
60
62
  Common options:
61
63
  -h, --help Show this message
@@ -92,8 +94,10 @@ END
92
94
  puts " start start an instance of the application"
93
95
  puts " stop stop all instances of the application"
94
96
  puts " restart stop all instances and restart them afterwards"
97
+ puts " reload send a SIGHUP to all instances of the application"
95
98
  puts " run start the application and stay on top"
96
99
  puts " zap set the application to a stopped state"
100
+ puts " status show status (PID) of application instances"
97
101
  puts
98
102
  puts "* and where <options> may contain several of the following:"
99
103
 
@@ -114,4 +118,4 @@ END
114
118
 
115
119
  end
116
120
 
117
- end
121
+ 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,16 +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
80
81
  else
81
82
  puts "Warning: no instances running. Starting..."
82
83
  @group.new_application.start
83
84
  end
85
+ when 'reload'
86
+ @group.reload_all
84
87
  when 'zap'
85
88
  @group.zap_all
86
89
  when 'status'
@@ -1,97 +1,5 @@
1
- #--
2
- ###############################################################################
3
- # daemonize.rb is a slightly modified version of daemonize.rb was #
4
- # from the Daemonize Library written by Travis Whitton #
5
- # for details, read the notice below #
6
- ###############################################################################
7
- #++
8
- #
9
- #
10
- # =Daemonize Library
11
- #
12
- # February. 4, 2005 Travis Whitton <whitton@atlantic.net>
13
- #
14
- # Daemonize allows you to easily modify any existing Ruby program to run
15
- # as a daemon. See README.rdoc for more details.
16
- #
17
- # == How to install
18
- # 1. su to root
19
- # 2. ruby install.rb
20
- # build the docs if you want to
21
- # 3. rdoc --main README.rdoc daemonize.rb README.rdoc
22
- #
23
- # == Copying
24
- # The Daemonize extension module is copywrited free software by Travis Whitton
25
- # <whitton@atlantic.net>. You can redistribute it under the terms specified in
26
- # the COPYING file of the Ruby distribution.
27
- #
28
- # == WARRANTY
29
- # THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
30
- # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
31
- # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
32
- # PURPOSE.
33
- #
34
- #
35
- # ----
36
- #
37
- # == Purpose
38
- #
39
- # Daemonize is a module derived from Perl's Proc::Daemon module. This module
40
- # allows you to easily modify any existing Ruby program to run as a daemon.
41
- # A daemon is a process that runs in the background with no controlling terminal.
42
- # Generally servers (like FTP and HTTP servers) run as daemon processes.
43
- # Note, do not make the mistake that a daemon == server. Converting a program
44
- # to a daemon by hand is a relatively simple process; however, this module will
45
- # save you the effort of repeatedly looking up the procedure, and it will also
46
- # insure that your programs are daemonized in the safest and most corrects
47
- # fashion possible.
48
- #
49
- # == Procedure
50
- #
51
- # The Daemonize module does the following:
52
- #
53
- # Forks a child and exits the parent process.
54
- #
55
- # Becomes a session leader (which detaches the program from
56
- # the controlling terminal).
57
- #
58
- # Forks another child process and exits first child. This prevents
59
- # the potential of acquiring a controlling terminal.
60
- #
61
- # Changes the current working directory to "/".
62
- #
63
- # Clears the file creation mask.
64
- #
65
- # Closes file descriptors.
66
- #
67
- # == Example usage
68
- #
69
- # Using the Daemonize module is extremely simple:
70
- #
71
- # require 'daemonize'
72
- #
73
- # class TestDaemon
74
- # include Daemonize
75
- #
76
- # def initialize
77
- # daemonize()
78
- # loop do
79
- # # do some work here
80
- # end
81
- # end
82
- # end
83
- #
84
- # == Credits
85
- #
86
- # Daemonize was written by Travis Whitton and is based on Perl's
87
- # Proc::Daemonize, which was written by Earl Hood. The above documentation
88
- # is also partially borrowed from the Proc::Daemonize POD documentation.
89
-
90
-
91
-
92
1
  module Daemonize
93
- VERSION = "0.1.1m"
94
-
2
+
95
3
  # Try to fork if at all possible retrying every 5 sec if the
96
4
  # maximum process limit for the system has been reached
97
5
  def safefork
@@ -112,38 +20,37 @@ module Daemonize
112
20
  module_function :safefork
113
21
 
114
22
 
115
- def simulate(logfile_name = nil)
116
- # NOTE: STDOUT and STDERR will not be redirected to the logfile, because in :ontop mode, we normally want to see the output
23
+ # Simulate the daemonization process (:ontop mode)
24
+ # NOTE: STDOUT and STDERR will not be redirected to the logfile,
25
+ # because in :ontop mode, we normally want to see the output
26
+ def simulate(logfile_name = nil, app_name = nil)
27
+ $0 = app_name if app_name
117
28
 
118
- Dir.chdir "/" # Release old working directory
119
- File.umask 0000 # Insure sensible umask
29
+ # Release old working directory
30
+ Dir.chdir "/"
31
+
32
+ # Release old working directory
33
+ Dir.chdir "/"
120
34
 
121
- # Make sure all file descriptors are closed
122
- ObjectSpace.each_object(IO) do |io|
123
- unless [STDIN, STDOUT, STDERR].include?(io)
124
- begin
125
- unless io.closed?
126
- io.close
127
- end
128
- rescue ::Exception
129
- end
130
- end
131
- end
35
+ close_io()
132
36
 
133
- # Free file descriptors and
134
- # point them somewhere sensible
135
- # STDOUT/STDERR should go to a logfile
37
+ # Free STDIN and point it to somewhere sensible
38
+ begin; STDIN.reopen "/dev/null"; rescue ::Exception; end
136
39
 
137
- begin; STDIN.reopen "/dev/null"; rescue ::Exception; end
40
+ # Split rand streams between spawning and daemonized process
41
+ srand
138
42
  end
139
43
  module_function :simulate
140
44
 
141
45
 
46
+ # Call a given block as a daemon
142
47
  def call_as_daemon(block, logfile_name = nil, app_name = nil)
48
+ # we use a pipe to return the PID of the daemon
143
49
  rd, wr = IO.pipe
144
50
 
145
51
  if tmppid = safefork
146
- # parent
52
+ # in the parent
53
+
147
54
  wr.close
148
55
  pid = rd.read.to_i
149
56
  rd.close
@@ -152,7 +59,7 @@ module Daemonize
152
59
 
153
60
  return pid
154
61
  else
155
- # child
62
+ # in the child
156
63
 
157
64
  rd.close
158
65
 
@@ -162,33 +69,24 @@ module Daemonize
162
69
  end
163
70
 
164
71
  # Prevent the possibility of acquiring a controlling terminal
165
- #if oldmode.zero?
166
- trap 'SIGHUP', 'IGNORE'
167
- exit if pid = safefork
168
- #end
72
+ trap 'SIGHUP', 'IGNORE'
73
+ exit if pid = safefork
169
74
 
170
75
  wr.write Process.pid
171
76
  wr.close
172
77
 
173
78
  $0 = app_name if app_name
174
79
 
175
- Dir.chdir "/" # Release old working directory
176
- File.umask 0000 # Insure sensible umask
177
-
178
- # Make sure all file descriptors are closed
179
- ObjectSpace.each_object(IO) do |io|
180
- unless [STDIN, STDOUT, STDERR].include?(io)
181
- begin
182
- unless io.closed?
183
- io.close
184
- end
185
- rescue ::Exception
186
- end
187
- end
188
- end
80
+ # Release old working directory
81
+ Dir.chdir "/"
189
82
 
83
+ close_io()
84
+
190
85
  redirect_io(logfile_name)
191
86
 
87
+ # Split rand streams between spawning and daemonized process
88
+ srand
89
+
192
90
  block.call
193
91
 
194
92
  exit
@@ -197,10 +95,10 @@ module Daemonize
197
95
  module_function :call_as_daemon
198
96
 
199
97
 
200
- # This method causes the current running process to become a daemon
98
+ # Transform the current process into a daemon
201
99
  def daemonize(logfile_name = nil, app_name = nil)
202
- srand # Split rand streams between spawning and daemonized process
203
- safefork and exit # Fork and exit from the parent
100
+ # Fork and exit from the parent
101
+ safefork and exit
204
102
 
205
103
  # Detach from the controlling terminal
206
104
  unless sess_id = Process.setsid
@@ -208,17 +106,29 @@ module Daemonize
208
106
  end
209
107
 
210
108
  # Prevent the possibility of acquiring a controlling terminal
211
- #if oldmode.zero?
212
- trap 'SIGHUP', 'IGNORE'
213
- exit if pid = safefork
214
- #end
215
-
109
+ trap 'SIGHUP', 'IGNORE'
110
+ exit if pid = safefork
111
+
216
112
  $0 = app_name if app_name
217
113
 
218
- Dir.chdir "/" # Release old working directory
219
- File.umask 0000 # Insure sensible umask
114
+ # Release old working directory
115
+ Dir.chdir "/"
116
+
117
+ close_io()
220
118
 
221
- # Make sure all file descriptors are closed
119
+ redirect_io(logfile_name)
120
+
121
+ # Split rand streams between spawning and daemonized process
122
+ srand
123
+
124
+ return sess_id
125
+ end
126
+ module_function :daemonize
127
+
128
+
129
+ def close_io()
130
+ # Make sure all input/output streams are closed
131
+ # Part I: close all IO objects (except for STDIN/STDOUT/STDERR)
222
132
  ObjectSpace.each_object(IO) do |io|
223
133
  unless [STDIN, STDOUT, STDERR].include?(io)
224
134
  begin
@@ -229,24 +139,27 @@ module Daemonize
229
139
  end
230
140
  end
231
141
  end
232
-
233
- redirect_io(logfile_name)
234
142
 
235
- #return oldmode ? sess_id : 0 # Return value is mostly irrelevant
236
- return sess_id
143
+ # Make sure all input/output streams are closed
144
+ # Part II: close all file decriptors (except for STDIN/STDOUT/STDERR)
145
+ ios = Array.new(8192) {|i| IO.for_fd(i) rescue nil}.compact
146
+ ios.each do |io|
147
+ next if io.fileno < 3
148
+ io.close
149
+ end
237
150
  end
238
- module_function :daemonize
151
+ module_function :close_io
239
152
 
240
153
 
241
- # Free file descriptors and
154
+ # Free STDIN/STDOUT/STDERR file descriptors and
242
155
  # point them somewhere sensible
243
- # STDOUT/STDERR should go to a logfile
244
156
  def redirect_io(logfile_name)
245
157
  begin; STDIN.reopen "/dev/null"; rescue ::Exception; end
246
158
 
247
159
  if logfile_name
248
160
  begin
249
161
  STDOUT.reopen logfile_name, "a"
162
+ File.chmod(0644, logfile_name)
250
163
  STDOUT.sync = true
251
164
  rescue ::Exception
252
165
  begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end
@@ -260,4 +173,5 @@ module Daemonize
260
173
  end
261
174
  module_function :redirect_io
262
175
 
176
+
263
177
  end