I l@ve RuBoard Previous Section Next Section

6.8 Forking a Daemon Process on Unix

Credit: Jürgen Hermann

6.8.1 Problem

You need to fork a daemon process on a Unix or Unix-like system, and this, in turn, requires a certain precise sequence of system calls.

6.8.2 Solution

Daemon processes must detach from their controlling terminal and process group. This is not hard, but it does take some care:

import sys, os

def main(  ):
    """ An example daemon main routine; writes a datestamp to file
        /tmp/daemon-log every 10 seconds.
    """
    import time

    f = open("/tmp/daemon-log", "w")
    while 1:
        f.write('%s\n' % time.ctime(time.time(  )))
        f.flush(  )
        time.sleep(10)

if _ _name_ _ == "_ _main_ _":
    # Do the Unix double-fork magic; see Stevens's book "Advanced
    # Programming in the UNIX Environment" (Addison-Wesley) for details
    try:
        pid = os.fork(  )
        if pid > 0:
            # Exit first parent
            sys.exit(0)
    except OSError, e:
        print >>sys.stderr, "fork #1 failed: %d (%s)" % (
            e.errno, e.strerror)
        sys.exit(1)

    # Decouple from parent environment
    os.chdir("/")
    os.setsid(  )
    os.umask(0)

    # Do second fork
    try:
        pid = os.fork(  )
        if pid > 0:
            # Exit from second parent; print eventual PID before exiting
            print "Daemon PID %d" % pid
            sys.exit(0)
    except OSError, e:
        print >>sys.stderr, "fork #2 failed: %d (%s)" % (
            e.errno, e.strerror)
        sys.exit(1)

    # Start the daemon main loop
    main(  )

6.8.3 Discussion

Forking a daemon on Unix requires a certain specific sequence of system calls, which is explained in W. Richard Steven's seminal book, Advanced Programming in the Unix Environment (Addison-Wesley). We need to fork twice, terminating each parent process and letting only the grandchild of the original process run the daemon's code. This allows us to decouple the daemon process from the calling terminal, so that the daemon process can keep running (typically as a server process without further user interaction, like a web server, for example) even after the calling terminal is closed. The only visible effect of this is that when you run this script as a main script, you get your shell prompt back immediately.

For all of the details about how and why this works in Unix and Unix-like systems, see Stevens's book. Stevens gives his examples in the C programming language, but since Python's standard library exposes a full POSIX interface, this can also be done in Python. Typical C code for a daemon fork translates almost literally to Python; the only difference you have to care about�a minor detail�is that Python's os.fork does not return -1 on errors but throws an OSError exception. Therefore, rather than testing for a less-than-zero return code from fork, as we would in C, we run the fork in the try clause of a try/except statement, so that we can catch the exception, should it happen, and print appropriate diagnostics to standard error.

6.8.4 See Also

Documentation of the standard library module os in the Library Reference; Unix manpages for the fork, umask, and setsid system calls; Advanced Programming in the Unix Environment, by W. Richard Stevens (Addison-Wesley, 1992).

    I l@ve RuBoard Previous Section Next Section