In everbright task schedule project, we need some daemon process to do certain work, here is a example of daemon class:
1 #encoding=utf-8 2 #!/usr/bin/env python 3 4 import sys, os, time, atexit 5 from signal import SIGTERM 6 Basedir='/home/ronglian/project/taskschedule' 7 class Daemon: 8 """ 9 A generic daemon class. 10 11 Usage: subclass the Daemon class and override the run() method 12 """ 13 def __init__(self, pidfile, stderr=Basedir+'/logs/deamon_err.log', stdout=Basedir+'/logs/deamon_out.log', stdin='/dev/null'): 14 self.stdin = stdin 15 self.stdout = stdout 16 self.stderr = stderr 17 self.pidfile = pidfile 18 19 def daemonize(self): 20 """ 21 do the UNIX double-fork magic, see Stevens' "Advanced 22 Programming in the UNIX Environment" for details (ISBN 0201563177) 23 http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16 24 """ 25 try: 26 pid = os.fork() 27 if pid > 0: 28 # exit first parent 29 sys.exit(0) 30 except OSError, e: 31 sys.stderr.write("fork #1 failed: %d (%s) " % (e.errno, e.strerror)) 32 sys.exit(1) 33 34 # decouple from parent environment 35 os.chdir("/") 36 os.setsid() 37 os.umask(0) 38 39 # do second fork 40 try: 41 pid = os.fork() 42 if pid > 0: 43 # exit from second parent 44 sys.exit(0) 45 except OSError, e: 46 sys.stderr.write("fork #2 failed: %d (%s) " % (e.errno, e.strerror)) 47 sys.exit(1) 48 49 # redirect standard file descriptors 50 sys.stdout.flush() 51 sys.stderr.flush() 52 si = file(self.stdin, 'r') 53 so = file(self.stdout, 'a+') 54 se = file(self.stderr, 'a+', 0) 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 59 # write pidfile 60 atexit.register(self.delpid) 61 pid = str(os.getpid()) 62 file(self.pidfile,'w+').write("%s " % pid) 63 64 def delpid(self): 65 os.remove(self.pidfile) 66 67 def start(self): 68 """ 69 Start the daemon 70 """ 71 # Check for a pidfile to see if the daemon already runs 72 try: 73 pf = file(self.pidfile,'r') 74 pid = int(pf.read().strip()) 75 pf.close() 76 except IOError: 77 pid = None 78 79 if pid: 80 message = "pidfile %s already exist. Daemon already running? " 81 sys.stderr.write(message % self.pidfile) 82 sys.exit(1) 83 84 # Start the daemon 85 self.daemonize() 86 self.run() 87 88 def stop(self): 89 """ 90 Stop the daemon 91 """ 92 # Get the pid from the pidfile 93 try: 94 pf = file(self.pidfile,'r') 95 pid = int(pf.read().strip()) 96 pf.close() 97 except IOError: 98 pid = None 99 100 if not pid: 101 message = "pidfile %s does not exist. Daemon not running? " 102 sys.stderr.write(message % self.pidfile) 103 return # not an error in a restart 104 105 # Try killing the daemon process 106 try: 107 while 1: 108 os.kill(pid, SIGTERM) 109 time.sleep(0.1) 110 except OSError, err: 111 err = str(err) 112 if err.find("No such process") > 0: 113 if os.path.exists(self.pidfile): 114 os.remove(self.pidfile) 115 else: 116 print str(err) 117 sys.exit(1) 118 119 def restart(self): 120 """ 121 Restart the daemon 122 """ 123 self.stop() 124 self.start() 125 126 def run(self): 127 """ 128 You should override this method when you subclass Daemon. It will be called after the process has been 129 daemonized by start() or restart(). 130 """
Here is a example how to use the class, need to rewrite the run function in parent calss:
1 #encoding=utf-8 2 3 import sys, time 4 from daemon import Daemon 5 import dbaction 6 import Task 7 import getdependency 8 from tslogging import GlobalLogging as Logging 9 10 class sys_sync_task_mgr(Daemon): 11 def __init__(self,temppath,starttime,frequency): 12 Daemon.__init__(self,temppath) 13 self.starttime = starttime 14 self.frequency = frequency 15 16 def run(self): 17 18 19 while True: 20 tasknolist= self.get_task_list() 21 22 if len(tasknolist['sys_task']) > 0: 23 if time.ctime()>self.starttime: 24 Logging.getLog().info('Available system task list:%s'%(str(tasknolist['sys_task']))) 25 try: 26 for taskno in tasknolist['sys_task']: 27 Logging.getLog().info('Start running system task:%s'%str(taskno)) 28 task = Task.sys_sync_task(taskno) 29 task.task_run() 30 except Exception, ex: 31 print 'hello' 32 Logging.getLog().error( "Exception in class: 'sys_sync_task_mgr' function:'run' :"+str(ex)) 33 else: 34 print 'hello' 35 Logging.getLog().warn('Time to run the tasks still not reach.') 36 time.sleep(self.frequency) 37 def get_task_list(self): 38 tasklist = getdependency.task_dependency([],3,1).get_executable_task() 39 return tasklist 40 41 #main function 42 if __name__ == "__main__": 43 daemon = sys_sync_task_mgr('/tmp/daemon_sys_sync_task_mgr.pid',time.ctime(),20) 44 if len(sys.argv) == 2: 45 if 'start' == sys.argv[1]: 46 daemon.start() 47 elif 'stop' == sys.argv[1]: 48 daemon.stop() 49 elif 'restart' == sys.argv[1]: 50 daemon.restart() 51 else: 52 print "Unknown command" 53 sys.exit(2) 54 sys.exit(0) 55 else: 56 print "usage: %s start|stop|restart" % sys.argv[0] 57 sys.exit(2)