#!/usr/bin/env python import sys, os, time, signal, atexit shutdown = False graceful_shutdown = False def sig_handler(sig,frame): global shutdown global graceful_shutdown if sig == signal.SIGINT: graceful_shutdown = True elif sig == signal.SIGTERM: shutdown = True class Daemon(object): def __init__(self, cmd, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): self.stdin = stdin self.stdout = stdout self.stderr = stderr self.cmd = cmd self.pidfile = os.path.splitext(sys.argv[0])[0] + ".pid" def register_handler(self): signal.signal(signal.SIGINT, sig_handler) signal.signal(signal.SIGTERM, sig_handler) signal.signal(signal.SIGCHLD, sig_handler) def daemonize(self): try: pid = os.fork() if pid > 0: # exit first parent sys.exit(0) except OSError, e: sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(1) # decouple from parent environment os.chdir(".") os.setsid() os.umask(0) # do second fork try: pid = os.fork() if pid > 0: # exit from second parent sys.exit(0) except OSError, e: sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(1) # redirect standard file descriptors si = file(self.stdin, 'r') so = file(self.stdout, 'a+') se = file(self.stderr, 'a+', 0) pid = str(os.getpid()) #sys.stderr.write("\n%s\n" % pid) #sys.stderr.flush() if self.pidfile: file(self.pidfile,'w+').write("%s\n" % pid) #atexit.register(self.delpid) os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno()) def get_childs_pid(self, pid): li = [] cmd = "ps -ef|awk '{print $2,$3}'" for item in os.popen(cmd).readlines(): item = item.strip() l = item.split(' ') p1 = l[0].strip() p2 = l[1].strip() if p2 == pid: li.append(p1) return li def get_grand_childs_pid(self,child_pids): li = [] for pid in child_pids: lii = self.get_childs_pid(pid) if len(lii) == 0: continue li.append(lii[0]) return li def start(self): try: num_childs = 1 if num_childs > 0: child = False global shutdown global graceful_shutdown while not child and not shutdown and not graceful_shutdown: if num_childs > 0: pid = os.fork() if pid > 0: num_childs = num_childs - 1 elif pid == 0: child = True else: sys.exit(1) else: exit_stat = os.wait() pid = exit_stat[0] num_childs = num_childs + 1 time.sleep(1) os.system(self.cmd) except OSError, e: sys.stderr.write("fork #3 failed: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(1); def run(self): try: pf = file(self.pidfile,'r') pid = int(pf.read().strip()) pf.close() except IOError: pid = None if pid: message = "pidfile %s already exist. Daemon already running?\n" sys.stderr.write(message % self.pidfile) sys.exit(1) self.daemonize() self.start() def delpid(self): os.remove(self.pidfile) def stop(self): try: pf = file(self.pidfile,'r') pid = int(pf.read().strip()) pf.close() except IOError: pid = None if not pid: message = "pidfile %s does not exist. Daemon not running?\n" sys.stderr.write(message % self.pidfile) return li = self.get_childs_pid(str(pid)) lig = self.get_grand_childs_pid(li) for item in lig: try: os.kill(int(item),signal.SIGINT) os.kill(int(item),signal.SIGTERM) os.kill(int(item),signal.SIGKILL) except: pass try: while 1: os.kill(pid, signal.SIGTERM) time.sleep(0.5) except OSError, err: err = str(err) if err.find("No such process") > 0: if os.path.exists(self.pidfile): os.remove(self.pidfile) else: print str(err) sys.exit(1) def main(): cmd = "php /home/www/shop_develop/crontab/index.php queue index" d = Daemon(cmd) d.register_handler() if len(sys.argv) == 2: if 'start' == sys.argv[1]: try: d.run() except: pass elif 'stop' == sys.argv[1]: print 'stopping...' d.stop() elif 'status' == sys.argv[1]: try: pf = file(d.pidfile,'r') pid = int(pf.read().strip()) pf.close() except IOError: pid = None except SystemExit: pid = None if pid: print 'running as pid %s' % pid else: print 'not running' else: print "Unknown command" sys.exit(2) else: print "usage: %s start|stop|status" % sys.argv[0] sys.exit(2) if __name__ == '__main__': main()