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 beforeumask
stdin
, 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/