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
34 do the UNIX double-fork magic, see Stevens' "Advanced
35 Programming in the UNIX Environment" for details (ISBN 0201563177)
36 http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
44 sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
47 # Decouple from parent environment
56 # exit from second parent
59 sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
63 # redirect standard file descriptors
66 si = file(self.stdin, 'r')
67 so = file(self.stdout, 'a+')
68 se = file(self.stderr, 'a+', 0)
69 os.dup2(si.fileno(), sys.stdin.fileno())
70 os.dup2(so.fileno(), sys.stdout.fileno())
71 os.dup2(se.fileno(), sys.stderr.fileno())
73 atexit.register(self.shutdown)
74 self.signal_management()
80 pid = str(os.getpid())
82 file(self.pidfile, 'w').write('%s\n' % pid)
83 #except IOError, wpid_err:
84 except Exception, wpid_err:
85 sys.stderr.write(u'Error trying to write pid file to %s: %s\n' %
86 (unicode(self.pidfile, 'utf-8'), wpid_err))
88 atexit.register(self.delpid)
90 def signal_management(self):
91 # Declare signal handlers
92 signal(SIGTERM, self.exit_handler)
94 def exit_handler(self, signum, frame):
98 os.remove(self.pidfile)
104 # Check for a pidfile to see if the daemon already runs
106 pf = file(self.pidfile, 'r')
107 pid = int(pf.read().strip())
113 message = "pidfile %s already exist. Daemon already running?\n"
114 sys.stderr.write(message % self.pidfile)
121 def foreground(self):
123 Foreground/debug mode
126 atexit.register(self.shutdown)
133 # Get the pid from the pidfile
135 pf = file(self.pidfile, 'r')
136 pid = int(pf.read().strip())
142 message = "pidfile %s does not exist. Daemon not running?\n"
143 sys.stderr.write(message % self.pidfile)
144 return # not an error in a restart
146 # Try killing the daemon process
148 os.kill(pid, SIGTERM)
152 if err.find("No such process") > 0:
153 if os.path.exists(self.pidfile):
154 message = "Daemon not running? removing pid file %s.\n"
155 sys.stderr.write(message % self.pidfile)
156 os.remove(self.pidfile)
170 You should override this method when you subclass Daemon. It will be
171 called when the process is being stopped.
173 Daemon() uses atexit to call Daemon().shutdown(), as a consequence
174 shutdown and any other functions registered via this module are not
175 called when the program is killed by an un-handled/unknown signal.
176 This is the reason of Daemon().signal_management() existence.
181 You should override this method when you subclass Daemon. It will be
182 called after the process has been daemonized by start() or restart().
190 if __name__ == '__main__':
194 # vim: ai ts=4 sw=4 sts=4 expandtab