A daemon process class in python

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)
原文地址:https://www.cnblogs.com/allenz/p/4756111.html