python-daemon

3.1.2 · active · verified Sun Apr 05

python-daemon is a Python library that implements the well-behaved Unix daemon process specification outlined in PEP 3143. It provides a `DaemonContext` class to manage the process environment for a program becoming a daemon, handling aspects like forking, changing directories, setting umask, and redirecting standard file descriptors. The current version is 3.1.2, and it is actively maintained with releases approximately every few months, though code changes are less frequent.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to use `DaemonContext` as a context manager to daemonize a simple Python script. It includes basic logging, optional PID file management using `lockfile.pidlockfile.TimeoutPIDLockFile`, and important configurations like `working_directory`, `umask`, and preserving open file descriptors for logging. Run this script and observe that it detaches from the terminal and continues to run, logging to `/tmp/my_daemon.log`.

import daemon
import time
import logging
import sys
import os

# Optional: for robust PID file management
try:
    from lockfile import pidlockfile
except ImportError:
    pidlockfile = None

LOG_FILE = '/tmp/my_daemon.log'
PID_FILE = '/tmp/my_daemon.pid'

def do_program_work():
    logging.basicConfig(
        filename=LOG_FILE,
        level=logging.INFO,
        format='%(asctime)s - %(levelname)s - %(message)s'
    )
    logger = logging.getLogger()
    logger.info("Daemon started.")

    # Example: Keep track of open log file descriptor
    # so daemon does not close it.
    log_handler_file = None
    for handler in logger.handlers:
        if hasattr(handler, 'stream') and hasattr(handler.stream, 'fileno'):
            log_handler_file = handler.stream.fileno()
            break

    while True:
        logger.info(f"Daemon still running at {time.ctime()}")
        time.sleep(5)


if __name__ == '__main__':
    # Prepare a PID file object if lockfile is installed
    pid_file = None
    if pidlockfile:
        pid_file = pidlockfile.TimeoutPIDLockFile(PID_FILE)

    # Open the daemon context
    # Explicitly keep stdout/stderr for debugging, typically redirect to /dev/null or log file
    with daemon.DaemonContext(
        working_directory='/',
        umask=0o002, # Set umask explicitly; 0o022 or 0o027 are common
        pidfile=pid_file,
        stdout=sys.stdout, # For demonstration, usually redirect to a log file or /dev/null
        stderr=sys.stderr, # For demonstration, usually redirect to a log file or /dev/null
        files_preserve=[log_handler_file] if log_handler_file else [] # Preserve log file descriptor
    ):
        do_program_work()

view raw JSON →