Package linspector :: Package lib :: Package core :: Module daemon
[hide private]
[frames] | no frames]

Source Code for Module linspector.lib.core.daemon

  1  import sys 
  2  import os 
  3  import time 
  4  import atexit 
  5  from signal import SIGTERM 
  6   
  7   
8 -class Daemon:
9 """ 10 A generic daemon class. 11 12 Usage: subclass the Daemon class and override the run() method 13 """ 14
15 - def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
16 self.stdin = stdin 17 self.stdout = stdout 18 self.stderr = stderr 19 self.pidfile = pidfile
20
21 - def daemonize(self):
22 """ 23 do the UNIX double-fork magic, see Stevens' "Advanced 24 Programming in the UNIX Environment" for details (ISBN 0201563177) 25 http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16 26 """ 27 try: 28 pid = os.fork() 29 if pid > 0: 30 # exit first parent 31 sys.exit(0) 32 except OSError, e: 33 sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) 34 sys.exit(1) 35 36 # decouple from parent environment 37 os.chdir("/") 38 os.setsid() 39 os.umask(0) 40 41 # do second fork 42 try: 43 pid = os.fork() 44 if pid > 0: 45 # exit from second parent 46 sys.exit(0) 47 except OSError, e: 48 sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) 49 sys.exit(1) 50 51 # redirect standard file descriptors 52 sys.stdout.flush() 53 sys.stderr.flush() 54 si = file(self.stdin, 'r') 55 so = file(self.stdout, 'a+') 56 se = file(self.stderr, 'a+', 0) 57 os.dup2(si.fileno(), sys.stdin.fileno()) 58 os.dup2(so.fileno(), sys.stdout.fileno()) 59 os.dup2(se.fileno(), sys.stderr.fileno()) 60 61 # write pidfile 62 atexit.register(self.delpid) 63 pid = str(os.getpid()) 64 file(self.pidfile, 'w+').write("%s\n" % pid)
65
66 - def delpid(self):
67 os.remove(self.pidfile)
68
69 - def start(self):
70 """ 71 Start the daemon 72 """ 73 # Check for a pidfile to see if the daemon already runs 74 try: 75 pf = file(self.pidfile, 'r') 76 pid = int(pf.read().strip()) 77 pf.close() 78 except IOError: 79 pid = None 80 81 if pid: 82 message = "pidfile %s already exist. daemon already running?\n" 83 sys.stderr.write(message % self.pidfile) 84 sys.exit(1) 85 86 # Start the daemon 87 self.daemonize() 88 self.run()
89
90 - def stop(self):
91 """ 92 Stop the daemon 93 """ 94 # Get the pid from the pidfile 95 try: 96 pf = file(self.pidfile, 'r') 97 pid = int(pf.read().strip()) 98 pf.close() 99 except IOError: 100 pid = None 101 102 if not pid: 103 message = "pidfile %s does not exist. daemon not running?\n" 104 sys.stderr.write(message % self.pidfile) 105 return # not an error in a restart 106 107 # Try killing the daemon process 108 try: 109 while 1: 110 os.kill(pid, SIGTERM) 111 time.sleep(0.1) 112 except OSError, err: 113 err = str(err) 114 if err.find("No such process") > 0: 115 if os.path.exists(self.pidfile): 116 os.remove(self.pidfile) 117 else: 118 print str(err) 119 sys.exit(1)
120
121 - def restart(self):
122 """ 123 Restart the daemon 124 """ 125 self.stop() 126 self.start()
127
128 - def run(self):
129 """ 130 You should override this method when you subclass Daemon. 131 It will be called after the process has been 132 daemonized by start() or restart(). 133 """
134