queue-daemon.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #!/usr/bin/env python
  2. import sys, os, time, signal, atexit
  3. shutdown = False
  4. graceful_shutdown = False
  5. def sig_handler(sig,frame):
  6. global shutdown
  7. global graceful_shutdown
  8. if sig == signal.SIGINT:
  9. graceful_shutdown = True
  10. elif sig == signal.SIGTERM:
  11. shutdown = True
  12. class Daemon(object):
  13. def __init__(self, cmd, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
  14. self.stdin = stdin
  15. self.stdout = stdout
  16. self.stderr = stderr
  17. self.cmd = cmd
  18. self.pidfile = os.path.splitext(sys.argv[0])[0] + ".pid"
  19. def register_handler(self):
  20. signal.signal(signal.SIGINT, sig_handler)
  21. signal.signal(signal.SIGTERM, sig_handler)
  22. signal.signal(signal.SIGCHLD, sig_handler)
  23. def daemonize(self):
  24. try:
  25. pid = os.fork()
  26. if pid > 0:
  27. # exit first parent
  28. sys.exit(0)
  29. except OSError, e:
  30. sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
  31. sys.exit(1)
  32. # decouple from parent environment
  33. os.chdir(".")
  34. os.setsid()
  35. os.umask(0)
  36. # do second fork
  37. try:
  38. pid = os.fork()
  39. if pid > 0:
  40. # exit from second parent
  41. sys.exit(0)
  42. except OSError, e:
  43. sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
  44. sys.exit(1)
  45. # redirect standard file descriptors
  46. si = file(self.stdin, 'r')
  47. so = file(self.stdout, 'a+')
  48. se = file(self.stderr, 'a+', 0)
  49. pid = str(os.getpid())
  50. #sys.stderr.write("\n%s\n" % pid)
  51. #sys.stderr.flush()
  52. if self.pidfile:
  53. file(self.pidfile,'w+').write("%s\n" % pid)
  54. #atexit.register(self.delpid)
  55. os.dup2(si.fileno(), sys.stdin.fileno())
  56. os.dup2(so.fileno(), sys.stdout.fileno())
  57. os.dup2(se.fileno(), sys.stderr.fileno())
  58. def get_childs_pid(self, pid):
  59. li = []
  60. cmd = "ps -ef|awk '{print $2,$3}'"
  61. for item in os.popen(cmd).readlines():
  62. item = item.strip()
  63. l = item.split(' ')
  64. p1 = l[0].strip()
  65. p2 = l[1].strip()
  66. if p2 == pid:
  67. li.append(p1)
  68. return li
  69. def get_grand_childs_pid(self,child_pids):
  70. li = []
  71. for pid in child_pids:
  72. lii = self.get_childs_pid(pid)
  73. if len(lii) == 0:
  74. continue
  75. li.append(lii[0])
  76. return li
  77. def start(self):
  78. try:
  79. num_childs = 1
  80. if num_childs > 0:
  81. child = False
  82. global shutdown
  83. global graceful_shutdown
  84. while not child and not shutdown and not graceful_shutdown:
  85. if num_childs > 0:
  86. pid = os.fork()
  87. if pid > 0:
  88. num_childs = num_childs - 1
  89. elif pid == 0:
  90. child = True
  91. else:
  92. sys.exit(1)
  93. else:
  94. exit_stat = os.wait()
  95. pid = exit_stat[0]
  96. num_childs = num_childs + 1
  97. time.sleep(1)
  98. os.system(self.cmd)
  99. except OSError, e:
  100. sys.stderr.write("fork #3 failed: %d (%s)\n" % (e.errno, e.strerror))
  101. sys.exit(1);
  102. def run(self):
  103. try:
  104. pf = file(self.pidfile,'r')
  105. pid = int(pf.read().strip())
  106. pf.close()
  107. except IOError:
  108. pid = None
  109. if pid:
  110. message = "pidfile %s already exist. Daemon already running?\n"
  111. sys.stderr.write(message % self.pidfile)
  112. sys.exit(1)
  113. self.daemonize()
  114. self.start()
  115. def delpid(self):
  116. os.remove(self.pidfile)
  117. def stop(self):
  118. try:
  119. pf = file(self.pidfile,'r')
  120. pid = int(pf.read().strip())
  121. pf.close()
  122. except IOError:
  123. pid = None
  124. if not pid:
  125. message = "pidfile %s does not exist. Daemon not running?\n"
  126. sys.stderr.write(message % self.pidfile)
  127. return
  128. li = self.get_childs_pid(str(pid))
  129. lig = self.get_grand_childs_pid(li)
  130. for item in lig:
  131. try:
  132. os.kill(int(item),signal.SIGINT)
  133. os.kill(int(item),signal.SIGTERM)
  134. os.kill(int(item),signal.SIGKILL)
  135. except:
  136. pass
  137. try:
  138. while 1:
  139. os.kill(pid, signal.SIGTERM)
  140. time.sleep(0.5)
  141. except OSError, err:
  142. err = str(err)
  143. if err.find("No such process") > 0:
  144. if os.path.exists(self.pidfile):
  145. os.remove(self.pidfile)
  146. else:
  147. print str(err)
  148. sys.exit(1)
  149. def main():
  150. cmd = "php /home/www/shop_develop/crontab/index.php queue index"
  151. d = Daemon(cmd)
  152. d.register_handler()
  153. if len(sys.argv) == 2:
  154. if 'start' == sys.argv[1]:
  155. try:
  156. d.run()
  157. except:
  158. pass
  159. elif 'stop' == sys.argv[1]:
  160. print 'stopping...'
  161. d.stop()
  162. elif 'status' == sys.argv[1]:
  163. try:
  164. pf = file(d.pidfile,'r')
  165. pid = int(pf.read().strip())
  166. pf.close()
  167. except IOError:
  168. pid = None
  169. except SystemExit:
  170. pid = None
  171. if pid:
  172. print 'running as pid %s' % pid
  173. else:
  174. print 'not running'
  175. else:
  176. print "Unknown command"
  177. sys.exit(2)
  178. else:
  179. print "usage: %s start|stop|status" % sys.argv[0]
  180. sys.exit(2)
  181. if __name__ == '__main__':
  182. main()