Supervisors and Init Systems: Part 2
On Monday I began a series about supervisors. It
mostly covered the most basic Supervisors out there, daemontools,
daemontools-encore, runit, and perp. This post will cover the more
advanced generation, which includes s6 and nosh.
Note: In this post I will treat s6 and nosh as a whole, despite the fact
that each has huge amounts of standalone parts and furthermore that each has
multiple distributions.
🔗 The Advanced Supervisors
Both of the supervisors discussed here have a very similar model and many of the
various pieces can be swapped in and out. I have used both nosh and s6 at
the same time within different services in the same supervisor tree. (By the
way, this interchangeability is not true of all supervisors; I’ll discuss that
on either Friday or next Monday.)
But to be blunt, while there are some significant additions that, say, runit
added to daemontools (specifically first class logger support and the check
script, also known as a readiness protocol) the distinctions between nosh and
s6 are much more subtle. There are absolutely differences, just not enough to
say one is better than the other. (runit is better than daemontools.)
🔗 s6
s6 is one of the newer supervisors in this list. I can’t find a release
before 2014 and the version control started over at 2.x. As far as I can tell
s6 was implemented as an alternative to systemd, which we’ll get into later.
s6 (and the next supervisor in this list, nosh) has the fairly interesting
property of avoiding shell scripts in order to be more secure and predictable.
If this argument sounds ridiculous, consider how many vulnerabilities in modern
software are caused by parsers, and now consider sidestepping that problem
entirely by just not having a parser.
s6 leverages a suite of tools collectively called execline for
this. Fundamentally it and nosh are very similar. The hand-wavy version is,
instead of having a Bourne-shell interpreter that reads a script and manages the
various programs and interaction until the end, both execlineb and nosh set
up a special environment and then are gone, no longer running at all. Here is
an example with a program many of us have heard of:
#!/bin/sh
exec env FOO=bar perl my-script.plIn the above (Bourne-shell) script we ran env(1), which set the environment
variable FOO to bar, and then immediately env(1) execed (or
chain-loaded) the perl interpreter. Now consider that both nosh and
execline ship with a few dozen commands in the same fashion, including cd,
trap, a few file descriptor manipulation commands, flow control, and more.
Even if you think the security and simplicity arguments are silly, having some
of these commands available can be extremely convenient. The difference that
execlineb and nosh have with the above example is that they simply tokenize,
exec, and get out of the way.
In addition to supporting the standard shell features, both s6 (as an
addon) and nosh have UCSPI support and many other
networking tools.
One notable tool that comes from the author of s6 (Laurent Bercot) is
sdnotify-wrapper, which allows a process to use the systemd readiness protocol
(which I’ll discuss Friday.) Basically you use it like most of the other tools
in this style (sdnotify-wrapper -t 60000 myprogram and args) and it will
advertise that your program is ready after your program writes a single line to
a given file descriptor; by default stdout.
The following is an execlineb run script I used to use (before moving my code
to Heroku) that uses s6 and its UCSPI additions:
#!/bin/execlineb
env SERVER_NAME=busybox SERVER_PORT=6000
cd ../..
bin/config-set-env
s6-tcpserver 127.0.0.1 6000
busybox httpd -i -f -h ./www
🔗 nosh
nosh is very similar to s6, but adds a really interesting feature:
it can read systemd units, but instead of parsing them at boot time you compile
them down to nosh scripts ahead of time, thus adding security,
predictability, and clarity. nosh is the first supervisor in this series not
written in C, instead implemented in C++. That doesn’t bother me much, but some
people are annoyed by it.
On top of all of the various tools that Laurent Bercot has built for the s6
suite of tools, nosh (built by Jonathan de Boyne Pollard) brings to the table
some console management tools. I have never used these, but I’d be interested
in trying.
Eventually I moved the script mentioned above from s6 to nosh, and here is
what it became:
#!/bin/nosh
chdir ../..
tcp-socket-listen 127.0.0.1 6000
tcp-socket-accept --no-delay
envdir --ignore-nodir --chomp /home/frew/.lizard-brain
bin/config-set-env
cgid plackup www/cgi-bin/impulse-www
Clearly a couple other changes were made, including the use of my own UCSPI based CGI server
There is so much more that could be discussed about both nosh and s6.
The software for both (this applies to the suites from the previous post as well,
there is just so much less) is carefully and beautifully designed to make sense
and work with other tools. In fact, as I was researching this post, I found
this quote about some of the console stuff provided by nosh:
As a bonus feature, the source package contains a getty
execlinebscript that does exactly that
Despite the fact that in theory nosh and s6 are competing for mindshare,
there is neither a technical nor even social reason to keep them separate, and
indeed nosh code uses s6 code.
Maybe it’s just my personal tastes, but just perusing Laurent and Jonathan’s sprawling writing is inspiring and informing to me. I highly recommend the following, if you can relate:
- execline grammar
- s6 sales pitch
- s6 oveview
- nosh sales pitch
- how to daemonize
- “Wrapping Apache Tomcat in many pointless extra layers”
Unlike in the first post, in which I could concretely recommend runit over the
rest, I do not think I can make such a recommendation here. s6 is more normal
(simple compilation) but does not ship packages. nosh is C++ and doesn’t use
make, but it integrates better with existing systems. Honestly, having
switched from one to the other, I would say either of these are fine and
swapping in the other, even piecemeal, is fine and pretty cool.
On Friday I’ll discuss some of the more unusual, niche supervisors.
(The following includes affiliate links.)
This topic is very unix heavy, so if you are totally lost or would like an in
depth refresher, Advanced Programming in the UNIX Environment, by Stevens
is a good option.
Similarly, some of the tools above (and many more in later posts) discuss tools
that while written for assistance in supervision are useful in isolation. I
think that
The Unix Programming Environment
does a great job diving into tools that are general enough to stand on their
own.
If you're interested in being notified when new posts are published, you can subscribe here; you'll get an email once a week at the most.