• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

よく使われているワード(クリックで追加)

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

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


コミットメタ情報

リビジョンdfde30b1f5206e919aa28aef23e372dd23e7ec7d (tree)
日時2011-01-24 01:15:15
作者Yasuhiro ABE <yasundial@user...>
コミッターYasuhiro ABE

ログメッセージ

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.

変更サマリ

差分

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