daemonproxy

A tight efficient process manager driven by external scripts

philosophy

This process manager is written in the spirit of daemontools, much like runit, s6, perp, and others.

Their common philosophy is that the one true way to monitor a daemon is for the daemon to be a child of a process manager, such that the process manager receives SIGCHLD the moment the daemon exits, sees the exit status of the daemon, and can take appropriate steps to restart the daemon.

The other semi-common philosophy is that the process manager should be able to restart a daemon connected to the same output pipe (for logging) that it was originally connected to, and also give it an identical environment each time it is started. (this is a thing that is hard to do when you run init scripts from cron jobs or other sloppy methods like that)

The point at which daemonproxy diverges from the rest is that it generates a stream of events which can be piped to an external script that does the actual service-management logic, and is in turn controlled by this script. Thus, it is a proxy for daemon management.

configuration

While the filesystem-based configuration of daemontools and friends is a nice simple and unix-friendly way to configure services, there are times when setting up a tree of special scripts, directories, and control files with special filesystem flags is something of a hassle. Particularly when you want to commit them to version control (losing the special permission flags), or want them to live on a read-only filesystem.

While each of those tools have various workarounds available, nothing beats a plain old config file, which can be committed to version control, stored on read-only media, or even generated by a script on the fly. daemonproxy makes this especially easy by even allowing the configuration to come from stdin.

In fact, daemonproxy's config file isn't really even a config file; it is just a stream of commands that might happen to be read from a file (or stdin, or a variety of other inputs). These commands might configure new services and they might start some of them.

But, the best feature of all is that commands can configure a "controller", which connects back to daemonproxy to dynamically issue more commands in response to events.

daemon management

daemonproxy is named daemonproxy because it is acting as a proxy for the actual service manager. The service manager you want to handle your special cases and needs is probably best written as a script. But, writing a process manager can be complicated, and a fatal bug could orphan all your daemons and make a difficult task of cleaning up the mess, or get stuck and stop performing its duties.

daemonproxy takes over the important role of the parent process, and can act as a watchdog for your script, while maintaining the state of all the services and file handles that connect them to their loggers. It also condenses signals and other events into a nice event stream (tab-delimited text) so your script doesn't have to deal with the complications of signal handling, nonblocking I/O, or waiting for children. All you have to do is read stdin and write stdout!

init replacement

daemonproxy is designed to be a suitable replacement for process 1. It uses a minimal amount of RAM, it can allocate all its dynamic memory on startup (the table sizes can be controlled with command line switches) and it has options to attempt recovery on lesser errors, or to exec() to a cleanup script in case of fatal error.

It is a single-thread process written in non-blocking style as a collection of state machines, and it has no external library dependencies, so it is a natural fit for static compilation. It also has relatively few lines of code! Memory footprint numbers are not yet available.

other uses

However, daemonproxy is certainly not limited to running as init! One of my main design goals is to use it for background jobs that web services want to run. A web service sometimes needs to kick off a background job, and then needs a way to check back on it to see if it is still running, whether it completed successfully, and maybe find the name of the output file (or screen session) it is using.

daemonproxy is a perfect fit for this, and accepts commands for creating new services, attaching arbitrary metadata to them, querying their PID and exit status, and the timestamps when they started or exited.