09 Nov 2021 - tsp
Last update 09 Nov 2021
So I’m not a huge fan of Python for some particular reasons that are out of scope for this blog entry but it’s a language that exists and that is often used so sometimes on has to use it (by the way I like it for playing around with algorithms, fast hacks and as some advanced scripting language anyways). And then there are moments where one has to develop services around an extensive Python codebase - then it makes simply no sense to rewrite everything in a more sane and stable language than to use Python for the remaining parts of course.
Services on Unix like systems are usually (except for the new
realized as so called
daemon processes. These are processes that are launched
just like ordinary processes but then detach from their terminal and thus also
from their process hierarchy and run in background. The Windows analogon are
of course services - but they work somewhat different. On Unix like systems it’s
the responsibility of the daemon to start up, detach itself from the terminal
and optionally (especially important when launched as root) limit it’s own execution
environment as far as possible to reduce attack surface.
Usually the daemonization process is the execution of the following steps:
ttyby closing standard input and output as well as standard error output
ttyby accident. This ensures the new child is not a session leader and thus has no way of gaining control of the
chrootdirectory to limit file system access as far as possible. In case one requires access to stuff like
PIDor logfiles these should be opened before
/dev/nullor a logfile.
On some Unices the applications might even limit themselves more - for example on FreeBSD applications can drop their permissions to gain access to network ports, prevent access to filesystems and limit access to certain system calls. This is of course operating system specific.
Since these steps are security critical and tedious to do right there are libraries
that allow applications to daemonize themselves. For Python there is the
new PEP-3143 - the standard daemon
process library that’s found in the
python-daemon PyPi package. Unfortunately
I never really got that working - the following recipe uses also an external
daemonize. As usual I don’t really feel good when using
an external dependency from PyPi but that’s the Python way as it seems. This
package can be references in
daemonize and can be
manually installed using
pip install daemonize
The mini recipe that I’m referencing here performs the following steps:
mainStartuproutine in case the script is started as application
ExampleDaemonclass. After daemonization - or without - the
runfunction is invoked.
logginginto an optional logfile and selects the log level
SIGHUPwhich I’m using to signal the process to re-read it’s configuration as well as
SIGINTwhich are hooked to signal a termination request.
The whole code is available as a GitHub GIST
This article is tagged: