1 # -*- coding: utf-8 -*-
5 # Copyright 2007, 2009 Sander Marechal <s.marechal@jejik.com>
6 # Copyright 2010, 2011, 2012 Jack Kaliko <kaliko@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
25 def __init__(self, pidfile,
32 self.pidfile = pidfile
37 Do the UNIX double-fork magic.
38 see W. Richard Stevens, "Advanced Programming in the Unix Environment"
39 for details (ISBN 0201563177)
42 Unix processes belong to "process group" which in turn lies within a "session".
43 A session can have a controlling tty.
44 Forking twice allows to detach the session from a possible tty.
45 The process lives then within the init process.
53 sys.stderr.write('fork #1 failed: %d (%s)\n' % (e.errno, e.strerror))
56 # Decouple from parent environment
59 self.umask = os.umask(0)
65 # exit from second parent
68 sys.stderr.write('fork #2 failed: %d (%s)\n' % (e.errno, e.strerror))
72 # redirect standard file descriptors
75 si = file(self.stdin, 'r')
76 so = file(self.stdout, 'a+')
77 se = file(self.stderr, 'a+', 0)
78 os.dup2(si.fileno(), sys.stdin.fileno())
79 os.dup2(so.fileno(), sys.stdout.fileno())
80 os.dup2(se.fileno(), sys.stderr.fileno())
82 atexit.register(self.shutdown)
83 self.signal_management()
89 pid = str(os.getpid())
92 file(self.pidfile, 'w').write('%s\n' % pid)
93 except Exception, wpid_err:
94 sys.stderr.write(u'Error trying to write pid file: %s\n' % wpid_err)
97 atexit.register(self.delpid)
99 def signal_management(self):
100 # Declare signal handlers
101 signal(SIGTERM, self.exit_handler)
103 def exit_handler(self, signum, frame):
108 os.unlink(self.pidfile)
109 except OSError as err:
110 message = 'Error trying to remove PID file: %s\n'
111 sys.stderr.write(message % err)
117 # Check for a pidfile to see if the daemon already runs
119 pf = file(self.pidfile, 'r')
120 pid = int(pf.read().strip())
126 message = 'pidfile %s already exist. Daemon already running?\n'
127 sys.stderr.write(message % self.pidfile)
134 def foreground(self):
136 Foreground/debug mode
139 atexit.register(self.shutdown)
146 # Get the pid from the pidfile
148 pf = file(self.pidfile, 'r')
149 pid = int(pf.read().strip())
155 message = 'pidfile %s does not exist. Is the Daemon running?\n'
156 sys.stderr.write(message % self.pidfile)
157 return # not an error in a restart
159 # Try killing the daemon process
161 os.kill(pid, SIGTERM)
165 if os.path.exists(self.pidfile):
166 message = "Daemon's not running? removing pid file %s.\n"
167 sys.stderr.write(message % self.pidfile)
168 os.remove(self.pidfile)
170 sys.stderr.write(err.strerror)
182 You should override this method when you subclass Daemon. It will be
183 called when the process is being stopped.
185 Daemon() uses atexit to call Daemon().shutdown(), as a consequence
186 shutdown and any other functions registered via this module are not
187 called when the program is killed by an un-handled/unknown signal.
188 This is the reason of Daemon().signal_management() existence.
193 You should override this method when you subclass Daemon. It will be
194 called after the process has been daemonized by start() or restart().
198 # vim: ai ts=4 sw=4 sts=4 expandtab