aboutsummaryrefslogtreecommitdiffstats
s6-linux-init: the s6-linux-init program

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 ] [ -W readyfd ] [ 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, and it does not trap ctrl-alt-del.
  • -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.
  • -W readyfd : before doing anything, wait for file descriptor readyfd to signal EOF. This is typically useful in containers that implement the Docker synchronization mechanism, where the container manager starts the container with a pipe open to the container's descriptor 3, does its preparation, and closes the pipe to tell the container's init that it can proceed. If this option is not given, or readyfd is 0, no synchronization occurs and s6-linux-init boots without waiting.

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.