License: Creative Commons
This is a Python class that will daemonize your Python code so it can continue running in the background. It works on Unix and Linux systems. It creates a PID file that is controlled by system file locks so the need to remove a stale pid file is not necessary.
The Daemon class will write to a log file if you set one up. Any code that uses the Daemon class can also write to the same log file making it easy to have a combined log.
The Daemon class has standard start, stop, restart commands plus a foreground mode. This current version no longer supports Python 2. This code may still support OSX but since I don't have a machine that runs OSX I cannot test it.
This code is based on the original version from jejik.com.
Define a class which inherits from Daemon and has a run() method which is what will be called once the daemonization is completed.
from daemonize import Daemon
class MyDaemon(Daemon):
def run(self, *args, **kwards):
# Do stuff
def stop_callback(self):
# Do anything you need to do before a signal shuts
# down your daemon.
A while loop set to True will usually work fine in the run() method or you could use something more sophisticated as mentioned below in the last paragraph under Continuous Execution.
There is also a stop_callback method that can be overridden in your sub-class to the Daemon class. It gives your daemon the ability to perform certain tasks before a shutdown is performed, like closing files etc.
Create a new object of your class, specifying where you want your PID file to exist:
md = MyDaemon('/path/to/pid.pid')
md.start()
There are a lot of arguments that can be used in the constructor of the Daemon class.
- pidfile: Mandatory fullpath including file name of the pid file.
- stdin: The input data stream, defaults to os.devnull.
- stdout: The output data stream, defaults to os.devnull.
- stderr: The error data stream, defaults to os.devnull.
- base_dir: The absolute or relative path to the directory that will be used after the process is detached from the terminal, defaults to '.' (current working directory).
- umask: The mask used for any files created by the daemon, defaults to 0o22.
- verbose: The default logging level. The values 1 = INFO, 2 = DEBUG, 3 = ERROR, and any number (other than 1, 2, 3) = WARNING, defaults to 1.
- use_gevent: Use gevent to handle the killing of the daemon, defaults to False.
- logger_name: The logger name used for logging, defaults to '' (the root logger).
- start() -- Starts the daemon (creates PID and daemonizes).
- stop() -- Stops the daemon (stops the child process and removes the PID).
- restart() -- Does a stop() and then start().
To start, restart, and stop the test daemon that is at the end of the daemonize/daemon.py code see below. Just substitute your code for the code below.
$ ps -ajx | grep daemonize/daemon | grep -v grep # No daemon running
$ python daemonize/daemon.py start
$ ps -ajx | grep daemonize/daemon | grep -v grep
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1 425677 425676 425676 ? -1 S 1000 0:00 python daemonize/daemon.py start
$ python daemonize/daemon.py restart
$ ps -ajx | grep daemonize/daemon | grep -v grep
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1 425823 425822 425822 ? -1 S 1000 0:00 python daemonize/daemon.py restart
$ python daemonize/daemon.py stop
$ ps -ajx | grep daemonize/daemon | grep -v grep # No daemon running
This is useful for debugging because you can start the code without making it a daemon. The running script then depends on the open shell like any normal Python script.
To do this, just call the run() method directly.
md = MyDaemon('/path/to/pid.pid')
md.run()
The run() method will be executed just once so if you want the daemon to be doing stuff continuously you may wish to use the [1] sched module to execute code repeatedly [2] example or just use a while True.
Footnotes
[1] | http://docs.python.org/library/sched.html |
[2] | https://github.com/serverdensity/sd-agent/blob/master/agent.py#L339 |