09 Nov 2021 - tsp
Last update 09 Nov 2021
4 mins
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 systemd area)
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:
tty by closing standard input
and output as well as standard error output
tty by accident. This
ensures the new child is not a session leader and thus has no way of
gaining control of the tty again.chroot directory to limit file system access as
far as possible. In case one requires access to stuff like PID or logfiles
these should be opened beforeumaskstdin, stdout and stderr either to /dev/null
or 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
library called 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 setup.cfg as daemonize and can be
manually installed using
pip install daemonize
The mini recipe that I’m referencing here performs the following steps:
mainStartup routine in case the script is started
as applicationmainDaemon
trampoline function.ExampleDaemon class. After
daemonization - or without - the run function is invoked.logging into an optional logfile and selects the
log levelSIGHUP which I’m using to signal the
process to re-read it’s configuration as well as SIGTERM and SIGINT
which are hooked to signal a termination request.The whole code is available as a GitHub GIST
This article is tagged:
Dipl.-Ing. Thomas Spielauer, Wien (webcomplains389t48957@tspi.at)
This webpage is also available via TOR at http://rh6v563nt2dnxd5h2vhhqkudmyvjaevgiv77c62xflas52d5omtkxuid.onion/