The daemontools family

Other possibly interesting pages:

The daemontools family is a family of dæmon supervision and management tools that all share similar design principles, and many implementation mechanisms.

Members

Daniel J. Bernstein's daemontools,

The original toolset. It began, with version 0.51 on 1997-07-15, as a way to "dæmonize" programs from the command line. This soon developed into a proper dæmon supervision suite, with a service manager, especially as the imposibility of securely "dæmonizing" a child process running in a terminal session became apparent.

This was packaged for Debian Linux by Gerrit Pape as daemontools, adding his own daemontools-doc with manual pages derived from Bernstein's WWW site and daemontools-run that runs daemontools under System 5 rc. It is also sysutils/daemontools in the FreeBSD ports tree and sysutils/daemontools in the NetBSD packages tree.

Gerrit Pape's manual pages and a couple of extra things have been collected into djbwares, a collection of several of Daniel J. Bernstein's tools all in one.

Gerrit Pape's runit

A reimplementation of the same design and mechanisms, begun with version 0.1.1 on 2001-11-20. It was extended to provide rudimentary system management as well, and remains (as of 2015) one of only two members of the daemontools family to provide a system manager program that can be run as process #1 of a Linux system.

runit has the famous "just run four shell scripts" approach to system management. It went down the same path as daemontools-encore, in more tightly integrating "log" and "main" services than the original daemontools did. All of the command names are quite different.

This was packaged for Debian Linux by Gerrit Pape as runit and (initially) runit-run. It is also sysutils/runit in the FreeBSD ports tree and runit-1.7.2p2 in the OpenBSD ports tree.

Adam Sampson's freedt

A GPL-licensed clone of the original daemontools, that was begun in 2003. The control status API is not binary compatible with daemontools, as is the case for most of the others.

It is fairly little-known. You'll be surprised to find that you have this pre-packaged if you have a BSD. It is sysutils/freedt in the FreeBSD ports tree, for example, and freedt-0.22p2 in the OpenBSD ports tree.

Bruce Guenter's daemontools-encore

A straight clone of the original daemontools, but with several augmentations. In particular, daemontools-encore expanded the range of dæmon states from just the plain binary "up" and "down" to "stopped", "starting", "running", "failed", and "stopping". It did this in a backwards-compatible way, so that its control/status API is a superset of the daemontools one. It went down the same path as runit, in more tightly integrating "log" and "main" services than the original daemontools did.

Attempts to package this for Debian Linux have not got off the ground. However, it is sysutils/daemontools-encore in the FreeBSD ports tree.

Laurent Bercot's s6

Another straight clone of the original daemontools, with the Bernstein libraries, that was begun around 2002–2003. Again, there are some augmentations. All of the programs have the original names but prefixed "s6-".

It is sysutils/s6 in the FreeBSD ports tree.

Of particular note is its accompanying toolset execline. This is a script interpreter that takes the design of the old Thompson UNIX version 6 shell, where if was an ordinary (external!) command and not a special shell language syntactical element (as became the case with the later Bourne shell), to its logical conclusion.

Wayne Marshall's perp.

A reimplementation from scratch of the same design, begun with version 0.00 on 2010-01-12. All of the command names are different; and a few of the mechanisms are different. Single-function run programs are instead multi-function rc.main programs.

perp went even further down the path taken by runit and daemontools-encore, in more tightly integrating "log" and "main" services than the original daemontools did. It is impossible to divorce "log" services from "main" services with perp.

the nosh package

A reimplementation from scratch of the same design, with some of the daemontools-encore augmented mechanisms. All of the command names are different, however "shims" are provided that (for example) symbolically links svc to service-control.

nosh does the things that people said for a decade could be done with daemontools, by adding layers on top, but never got around to doing. It also, at the time of the great Debian hoo-hah in 2014 over systemd, served to demonstrate that service units are not a lock-in mechanism. It is an existence proof that one can do dependency-based service management, one can have targets/milestones, and one can import from foreign systems with translation tools. It was also the second member of the family to provide a program that is suitable for running as Linux (and indeed BSD) process #1.

This is packaged as a suite of various packages for Debian Linux, for FreeBSD, and for OpenBSD.

nosh is actually the name of a "non-shell" script interpreter that comes in the package, akin to execline but aimed at the common use case (for run programs in particular) where all that one needs to do is chain through a sequence of helper programs.

Design

API

Greg White once described daemontools as "/var/run done the right way". Its most obvious distinguishing feature is that its control/status API is the filesystem, a collection of FIFOs and ordinary files in a supervise directory. There is no need for such dangerous, unreliable, and insecure mechanisms as PID files.

The API does not rely upon complex and arcane transport systems outwith the filesystem. There's no need for "bus manager" communications server processes, and so no need for the complex chicken-and-egg dances that occur at system startup with "bus managers". (D-Bus has a special, effectively undocumented given the paucity of its manual page, --systemd-activation switch that is used because the systemd process #1 cannot make its API available until it has first run the dæmon that provides the IPC mechanism over which things comunicate with systemd.) The API access controls are the filesystem's own access controls, and are manipulated with ordinary filesystem tools such as setfacl and chmod. (The people at Heavy Water Operations ask "Is it possible to allow a user other than root to control a service?". Yes, it is; by simply granting that user access to the relevant control/status API files with setfacl.)

Logging

The principles behind logging in the daemontools family are simple. Services can be categorized into "main" services that run some dæmon and write to their standard outputs and standard errors, and "log" services that read from their standard inputs and write to logs. The service manager connects the twain with an ordinary pipe. It holds this pipe open, with file descriptors, itself; which means that the "log" service can be restarted without losing pending log data sitting in the pipe.

There are a range of logging programs available:

dumblog

From freedt, this is a very basic logging program that just appends to one output file.

The difference between using this and just redirecting directly to file is that dumblog can be told to switch files. It can be instructed to close the current file and then re-open it, providing a very simple and basic manual log rotation mechanism. This is impossible with simple redirection (save for getting very dirty fiddling around with the internals of a running dæmon process using debugging mechanisms).

cyclog

From nosh, this is one step up from dumblog. Early versions of daemontools came with a cyclog program, but no longer do.

The major step up is auto-rotation of a set of automatically, and strictly, size-capped log files in size-capped log directories, with no manual outside intervention necessary. cyclog writes to sets of log files contained in log directories. When size limits are about to be exceeded on the set of files in a log directory, cyclog deletes old files to free up space. When size limits are about to be exceeded on an individual log file, cyclog closes that file and switches to a fresh one. Rotation can of course still be explicitly triggered if one really wants to.

tinylog

From perp, this is likewise one step up from dumblog. And it's the same step of auto-rotation of a set of automatically, and strictly, size-capped log files in size-capped log directories, with no manual outside intervention necessary. tinylog can also automatically run a compression program to compress old log files.

multilog, multilog, multilog, s6-log, and svlogd

Later versions of daemontools gave up cyclog for multilog, to which these are all roughly equivalent. In addition to what cyclog can do, these can run arbitrary post-processing commands when rotating the current log file, write out single-line "status" files with the last line of log, and apply filtering so that log lines are only sent to log directories if they match certain patterns.

Chain loading

Another daemontools distinguishing feature, albeit one shared with other toolsets, is that of chain loading. Composing the execution state that a dæmon process starts with is done by running a set of helper programs first. Each program does something to the execution state — adjusting UID/GID to drop privileges, setting/modifying/unsetting environment variables, changing working/root directories, and so forth — and then chain loads the next thing to run, overlaying its own program image in the same process, with the execve() system call. The final dæmon program is run via this chain of helpers.

Composability

All of the daemontools-family toolsets share the trait of composability. The operation of a run program is built from a toolset of tools, which can be composed in a multitude of ways according to desired function. Most of the family members come with their own toolsets that each can cover the vast majority of use cases.

But the important points are not completeness; but that incompleteness is not a problem and there is no lock-in. As shown in a side-by-side look at run scripts and service units, one can mix and match tools from different toolsets if one is not sufficient: a run script under freedt could use s6-log; a run script under daemontools-encore could use execline; one could use chpst under perp, or runtool under daemontools-encore; … and so forth.


© Copyright 2015 Jonathan de Boyne Pollard. "Moral" rights asserted.
Permission is hereby granted to copy and to distribute this web page in its original, unmodified form as long as its last modification datestamp is preserved.