• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

"yadaemon.rb" is my daemon wrapper class to protect the multiple process invocation.


Commit MetaInfo

Révisiondfde30b1f5206e919aa28aef23e372dd23e7ec7d (tree)
l'heure2011-01-24 01:15:15
AuteurYasuhiro ABE <yasundial@user...>
CommiterYasuhiro ABE

Message de Log

Fixed typos, such as "initializea"
Enhancement "stop" method to use the "stop.txt" file.
Added the "running" method which will work with the "stop.txt" file.
Fixed the @file_perms never be used bug.
Fixed the return code evaluation of the File::chown from zero (ruby1.8) to one (ruby1.9).
Added the "write_file" module method and work to write some files.

Change Summary

Modification

--- a/sample/change_euid.rb
+++ b/sample/change_euid.rb
@@ -36,7 +36,7 @@ end
3636
3737 daemon.run do |pid|
3838 i = 0
39- while true
39+ while daemon.running
4040 open(outfile,"w") do |f|
4141 f.flock(File::LOCK_EX)
4242 f.write(format("%s: %s\n", open(pid).read, i))
--- a/sample/first_step.rb
+++ b/sample/first_step.rb
@@ -15,7 +15,7 @@ daemon = YaDaemon.new(appname,"test.pid","/tmp", opts) ## the "/tmp/#{appname}/
1515 outfile = "/tmp/#{appname}/test.log" ## Check this file each five seconds later.
1616 daemon.run do |pid|
1717 i = 0
18- while true
18+ while daemon.running
1919 open(outfile,"w") do |f|
2020 f.flock(File::LOCK_EX)
2121 f.write(format("updated: %d\n", i))
--- a/sample/start_stop.rb
+++ b/sample/start_stop.rb
@@ -34,7 +34,7 @@ end
3434
3535 daemon.run do |pid|
3636 i = 0
37- while true
37+ while daemon.running
3838 open(outfile,"w") do |f|
3939 f.flock(File::LOCK_EX)
4040 f.write(format("%s: %s\n", open(pid).read, i))
--- a/yadaemon.rb
+++ b/yadaemon.rb
@@ -39,7 +39,7 @@
3939 # {:daemon=>false,:debug=>true})
4040 # daemon.run do |pid| ## pid == /tmp/myappname/myappname.pid
4141 # ## please write you code like the following;
42-# while true
42+# while daemon.running
4343 # puts Time.now
4444 # sleep 3
4545 # end
@@ -93,7 +93,7 @@
9393 #
9494 # "0755" or "755" will be converted to a octal variable by the 'oct' method.
9595 # If you use a numeric variable, you must use octal expression, like 0755.
96-# It means that 755 is wrong expression.
96+# It means that 755 is wrong expression, but 493 is correct.
9797 #
9898 #=File Permissions
9999 #
@@ -105,13 +105,13 @@
105105 # If you use :debug=true option, the piddir/appname/"debug.log" file
106106 # will be also created by uid:gid, and then chown-ed by euid:egid.
107107 #
108-# | @pidpath |
109-# | @piddir | |
110-# | pidpdir | appname | pidfile | "debug.log" |
111-# ---------+---------+---------+---------+-------------+
112-# user id | x | <uid>* | <uid>* | @euid= |
113-# group id | x | - | - | @egid= |
114-# ---------+---------+---------+---------+-------------+
108+# | @pidpath | | |
109+# | @piddir / | | |
110+# | pidpdir / appname / pidfile | "debug.log" | "stop.txt" |
111+# ---------+---------+---------+---------+-------------+------------+
112+# user id | x | @euid= | <uid>= | @euid= | @euid* |
113+# group id | x | - | - | @egid= | @egid= |
114+# ---------+---------+---------+---------+-------------+------------+
115115 # (<uid>,<gid> is same as Process::uid, Process::gid)
116116 # ('=' means these ownerships will be overwritten)
117117 # ('*' means it should be writable by that id)
@@ -134,20 +134,22 @@
134134 # limitations under the License.
135135 #
136136 #
137-
138137 # It's a utility class to process common tasks.
139138 # These methods should be tested by the unit test script.
139+#
140140 module YaDaemonUtils
141-
141+
142+ ##
143+ ## Note:
144+ ## The following methods having same prefix 'check_' are support methods for the option parser.
145+ ##
142146 def check_boolean(opts, label)
143147 (opts.has_key?(label) and (opts[label].kind_of?(FalseClass) or opts[label].kind_of?(TrueClass))) ? opts[label] : false
144148 end
145-
146149 def check_eugid(opts, label)
147150 label = "uid" if Process::methods.index(label) == nil
148151 (Process::uid == 0 and opts.has_key?(label) and opts[label].methods.index(:to_i) != nil) ? opts[label].to_i : Process.method(label).call
149152 end
150-
151153 def check_default_perms(opts,label)
152154 perm = 0711
153155 if opts.has_key?(label)
@@ -159,6 +161,25 @@ module YaDaemonUtils
159161 end
160162 perm
161163 end
164+
165+ ## It's a wrapper method to write something to the given filepath.
166+ ## args: perms must be fixed num
167+ ## return: true(if success) or false
168+ def write_file(filepath, perms, data)
169+ ret = false
170+ begin
171+ open(filepath, File::RDWR|File::CREAT, perms) do |f|
172+ f.flock(File::LOCK_EX)
173+ f.write(data.to_s)
174+ f.flush
175+ f.truncate(f.pos)
176+ end
177+ ret = true
178+ rescue
179+ ret = false
180+ end
181+ ret
182+ end
162183 end
163184
164185 ## It is a simple unix-like daemon class.
@@ -194,30 +215,51 @@ class YaDaemon
194215 @egid = check_eugid(opts,:egid)
195216 @file_perms = check_default_perms(opts,:perms)
196217
197- ## pidpdir must exist.
218+ ## take care the pidpdir which must exists.
198219 raise "pidpdir, #{pidpdir}, not exist." if not FileTest::exist?(pidpdir)
199-
220+
221+ ## prepare @piddir and @pidpath
200222 @piddir = File::join([File::expand_path(pidpdir),appname])
201223 raise "cannot mkdir(#{piddir})" if not FileTest::exist?(@piddir) and Dir::mkdir(@piddir) != 0
202-
224+ ## change ownership of @piddir
225+ stat = File::Stat.new(@piddir)
226+ if stat.uid != @euid
227+ if File::chown(@euid, nil, @piddir) == 1
228+ logit "initialize: succesfully changed #{@piddir}'s ownership."
229+ else
230+ raise "failed to chown #{@piddir}."
231+ end
232+ end
203233 @pidpath = File::join([@piddir, pidfile])
204- @debugfile = File::join([@piddir,"debug.log"]) if @debug
234+
235+ ## prepare the @stopfile
236+ ## used by run/stop methods and delete if existing.
237+ @stopfile = File::join([@piddir, "stop.txt"])
238+ if FileTest.exist?(@stopfile)
239+ if File::unlink(@stopfile) != 1
240+ logit "failed to delete the stop file, #{@stopfile}."
241+ raise "failed to delete the stop file, #{@stopfile}."
242+ end
243+ end
205244
245+ ## prepare the @debugfile
246+ @debugfile = File::join([@piddir,"debug.log"]) if @debug
206247 ## change owner,group of @debugfile.
207248 if @debug and Process::uid == 0
208- if not FileTest::exist?(@debugfile)
209- begin
210- ## touch @debugfile
211- open(@debugfile,"w") do |f| f.write() end
212- rescue
213- raise "cannot touch debug.log, #{@debugfile}."
249+ if not FileTest::exist?(@debugfile)
250+ if write_file(@debugfile, @file_perms, "")
251+ logit "succesfully create the debug.log file, #{@debugfile}."
252+ else
253+ logit "failed to touch the debug.log file, #{@debugfile}."
254+ raise "failed to touch the debug.log file, #{@debugfile}."
214255 end
215256 end
216257 stat = File::Stat.new(@debugfile)
217258 if stat.uid != @euid or stat.gid != @egid
218- if File::chown(@euid, @egid, @debugfile) == 0
219- logit "initializea: succesfully changed #{@debugfile}'s ownership."
259+ if File::chown(@euid, @egid, @debugfile) == 1
260+ logit "initialize: succesfully changed #{@debugfile}'s ownership."
220261 else
262+ logit "failed to chown #{@debugfile}."
221263 raise "failed to chown #{@debugfile}."
222264 end
223265 end
@@ -228,12 +270,12 @@ class YaDaemon
228270 logit "get_pid: called"
229271 pid = 0
230272 begin
231- open(@pidpath).each_line do |l| pid = l end
273+ open(@pidpath).each_line do |l| pid = l.to_i end
232274 rescue
233275 logit "get_pid: failed to open the pid file, @pidpath."
234276 end
235277 logit "get_pid: return #{pid}"
236- pid.to_i
278+ pid
237279 end
238280
239281 ## If a running process was found and it was not the own process, then return true.
@@ -251,9 +293,9 @@ class YaDaemon
251293 logit("check_proc: the pid file exists, but it has own process number. It's harmless, but should be never called.")
252294 return ret
253295 end
254- ## case 2: check /proc/$pid. (available on limited systems only)
296+ ## case 2a: check /proc/$pid. (available on limited systems only)
255297 ## skipped.
256- ## case 3: using kill -0 method (widely available on unix-like systems)
298+ ## case 2b: using kill -0 method (widely available on unix-like systems)
257299 begin
258300 k = Process::kill(0, pid)
259301 ret = true if k == 1
@@ -265,20 +307,15 @@ class YaDaemon
265307 ret
266308 end
267309
310+ def create_stop_file
311+ ret = write_file(@stopfile, @file_perms, "")
312+ logit "create_stop_file: return #{ret}"
313+ ret
314+ end
315+
268316 ## If there is no running process, then the pid file will be overwritten.
269317 def overwrite_pid_file
270- logit "overwrite_pid_file: called"
271- ret = false
272- begin
273- open(@pidpath, "w", 0644) do |f|
274- f.write(Process::pid.to_s)
275- f.flush
276- f.truncate(f.pos)
277- end
278- ret = true
279- rescue
280- ret = false
281- end
318+ ret = write_file(@pidpath, @file_perms, Process::pid.to_s)
282319 logit "overwrite_pid_file: return #{ret}"
283320 ret
284321 end
@@ -327,6 +364,10 @@ class YaDaemon
327364
328365 def stop
329366 logit "stop: called"
367+
368+ ## overwrite @stopfile
369+ create_stop_file()
370+
330371 if not check_proc
331372 logit "stop: this process has already stopped."
332373 return
@@ -363,4 +404,9 @@ class YaDaemon
363404 end
364405 ret
365406 end
407+
408+ def running
409+ not FileTest.exist?(@stopfile)
410+ end
411+
366412 end