s6-linux-init
Software
skarnet.org
The s6-linux-init program
s6-linux-init is a program that is meant to run as pid 1,
as a stage 1 init: it performs the necessary early system preparation
and execs into s6-svscan.
Interface
s6-linux-init [ -c basedir ] [ -p initial_path ] [ -s env_store ] [ -m umask ] [ -d slashdev ] [ -D initdefault ] [ -n | -N ] [ -C ] [ -B ] [ args... ]
- If s6-linux-init isn't pid 1, it execs into
s6-linux-init-telinit with the
same arguments.
- Else, it performs some early preparation, spawns a process that
will run the rc.init script, then execs into
s6-svscan.
Options
These options should exactly mirror the options with the same name that
have been given to s6-linux-init-maker.
If there is a discrepancy, the system might not boot.
- -c basedir : read all its initialization
data from basedir. If the data has not indeed been copied to
basedir, the system will not boot.
- -p initial_path : the initial value for
the PATH environment variable.
- -s env_store : the place where to dump
kernel environment variables.
- -m initial_umask : the initial file umask.
- -d slashdev : mount a devtmpfs on
slashdev. By default, no such mount is performed - it is assumed
that a devtmpfs is automounted on /dev at boot time by the kernel.
- -D initdefault : the initial runlevel
to boot to, if it isn't overridden by the kernel command line.
This is only given as a first argument to rc.init.
Default is default.
- -n : instead of unmounting /run and mounting
a tmpfs on it, just remount /run.
- -N : do not touch /run at all.
- -C : run in a container. This option modifies a few
of the operations described below, to accommodate running in a container
instead of on real hardware. For instance: it does not scan the command
line for a specific runlevel, it does not trap ctrl-alt-del, and before
anything else it waits for its descriptor 3, if present, to close.
(Docker uses this fd 3 mechanism as synchronization between the Docker
daemon and the container's init.)
- -B : do not run the catch-all logger. This option
removes the catch-all-logger-related operations from the list below;
s6-linux-init will not redirect output descriptors, and will
use a different synchronization mechanism to ensure rc.init
only runs when s6-svscan
is ready.
Early preparation
When booting a system, s6-linux-init performs the following
operations:
- It prints a banner to /dev/console.
- It chdirs to /.
- It sets the umask to initial_umask.
- It becomes a session leader.
- It mounts a devtmpfs on slashdev, if requested.
- It uses /dev/null as its stdin (instead of /dev/console).
/dev/console is still used, for now, as stdout and stderr.
- It unmounts /run (or the directory you have given to the
--tmpfsdir configure option at package build time), just in case;
then it creates a tmpfs on it. Alternatively, it remounts /run,
or does not touch it at all.
- It copies the whole basedir/run-image hierarchy to
/run (or your chosen tmpfsdir).
- It reads the initial environment from basedir/env.
- If required, it stores the kernel environment into env_store.
- It performs "the fifo trick", i.e. it redirects its stdout to the
catch-all logger's fifo, without blocking, before the catch-all
logger is even up (because it's a service that will be spawned a bit
later, when s6-svscan
is executed).
- It forks a child.
- The child scans the kernel command line to find a suitable runlevel
(default, 2, 3, 4, or 5). If
it doesn't find any kernel command line argument that defines a runlevel,
it uses initdefault.
- The child becomes a session leader.
- The child blocks until the catch-all logger runs.
- It also makes the catch-all logger's fifo its stderr.
- It traps the ctrl-alt-del keyboard combination.
- It execs into s6-svscan
with /run/service as its scandir (or tmpfsdir/service).
- s6-svscan
spawns the early services that are defined in
basedir/run-image/service, and have been copied into
/run/service (or tmpfsdir/service).
- One of those early services is s6-svscan-log, which is
the catch-all logger. When this service is up, s6-linux-init's
child unblocks.
- The child execs into basedir/scripts/rc.init.
The first argument to rc.init is the chosen runlevel. The kernel
command line, as given by the kernel to s6-linux-init (i.e. without
the key=value arguments, which were passed into s6-linux-init's
environment and were stored into env_store), makes for the rest of
the arguments given to rc.init.
By the time rc.init runs,
s6-svscan is running
as pid 1 and has spawned its early services - at least the catch-all logger,
and the other services, including the early getty if it has been defined, are
started in parallel and will be ready instantly. rc.init can then
perform stage 2 of the initialization process, i.e. the handoff to
the service manager.
Exit codes
s6-linux-init never exits. It spawns the rc.init script
and execs into s6-svscan,
which runs forever until the machine stops or reboots.
Notes
- The s6-linux-init
binary is not meant to be called directly, or be linked to /sbin/init
directly, because it takes command-line options.
Instead, after a
s6-linux-init-maker invocation,
the bin/ subdirectory of the target will contain a script called
init, which execs into s6-linux-init with the appropriate
command-line options, and is suitable as a /sbin/init program.
The bin/ subdirectory
should be copied by the administrator into /sbin for full
interface compatibility with sysvinit.