Welcome, guest | Sign In | My Account | Store | Cart

Boilerplate code for a Python Unix daemon.

Python, 11 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import sys 
import os  
if os.fork()==0:
    os.setsid()
    sys.stdout=open("/dev/null", 'w')
    sys.stdin=open("/dev/null", 'r')
    while(1):
        # Daemon's main code goes here                 
        pass

sys.exit(0)

9 comments

Wm Annis 22 years, 4 months ago  # | flag

Typo in the code: The parens are missing on the os.setsid() call.

Michael Kent 21 years, 9 months ago  # | flag

Attack of the zombie processes... My understanding of *NIX daemon processes is that, to avoid creating a 'zombie' process, you must use the standard 'double-fork' technique -- you must fork an intermidiate child process, that then forks the desired child process. Comments?

Tobias Klausmann 21 years, 8 months ago  # | flag

no Zombie army... I just used:

#!/usr/bin/python
import sys
import os,time

if os.fork()==0:
    os.setsid()
    sys.stdout=open("/dev/null", 'w')
    sys.stdin=open("/dev/null", 'r')
    time.sleep(20)

sys.exit(0)

And it resulted in no Zombie. Therefore, I guess, things work out right. It might be another issue if you do Shell Magick when starting the program, so the double fork could be added, just to be safe:

#!/usr/bin/python

import sys
import os,time
if os.fork()==0:
    os.setsid()
    sys.stdout=open("/dev/null", 'w')
    sys.stdin=open("/dev/null", 'r')
    if os.fork()==0:
        time.sleep(20) # or whatever your daemon does

sys.exit(0)
Andy Gimblett 21 years, 7 months ago  # | flag

More complete implementation of forking a daemon. A more definitive/complete answer to the question "How do I get my program to act like a daemon?" is given by the following Unix Programming FAQ entry:

http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16

...which is fairly completely implemented by the following python cookbook entry (and its comments):

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012

Noah Spurrier 21 years, 6 months ago  # | flag

You need to double fork... A daemon is different than a background process. A background process is attached to a process group of a controlling terminal (your login shell). If your controlling terminal dies then you background jobs also die. I strongly suspect that your original code will die when you exit your login shell.

The reason you need to double fork is to disconnect your new process group from the parent process controlling terminal. Failing to do this does not cause a zombie. Instead, failing to do this causes the child process to be sent copies of the signals sent to the parent. That means when the parent login shell dies (HUP signal) or gets killed (KILL signal) those signals will be broadcast to the children.

The following code demonstrates a daemon in Python. When you start this up and a file ('/tmp/daemon.log') will slowly get filled with integers (once per second). You can logout, kill your shell, or whatever and the daemon will still run. It will not appear in the process list unless you do 'ps -x' to list processes without controlling terminals.

Note that you have to have correct permissions to do this. Some systems will not allow you to create a daemon. Some UNIXes have other mechanisms to do this. I'm pretty sure that this is portable.

I'm no authority. This is from memory. I may be wrong,

Yours,

Noah

#!/usr/bin/env python
'''Daemon example'''

import os, sys, time

def main ():
    '''This is the main function run by the daemon.
    '''
    fout = open ('/tmp/daemon.log', 'a')
    fout.write ('daemon started with pid %d\n' % os.getpid())
    c = 0
    while 1:
        fout.write ('Count: %d\n' % c)
        fout.flush()
        c = c + 1
        time.sleep(1)

if __name__ == '__main__':
    pid = os.fork ()
    if pid == 0: # if pid is child...
        os.setsid() # Create new session and sets process group.
        pid = os.fork () # Will have INIT (pid 1) as parent process...
        if pid == 0: # if pid is child...
            main ()
Keith Dart 21 years, 5 months ago  # | flag

setpgrp vs. double fork. I believe that calling setpgrp() in your forked daemon obviates the need for a second fork. That is what I have always done and it seems to work fine.

Michael Babcock 21 years, 4 months ago  # | flag

Consider doing these only optionally. I hate it personally when programs insist on behaving like this normally; I use supervise to monitor all my daemon processes and it works wonderfully; no extra code in the daemons at all and good notification (and auto-restarting) of daemon death.

Richard Moore 16 years, 8 months ago  # | flag

Simplified backgrounding... Could you not simply use the following to background the current process?

if not (os.fork() == 0 and os.fork() == 0): sys.exit(0)

Thanks,

RicMoo

ben w 15 years, 7 months ago  # | flag

Here's the same code in a slightly different form:

def become_daemon():
    pid = os.fork ()
    if pid != 0: # if pid is not child...
        sys.exit(0)

    os.setsid() # Create new session and sets process group.
    pid = os.fork () # Will have INIT (pid 1) as parent process...
    if pid != 0: # if pid is not child...
        sys.exit(0)

Then, at the beginning of my script I can do:

become_daemon()

# do whatever
Created by Alexey Vyskubov on Thu, 8 Mar 2001 (PSF)
Python recipes (4591)
Alexey Vyskubov's recipes (1)

Required Modules

Other Information and Tasks