Python: Tips For Writing Daemons
Here’s some useful information for writing daemons in Python.
One common problem that people run into is os.fork() producing zombie processes when children quit. This can easily be overcome by setting the SIGCHLD signal to SIG_IGN. ie:
import signal signal.signal(signal.SIGCHLD, signal.SIG_IGN)
On some flavors of Unix, you are forced to do a double-fork on startup, in order to go into daemon mode. This is because single forking isn’t guaranteed to detach from the controlling terminal. The solution is this:
import os, sys, time
# Main loop
def main():
# Drop privs.
os.setgid(1000) # Replace with desired GID
os.setuid(1000) # Replace with desired UID
time.sleep(10)
sys.exit(0)
if (not os.fork()):
os.setsid() # Become session leader
pid = os.fork()
if (pid):
# Parent, write PID file
fp = open('/var/run/my-daemon.pid', 'w')
fp.write(str(pid))
fp.flush()
# Forcibly sync disk
os.fsync(fp.fileno())
fp.close()
os._exit(0)
else:
# Child, call main
main()
else:
# Parent
os._exit(0)

May 4th, 2008 at 4:00 am
Most UNIX daemons will also want to set an umask, chdir to some sensible directory and re-open stdin, stdout and stderr
May 4th, 2008 at 11:42 am
Very true. os.dup2() is your friend.
May 5th, 2008 at 5:21 am
There are a few other steps in turning a process into a well behaved daemon. Here are the steps I go through:
1. Fork # Make new process 1
1.parent. Exit
1.child. Decouple from parent
os.chdir(”/”) # So we don’t tie up a file system
os.setsid() # Become a session/group leader
os.umask(0) # Could be other things here as well — allow core’s and what not.
1.child. Fork # Make new process 2
2.parent. Exit
2.child Close all open file descriptors in a pinch, these are 0-1023
2.child Open stdin, stdout and stderr to /dev/null use os.dup2() for this if you want.
2.child Congrats, you’re now a daemon.
May 5th, 2008 at 8:01 am
[…] 5th, 2008 in Links A few good tips on writing daemons in Python, including a Python example of the double-fork console detachment […]
June 5th, 2008 at 3:31 am
tips…
Good websites are few and far between; yours is a pleasure to visit; bookmarking for future visits and I enthusiastically recommend the same!…
September 25th, 2008 at 10:41 pm
Other problems not dealt with:
* Dropping setuid and setgid privileges
* PID file handling: don’t start if the PID file already exists, otherwise write the PID line to the specified file, remove the PID file when program terminates
* Signal handling: make sure cleanup is done in response to appropriate signals
Optional extras usually present in well-behaved daemons:
* Redirect stdout and stderr to syslog
* Drop root privileges and switch to a specified user and group id
* Operate within a chroot jail
* Respawn on termination
* Cooperate with operation under initd or inetd
I’m rather disappointed that these widely-standardised daemon behaviours aren’t present in the Python standard library.