1 # -*- coding: utf-8 -*-
2 # Copyright 2007, 2009 Sander Marechal <s.marechal@jejik.com>
3 # Copyright 2010, 2011, 2012 Jack Kaliko <kaliko@azylum.org>
5 # http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/
7 # python-seth is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Lesser General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # python-seth is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public License
18 # along with python-seth. If not, see <http://www.gnu.org/licenses/>.
25 from signal import signal, SIGTERM
30 A generic daemon class.
32 Usage: subclass the Daemon class and override the run() method
34 Daemon([pidfile[, stdin[, stdout[, stderr]]]])
36 pidfile : file to write pid to (default no pid file writen)
37 stdin : standard input file descriptor (default to /dev/null)
38 stdout : standard output file descriptor (default to /dev/null)
39 stderr : standard error file descriptorr (default to /dev/null)
43 def __init__(self, pidfile,
50 self.pidfile = pidfile
55 Do the UNIX double-fork magic.
56 see W. Richard Stevens, "Advanced Programming in the Unix Environment"
57 for details (ISBN 0201563177)
60 Unix processes belong to "process group" which in turn lies within a "session".
61 A session can have a controlling tty.
62 Forking twice allows to detach the session from a possible tty.
63 The process lives then within the init process.
71 sys.stderr.write('fork #1 failed: {0.errno:d} ({0.strerror})\n'.format(e))
74 # Decouple from parent environment
77 self.umask = os.umask(0)
83 # exit from second parent
86 sys.stderr.write('fork #2 failed: {0.errno:d} ({0.strerror})\n'.format(e))
90 # redirect standard file descriptors
93 # TODO: binary or txt mode?
94 si = open(self.stdin, mode='rb')
95 so = open(self.stdout, mode='ab+')
96 se = open(self.stderr, mode='ab+', buffering=0)
97 os.dup2(si.fileno(), sys.stdin.fileno())
98 os.dup2(so.fileno(), sys.stdout.fileno())
99 os.dup2(se.fileno(), sys.stderr.fileno())
101 atexit.register(self.shutdown)
102 self.signal_management()
108 pid = str(os.getpid())
111 open(self.pidfile, 'w').write('%s\n' % pid)
112 except Exception as wpid_err:
113 sys.stderr.write('Error trying to write pid file: {}\n'.format(wpid_err))
116 atexit.register(self.delpid)
118 def signal_management(self):
119 """Declare signal handlers
121 signal(SIGTERM, self.exit_handler)
123 def exit_handler(self, signum, frame):
127 """Remove PID file"""
129 os.unlink(self.pidfile)
130 except OSError as err:
131 message = 'Error trying to remove PID file: {}\n'
132 sys.stderr.write(message.format(err))
138 # Check for a pidfile to see if the daemon already runs
140 pf = open(self.pidfile, 'r')
141 pid = int(pf.read().strip())
147 message = 'pidfile {0.pidfile} already exist. Daemon already running?\n'
148 sys.stderr.write(message.format(self))
155 def foreground(self):
157 Foreground/debug mode
160 atexit.register(self.shutdown)
167 # Get the pid from the pidfile
169 pf = open(self.pidfile, 'r')
170 pid = int(pf.read().strip())
176 message = 'pidfile {0.pidfile} does not exist. Is the Daemon running?\n'
177 sys.stderr.write(message.format(self))
178 return # not an error in a restart
180 # Try killing the daemon process
182 os.kill(pid, SIGTERM)
184 except OSError as err:
186 if os.path.exists(self.pidfile):
187 message = "Daemon's not running? removing pid file {0.pidfile}.\n"
188 sys.stderr.write(message.format(self))
189 os.remove(self.pidfile)
191 sys.stderr.write(err.strerror)
203 You should override this method when you subclass Daemon. It will be
204 called when the process is being stopped.
206 Daemon() uses atexit to call Daemon().shutdown(), as a consequence
207 shutdown and any other functions registered via this module are not
208 called when the program is killed by an un-handled/unknown signal.
209 This is the reason of Daemon().signal_management() existence.
214 You should override this method when you subclass Daemon. It will be
215 called after the process has been daemonized by start() or restart().
219 # vim: ai ts=4 sw=4 sts=4 expandtab