Quickstart and FAQ for s6-linux-init
- Install all the s6-linux-init dependencies:
- Install s6-linux-init itself
- Save your old /sbin/init binary
- Save and remove your old /etc/s6-linux-init directory, if you have one
- Make sure you have a /run directory
- Write a machine initialization script in /etc/rc.init and
a machine shutdown script in /etc/rc.shutdown. Make them executable.
- If, at shutdown time, you need to run a script before the
supervision tree is torn down (for instance if you're using
s6-rc and want to
cleanly stop all your services), write that script in
- Check that your devtmpfs is automounted by your kernel at boot time. If it is not,
add the -d 1 option to the s6-linux-init-maker command line below.
- As root, run:
rm -rf /tmp/s6-linux-init /tmp/init
mv /tmp/s6-linux-init /etc/
ln -sf /etc/s6-linux-init/init /sbin/init
- Congratulations! your machine is now running a s6-based init system.
- To shut the machine down, use the
s6-reboot command as appropriate.
Why is it so complicated to use s6 as an init process? It's much
simpler with runit.
Yes, runit is simpler, because it provides a simple
suitable as a /sbin/init program and calls scripts to
handle the three stages of init. However, the runit design has a
few perfectible points:
- The one-time initialization is performed in /etc/runit/1, but
the supervision tree is not run until /etc/runit/2, which means
means that it is impossible to start supervised services during the
one-time initialization. Early daemons such as udevd, for
instance, have to remain unsupervised.
- runit runs with its descriptors pointing to /dev/console,
which means that error messages from the supervision tree, and uncaught
logs, will be displayed on the system console; they are not saved beyond
the console buffer capabilities.
- The runit supervision tree is of height 3
(runit, runsvdir, runsv), when height 2 is enough - some init
systems, like sysvinit, systemd or launchd, even provide a
supervision tree of height 1! (At the expense of complexity in the init
process, of course.) Height 3 is a bit redundant, because the supervision
capabilities of the root will be redundant with either those of the trunk
or those of the branches. Its display is also aesthetically less pleasing than
height 2: try out ps afuxww on a runit-based system.
Yes, this point is extremely minor, but still deserves a mention. :-)
Running a s6-based init addresses those issues:
- Save for the initial tmpfs mount, all of the machine
initialization runs in the stage 2 script, i.e. /etc/rc.init,
and the supervision tree is already available at that point. This
makes it possible to start one-shot services as well as long-run
services in the desired order while ensuring that every long-run service
is properly supervised, i.e. it lays the ground for a proper dependency
- s6-linux-init solves the problem of uncaught logs in a clean
way, and any error message from any process in the system is
guaranteed to end up in a logging directory. The only
exception is error messages from the catch-all logger process itself:
those naturally go to /dev/console.
- When s6-svscan runs as process 1, the supervision tree is of
height 2, and ps afuxww looks clean.
To sum up, a s6-based init is cleaner than a runit-based
init; it's a bit more complex to set up, but it organizes the system
in a better way, without using more resources. And the goal of
s6-linux-init is to make the setup more accessible.
My /etc/rc.init script is not printing anything!
You probably gave the -r option to
your /etc/rc.init's output is being logged into the
/run/uncaught-logs directory instead of printed to
I want to run s6 in a container, and I just want to log
to stdout/stderr, without this tmpfs and /dev/console
without having a catch-all logger inside the container. Is it
Yes, it is possible, but then s6-linux-init may not be what you
are looking for. For your case, it will be simpler to run s6-svscan
If you are using
Docker, there is a
project specifically made for integrating s6 into Docker images.