EDIT: I gave a talk about this subject at my local python meetup and wrote a bit more in-depth code which I put on Github. You will more information there.
The title says it all. I had to do a project which required creating a daemon and use python 2.7 and had quite the time trying to get it work since there are not very many examples out there. I thought that I would share some of the knowledge that I gained over this little venture in the hopes that someone else will not have to go through the pain.
##Step 1: Do the pip
To get all the required materials simply run:
$ pip install python-daemon
##Step 2: Start the fun stuff
# -*- coding: utf-8 -*- """Example of how to run a daemon.""" import time from daemon import runner class DaemonApp(object): """Daemon App.""" def __init__(self): """Initialize Daemon.""" self.stdin_path = '/dev/null' self.stdout_path = '/dev/null' self.stderr_path = '/dev/null' self.pidfile_path = '/tmp/daemon.pid' self.pidfile_timeout = 1 def run(self): """Main Daemon Code.""" while True: time.sleep(1) if __name__ == '__main__': app = DaemonApp() daemon_runner = runner.DaemonRunner(app) daemon_runner.do_action()
This is the easiest example I can show. To run this example save it to a file, I call mine main.py, and then run:
$ python main.py start
To check if your process is running you can check two things. First try to read the pid file:
$ cat /tmp/daemon.pid 3527
You won’t necessarily have the same process id but you should get a number. Now the pid file is more of just a check to see that your daemon started. If your daemon logic hits an exception after it starts it will die and the pid file will not always be removed. Only if the “happy path” of execution occurs will the pid file truly reflect the current state of the daemon. The other way to check if the process is currently running is to use:
$ ps aux | grep main.py root 3991 0.0 0.0 2434840 792 s011 S+ 9:43PM 0:00.00 grep main.py root 3527 0.0 0.0 2487108 1896 ?? S 9:43PM 0:00.00 python main.py start
Here we can see that the daemon pid file matches the pid id from the ps aux command. Some other points to note are in general you probably won’t want to have stdout_path and stderr_path point to /dev/null because that means you can’t see any errors that will cause your daemon to die. I usually point these to files and then I will use ‘tail -f /path/to/file’ to watch for statuses. You could instead make the daemon app look like this instead.
class DaemonApp(object): """Daemon App.""" def __init__(self): """Initialize Daemon.""" self.stdin_path = '/dev/null' self.stdout_path = '/tmp/stdout.txt' self.stderr_path = '/tmp/stderr.txt' self.pidfile_path = '/tmp/daemon.pid' self.pidfile_timeout = 1
Now in the PEP 3143 documentation you will read about DaemonContext objects. The objects basically represent settings that are applied to your daemon class, things like ‘uid’ and ‘guid’. Following safety best practices you might want to have your daemon run as a lower level user instead of root, which we saw in our ‘ps aux’ example.
# New imports import grp import pwd import time ... if __name__ == '__main__': app = DaemonApp() daemon_runner = runner.DaemonRunner(app) daemon_gid = grp.getgrnam('hiarc').gr_gid daemon_uid = pwd.getpwnam('hiarc').pw_uid daemon_runner.daemon_context.gid = daemon_gid daemon_runner.daemon_context.uid = daemon_uid daemon_runner.do_action()
and now running ps aux:
$ ps aux | grep main.py root 42784 0.0 0.0 2434840 712 s011 R+ 9:59PM 0:00.00 grep main.py hiarc 42597 0.0 0.0 2461524 1924 ?? S 9:59PM 0:00.00 python main.py start
WOOO! After you get it running with these lowered permissions you have all the main ingredients to start your daemon project. Good luck!