Creating a Daemon with Python

Learn how to 'daemonize' your Linux and UNIX system monitoring and management utilities.
(Page 1 of 2)

If you are an average internet user, then you interact with daemons every day. This article will describe what daemons do, how to create them in Python, and what you can use them for.

Daemon Defined

A daemon is a process on UNIX that runs in the background and will typically keep running until it is explicitly told to stop. Examples of daemon processes include web servers (lighttpd and Apache httpd), schedulers (cron and at), DNS servers (bind), mail servers (courier and dovecot), and database servers (MySQL and PostgreSQL).

The typical web user will probably interact with at least one UNIX daemon in the form of a web server, DNS server, or database server on an average day. These types of processes run in the background on a server somewhere, unattended by any person, working tirelessly to do the work that they were designed for.

You can background a process on UNIX by putting an ampersand (&) at the end of the command that you started it with. For example:

dink:~ jmjones$ $(sleep 10; echo echo "WAKING UP";) &
[1] 314
dink:~ jmjones$ WAKING UP

This backgrounded the sleep and echo commands. Ten seconds later, after sleep completed, the command echoed "WAKING UP" and appeared on my terminal. But just running a process in the background doesn't qualify it for daemon status. There are some deeper technical qualifications that an aspiring process has to meet in order to be branded with the daemon label.

Forking a Daemon Process

Following is the recipe "Forking a Daemon Process on Unix" from The Python Cookbook that will allow your Python code to daemonize itself.

import sys, os
def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
    # Perform first fork.
    try:
        pid = os.fork( )
        if pid > 0:
            sys.exit(0) # Exit first parent.
    except OSError, e:
        sys.stderr.write("fork #1 failed: (%d) %sn" % (e.errno, e.strerror))
        sys.exit(1)
    # Decouple from parent environment.
    os.chdir("/")
    os.umask(0)
    os.setsid( )
    # Perform second fork.
    try:
        pid = os.fork( )
        if pid > 0:
            sys.exit(0) # Exit second parent.
    except OSError, e:
        sys.stderr.write("fork #2 failed: (%d) %sn" % (e.errno, e.strerror))
        sys.exit(1)
    # The process is now daemonized, redirect standard file descriptors.
    for f in sys.stdout, sys.stderr: f.flush( )
    si = file(stdin, 'r')
    so = file(stdout, 'a+')
    se = file(stderr, 'a+', 0)
    os.dup2(si.fileno( ), sys.stdin.fileno( ))
    os.dup2(so.fileno( ), sys.stdout.fileno( ))
    os.dup2(se.fileno( ), sys.stderr.fileno( ))

One way that a daemon process differs from a normal backgrounded task is that a daemon process disassociates from its calling process and controlling terminal. This recipe outlines the standard procedure for creating a daemon process. This procedure includes forking once, calling setsid to become a session leader, then forking a second time.

Along the way, it is common to also change directory to / to ensure that the resulting working directory will always exist. It also ensures that the daemon process doesn't tie up the ability of the system to unmount the filesystem that it happens to be in. It is also typical to set its umask to 0 so that its file creation is set to the most permissive.

After becoming a daemon, this Python example also sets its standard input (stdin), standard output (stdout), and standard error (stderr) to the values the caller specified.


Page 1 of 2

 
1 2
Next Page





0 Comments (click to add your comment)
Comment and Contribute

 


(Maximum characters: 1200). You have characters left.