daemontools
A series of scripts that run the supervise program. It initially runs svscanboot [1], which enables logging and uses svscan [2] to look through a service directory in order to execute the supervise executable for each service. [3] Supervise loads the run command, and unlike runit (which was inspired by daemontools) when run ends, it waits a second and executes run again. As with runit, if it can read a down file, then it does not start the service. [3]
To control the service, you run svc [command] services, which writes to a the named pipe control. This pipe is being managed by supervise, which uses it to send a signal to the process depending on the control value it reads. [4]
When this uses System V init, you must add svscanboot to the inittab as a respawn process.
---
runit
Executes /etc/runit/2 and if this fails, restarts it. /etc/runit/2 generally runs runsvdir on a particular directory (normally /etc/service) [5] and once every 5 seconds checks if the time of last modification, the inode, or the device has changed, in which case it starts a new runsv process on the new directory.
runsv switches to the directory of the service and if the file down doesn't exist it executes the run script. Once the script exits, if there is a finish script it executes this. If there is no finish script, then runsv executes the run script again. [6]
To handle abnormal failure, you must write a script that handles it. When the run command exits, runsv passes the exit code (-1 if abnormal exit) and least significant byte of the exit status as determined by waitpid - useful if a signal is sent. [6]
You start and stop a service by using the sv program. The mechanism used in to create a pipe named control in the service directory, which runsv reads and when a control character is written to the pipe it first checks to see if there is a custom command it needs to run, if so then it runs it. runsv will send a signal to the process it is monitoring depending on what control character is written to the pipe, or unless the custom command returns 0 in which case no signal is sent. [6]
runit is meant to replace init, and run under PID 1. [7] However, it can still use it with the existing init on your system. [8] You can configure it to replace the logging facility via the <service>/log/run script - runit just redirects the services standard output to it as standard input and you just send that input to the logger.
---
OpenRC
Not a replacement for init, but instead is invoked by init. /sbin/openrc reads /etc/runlevels, builds a dependency graph and then starts the run scripts for each of the services in the correct order. Then executable ends. [9]
---
s6
Basically inspired by runit, except the guy who makes it feels that dependency management is important and should be run by PID1. [14]
To do this, he has created a minimal shell language called execline [10] which he has run as the first process by his program execlineb [11], creates a tmpfs filesystem and copies a base image prepared by s6-linux-init into it [12], has the process reload its environment variables then forks and blocks a child process. Next, it executes as PID 1 into the service dependency tool s6-svscan, which scans a service directory and loads some initial minimal services (the logger and an optional getty, etc).
Once this is done the child process unblocks and executes s6-rc-init, which requires a compiled service database and a services directory for it to scan. After this is done, the system will be in a fully operational state.
To shutdown, PID 1 is sent a s6-svscanctl command and a shutdown script is issued.
---
In Summary
Here's the thing I see. With the exception of s6, which makes sense but seems overly complicated to me, all of these init systems have issues. daemontools polls to see if services need to be loaded, and has no dependency order. Runit has the same issue, but as pointed out by the s6 creator, if the runsv process dies then the pipe between the logger and the process means that you can lose the log. [15] s6 also does dependency by forking early, then blocking that child process till the system is usable enough for normal services to start correctly. To do this requires considerable effort, which may not be a big problem but I don't know if it's a big enough concern to be concerned about.
Runit and daemontools run shell scripts, but not in the system V way - they have run scripts you can customize. s6 has something similar, but allows for dependency tracking through listening and waiting for the status of services. You can combine Runit with OpenRC.
systemd uses socket activation for it's dependency tracking. The biggest criticism of it is that it runs in PID 1, and if it crashes it will take out your system. Whilst there are ways around this (as shown by the s6 system), I think in reality it's unlikely to occur. YMMV. But systemd provides unit files and a bunch of configurability, and I personally think it makes everyone's life easier.
The ancilliary utilities are not running in PID 1 though. And as with other systems, you use a utility to start and stop services - which some object to, but when you objectively look at it I really think you'd be hard pressed to be terribly worried about it.
So systemd does do a lot, but I think most of the arguments I've seen so far don't really show how it is a failed system in any way.
1. http://cr.yp.to/daemontools/svscanboot.html
2. http://cr.yp.to/daemontools/svscan.html
3. http://cr.yp.to/daemontools/supervise.html
4. http://cr.yp.to/daemontools/svc.html
5. http://smarden.org/runit/debian/2
6. http://smarden.org/runit/runsv.8.html
7. http://smarden.org/runit/replaceinit.html
8. http://smarden.org/runit/useinit.html
9. https://github.com/OpenRC/openrc/blob/master/guide.md
10. http://skarnet.org/software/execline/
11. http://skarnet.org/software/execline/execlineb.html
12. http://skarnet.org/software/s6-linux-init/s6-linux-init-make...
13. http://skarnet.org/software/s6-rc/s6-rc-init.html