mlanett-daemons 1.0.13 → 1.1.10.2

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