Movatterモバイル変換


[0]ホーム

URL:


Following system colour schemeSelected dark colour schemeSelected light colour scheme

Python Enhancement Proposals

PEP 3143 – Standard daemon process library

Author:
Ben Finney <ben+python at benfinney.id.au>
Status:
Deferred
Type:
Standards Track
Created:
26-Jan-2009
Python-Version:
3.x
Post-History:


Table of Contents

Abstract

Writing a program to become a well-behaved Unix daemon is somewhatcomplex and tricky to get right, yet the steps are largely similar forany daemon regardless of what else the program may need to do.

This PEP introduces a package to the Python standard library thatprovides a simple interface to the task of becoming a daemon process.

PEP Deferral

Further exploration of the concepts covered in this PEP has been deferredfor lack of a current champion interested in promoting the goals of the PEPand collecting and incorporating feedback, and with sufficient availabletime to do so effectively.

Specification

Example usage

Simple example of directDaemonContext usage:

importdaemonfromspamimportdo_main_programwithdaemon.DaemonContext():do_main_program()

More complex example usage:

importosimportgrpimportsignalimportdaemonimportlockfilefromspamimport(initial_program_setup,do_main_program,program_cleanup,reload_program_config,)context=daemon.DaemonContext(working_directory='/var/lib/foo',umask=0o002,pidfile=lockfile.FileLock('/var/run/spam.pid'),)context.signal_map={signal.SIGTERM:program_cleanup,signal.SIGHUP:'terminate',signal.SIGUSR1:reload_program_config,}mail_gid=grp.getgrnam('mail').gr_gidcontext.gid=mail_gidimportant_file=open('spam.data','w')interesting_file=open('eggs.data','w')context.files_preserve=[important_file,interesting_file]initial_program_setup()withcontext:do_main_program()

Interface

A new package,daemon, is added to the standard library.

A class,DaemonContext, is defined to represent the settings andprocess context for the program running as a daemon process.

DaemonContext objects

ADaemonContext instance represents the behaviour settings andprocess context for the program when it becomes a daemon. Thebehaviour and environment is customised by setting options on theinstance, before calling theopen method.

Each option can be passed as a keyword argument to theDaemonContextconstructor, or subsequently altered by assigning to an attribute onthe instance at any time prior to callingopen. That is, foroptions namedwibble andwubble, the following invocation:

foo=daemon.DaemonContext(wibble=bar,wubble=baz)foo.open()

is equivalent to:

foo=daemon.DaemonContext()foo.wibble=barfoo.wubble=bazfoo.open()

The following options are defined.

files_preserve
Default:
None

List of files that shouldnot be closed when starting thedaemon. IfNone, all open file descriptors will be closed.

Elements of the list are file descriptors (as returned by a fileobject’sfileno() method) or Pythonfile objects. Eachspecifies a file that is not to be closed during daemon start.

chroot_directory
Default:
None

Full path to a directory to set as the effective root directory ofthe process. IfNone, specifies that the root directory is notto be changed.

working_directory
Default:
'/'

Full path of the working directory to which the process shouldchange on daemon start.

Since a filesystem cannot be unmounted if a process has itscurrent working directory on that filesystem, this should eitherbe left at default or set to a directory that is a sensible “homedirectory” for the daemon while it is running.

umask
Default:
0

File access creation mask (“umask”) to set for the process ondaemon start.

Since a process inherits its umask from its parent process,starting the daemon will reset the umask to this value so thatfiles are created by the daemon with access modes as it expects.

pidfile
Default:
None

Context manager for a PID lock file. When the daemon context opensand closes, it enters and exits thepidfile context manager.

detach_process
Default:
None

IfTrue, detach the process context when opening the daemoncontext; ifFalse, do not detach.

If unspecified (None) during initialisation of the instance,this will be set toTrue by default, andFalse only ifdetaching the process is determined to be redundant; for example,in the case when the process was started byinit, byinitd, orbyinetd.

signal_map
Default:
system-dependent

Mapping from operating system signals to callback actions.

The mapping is used when the daemon context opens, and determinesthe action for each signal’s signal handler:

  • A value ofNone will ignore the signal (by setting thesignal action tosignal.SIG_IGN).
  • A string value will be used as the name of an attribute on theDaemonContext instance. The attribute’s value will be usedas the action for the signal handler.
  • Any other value will be used as the action for the signalhandler.

The default value depends on which signals are defined on therunning system. Each item from the list below whose signal isactually defined in thesignal module will appear in thedefault map:

  • signal.SIGTTIN:None
  • signal.SIGTTOU:None
  • signal.SIGTSTP:None
  • signal.SIGTERM:'terminate'

Depending on how the program will interact with its childprocesses, it may need to specify a signal map that includes thesignal.SIGCHLD signal (received when a child process exits).See the specific operating system’s documentation for more detailon how to determine what circumstances dictate the need for signalhandlers.

uid
Default:
os.getuid()
gid
Default:
os.getgid()

The user ID (“UID”) value and group ID (“GID”) value to switchthe process to on daemon start.

The default values, the real UID and GID of the process, willrelinquish any effective privilege elevation inherited by theprocess.

prevent_core
Default:
True

If true, prevents the generation of core files, in order to avoidleaking sensitive information from daemons run asroot.

stdin
Default:
None
stdout
Default:
None
stderr
Default:
None

Each ofstdin,stdout, andstderr is a file-like objectwhich will be used as the new file for the standard I/O streamsys.stdin,sys.stdout, andsys.stderr respectively. The fileshould therefore be open, with a minimum of mode ‘r’ in the caseofstdin, and mode ‘w+’ in the case ofstdout andstderr.

If the object has afileno() method that returns a filedescriptor, the corresponding file will be excluded from beingclosed during daemon start (that is, it will be treated as thoughit were listed infiles_preserve).

IfNone, the corresponding system stream is re-bound to thefile named byos.devnull.

The following methods are defined.

open()
Return:
None

Open the daemon context, turning the current program into a daemonprocess. This performs the following steps:

  • If this instance’sis_open property is true, returnimmediately. This makes it safe to callopen multiple times onan instance.
  • If theprevent_core attribute is true, set the resource limitsfor the process to prevent any core dump from the process.
  • If thechroot_directory attribute is notNone, set theeffective root directory of the process to that directory (viaos.chroot).

    This allows running the daemon process inside a “chroot gaol”as a means of limiting the system’s exposure to rogue behaviourby the process. Note that the specified directory needs toalready be set up for this purpose.

  • Set the process UID and GID to theuid andgid attributevalues.
  • Close all open file descriptors. This excludes those listed inthefiles_preserve attribute, and those that correspond to thestdin,stdout, orstderr attributes.
  • Change current working directory to the path specified by theworking_directory attribute.
  • Reset the file access creation mask to the value specified bytheumask attribute.
  • If thedetach_process option is true, detach the currentprocess into its own process group, and disassociate from anycontrolling terminal.
  • Set signal handlers as specified by thesignal_map attribute.
  • If any of the attributesstdin,stdout,stderr are notNone, bind the system streamssys.stdin,sys.stdout,and/orsys.stderr to the files represented by thecorresponding attributes. Where the attribute has a filedescriptor, the descriptor is duplicated (instead of re-bindingthe name).
  • If thepidfile attribute is notNone, enter its contextmanager.
  • Mark this instance as open (for the purpose of futureopen andclose calls).
  • Register theclose method to be called during Python’s exitprocessing.

When the function returns, the running program is a daemonprocess.

close()
Return:
None

Close the daemon context. This performs the following steps:

  • If this instance’sis_open property is false, returnimmediately. This makes it safe to callclose multiple timeson an instance.
  • If thepidfile attribute is notNone, exit its contextmanager.
  • Mark this instance as closed (for the purpose of futureopenandclose calls).
is_open
Return:
True if the instance is open,False otherwise.

This property exposes the state indicating whether the instance iscurrently open. It isTrue if the instance’sopen method hasbeen called and theclose method has not subsequently beencalled.

terminate(signal_number,stack_frame)
Return:
None

Signal handler for thesignal.SIGTERM signal. Performs thefollowing step:

  • Raise aSystemExit exception explaining the signal.

The class also implements the context manager protocol via__enter__ and__exit__ methods.

__enter__()
Return:
TheDaemonContext instance

Call the instance’sopen() method, then return the instance.

__exit__(exc_type,exc_value,exc_traceback)
Return:
True orFalse as defined by the context managerprotocol

Call the instance’sclose() method, then returnTrue if theexception was handled orFalse if it was not.

Motivation

The majority of programs written to be Unix daemons either implementbehaviour very similar to that in thespecification, or arepoorly-behaved daemons by thecorrect daemon behaviour.

Since these steps should be much the same in most implementations butare very particular and easy to omit or implement incorrectly, theyare a prime target for a standard well-tested implementation in thestandard library.

Rationale

Correct daemon behaviour

According to Stevens in[stevens] §2.6, a program should perform thefollowing steps to become a Unix daemon process.

  • Close all open file descriptors.
  • Change current working directory.
  • Reset the file access creation mask.
  • Run in the background.
  • Disassociate from process group.
  • Ignore terminal I/O signals.
  • Disassociate from control terminal.
  • Don’t reacquire a control terminal.
  • Correctly handle the following circumstances:
    • Started by System Vinit process.
    • Daemon termination bySIGTERM signal.
    • Children generateSIGCLD signal.

Thedaemon tool[slack-daemon] lists (in its summary of features)behaviour that should be performed when turning a program into awell-behaved Unix daemon process. It differs from this PEP’s intent inthat it invokes aseparate program as a daemon process. Thefollowing features are appropriate for a daemon that starts itselfonce the program is already running:

  • Sets up the correct process context for a daemon.
  • Behaves sensibly when started byinitd(8) orinetd(8).
  • Revokes any suid or sgid privileges to reduce security risks in casedaemon is incorrectly installed with special privileges.
  • Prevents the generation of core files to prevent leaking sensitiveinformation from daemons run as root (optional).
  • Names the daemon by creating and locking a PID file to guaranteethat only one daemon with the given name can execute at any giventime (optional).
  • Sets the user and group under which to run the daemon (optional,root only).
  • Creates a chroot gaol (optional, root only).
  • Captures the daemon’s stdout and stderr and directs them to syslog(optional).

A daemon is not a service

This PEP addresses only Unix-style daemons, for which the abovecorrect behaviour is relevant, as opposed to comparable behaviours onother operating systems.

There is a related concept in many systems, called a “service”. Aservice differs from the model in this PEP, in that rather than havingthecurrent program continue to run as a daemon process, a servicestarts anadditional process to run in the background, and thecurrent process communicates with that additional process via somedefined channels.

The Unix-style daemon model in this PEP can be used, among otherthings, to implement the background-process part of a service; butthis PEP does not address the other aspects of setting up and managinga service.

Reference Implementation

Thepython-daemon package[python-daemon].

Other daemon implementations

Prior to this PEP, several existing third-party Python libraries ortools implemented some of this PEP’scorrect daemon behaviour.

Thereference implementation is a fairly direct successor from thefollowing implementations:

Other Python daemon implementations that differ from this PEP:

  • Thezdaemon tool[zdaemon] was written for the Zope project. Like[slack-daemon], it differs from this specification because it isused to run another program as a daemon process.
  • The Python librarydaemon[clapper-daemon] is (according to itshomepage) no longer maintained. As of version 1.0.1, it implementsthe basic steps from[stevens].
  • Thedaemonize library[seutter-daemonize] also implements thebasic steps from[stevens].
  • Ray Burr’sdaemon.py module[burr-daemon] provides the[stevens]procedure as well as PID file handling and redirection of output tosyslog.
  • Twisted[twisted] includes, perhaps unsurprisingly, animplementation of a process daemonisation API that is integratedwith the rest of the Twisted framework; it differs significantlyfrom the API in this PEP.
  • The Pythoninitd library[dagitses-initd], which uses[clapper-daemon], implements an equivalent of Unixinitd(8) forcontrolling a daemon process.

References

[stevens] (1,2,3,4)
UnixNetworkProgramming, W. Richard Stevens, 1994 PrenticeHall.
[slack-daemon] (1,2)
The (non-Python) “libslack” implementation of adaemon toolhttp://www.libslack.org/daemon/ by “raf” <raf@raf.org>.
[python-daemon] (1,2)
Thepython-daemon libraryhttp://pypi.python.org/pypi/python-daemon/ by Ben Finney etal.
[cookbook-66012] (1,2)
Python Cookbook recipe 66012, “Fork a daemon process on Unix”http://code.activestate.com/recipes/66012/.
[cookbook-278731]
Python Cookbook recipe 278731, “Creating a daemon the Python way”http://code.activestate.com/recipes/278731/.
[bda.daemon]
Thebda.daemon libraryhttp://pypi.python.org/pypi/bda.daemon/ by RobertNiederreiter et al.
[zdaemon]
Thezdaemon toolhttp://pypi.python.org/pypi/zdaemon/ byGuido van Rossum et al.
[clapper-daemon] (1,2)
Thedaemon libraryhttp://pypi.python.org/pypi/daemon/ byBrian Clapper.
[seutter-daemonize]
Thedaemonize libraryhttp://daemonize.sourceforge.net/ byJerry Seutter.
[burr-daemon]
Thedaemon.py modulehttp://www.nightmare.com/~ryb/code/daemon.py by Ray Burr.
[twisted]
TheTwisted application frameworkhttp://pypi.python.org/pypi/Twisted/ by Glyph Lefkowitz etal.
[dagitses-initd]
The Pythoninitd libraryhttp://pypi.python.org/pypi/initd/by Michael Andreas Dagitses.

Copyright

This work is hereby placed in the public domain. To the extent thatplacing a work in the public domain is not legally possible, thecopyright holder hereby grants to all recipients of this work allrights and freedoms that would otherwise be restricted by copyright.


Source:https://github.com/python/peps/blob/main/peps/pep-3143.rst

Last modified:2025-02-01 08:59:27 GMT


[8]ページ先頭

©2009-2025 Movatter.jp