1 # -*- coding: utf-8 -*-
5 # Copyright 2007, 2009 Sander Marechal <s.marechal@jejik.com>
6 # Copyright 2010, 2011 Jack Kaliko <efrim@azylum.org>
8 # http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/
14 from signal import signal, SIGTERM
19 A generic daemon class.
21 Usage: subclass the Daemon class and override the run() method
23 def __init__(self, pidfile,
30 self.pidfile = pidfile
35 do the UNIX double-fork magic, see Stevens' "Advanced
36 Programming in the UNIX Environment" for details (ISBN 0201563177)
37 http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
45 sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
48 # Decouple from parent environment
51 self.umask = os.umask(0)
57 # exit from second parent
60 sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
64 # redirect standard file descriptors
67 si = file(self.stdin, 'r')
68 so = file(self.stdout, 'a+')
69 se = file(self.stderr, 'a+', 0)
70 os.dup2(si.fileno(), sys.stdin.fileno())
71 os.dup2(so.fileno(), sys.stdout.fileno())
72 os.dup2(se.fileno(), sys.stderr.fileno())
74 atexit.register(self.shutdown)
75 self.signal_management()
81 pid = str(os.getpid())
84 file(self.pidfile, 'w').write('%s\n' % pid)
85 #except IOError, wpid_err:
86 except Exception, wpid_err:
87 sys.stderr.write(u'Error trying to write pid file to %s: %s\n' %
88 (unicode(self.pidfile, 'utf-8'), wpid_err))
91 atexit.register(self.delpid)
93 def signal_management(self):
94 # Declare signal handlers
95 signal(SIGTERM, self.exit_handler)
97 def exit_handler(self, signum, frame):
101 os.unlink(self.pidfile)
107 # Check for a pidfile to see if the daemon already runs
109 pf = file(self.pidfile, 'r')
110 pid = int(pf.read().strip())
116 message = "pidfile %s already exist. Daemon already running?\n"
117 sys.stderr.write(message % self.pidfile)
124 def foreground(self):
126 Foreground/debug mode
129 atexit.register(self.shutdown)
136 # Get the pid from the pidfile
138 pf = file(self.pidfile, 'r')
139 pid = int(pf.read().strip())
145 message = "pidfile %s does not exist. Daemon not running?\n"
146 sys.stderr.write(message % self.pidfile)
147 return # not an error in a restart
149 # Try killing the daemon process
151 os.kill(pid, SIGTERM)
155 if err.find("No such process") > 0:
156 if os.path.exists(self.pidfile):
157 message = "Daemon not running? removing pid file %s.\n"
158 sys.stderr.write(message % self.pidfile)
159 os.remove(self.pidfile)
173 You should override this method when you subclass Daemon. It will be
174 called when the process is being stopped.
176 Daemon() uses atexit to call Daemon().shutdown(), as a consequence
177 shutdown and any other functions registered via this module are not
178 called when the program is killed by an un-handled/unknown signal.
179 This is the reason of Daemon().signal_management() existence.
184 You should override this method when you subclass Daemon. It will be
185 called after the process has been daemonized by start() or restart().
193 if __name__ == '__main__':
197 # vim: ai ts=4 sw=4 sts=4 expandtab