S6-linux-init (package)

s6-linux-init is s6-based init system, with optional s6-rc support, on top of the Linux kernel]]. The package's documentation is provided in HTML format, and can be read on a text user interface using for example.

Files

 * — Default base directory of and.
 * — List of account names used by when invoked with an   option, to decide whether the machine shutdown request should be allowed to proceed or not.

Usage
The package provides the program, which helps create several components of an s6-based init system, programs for booting and shutting down the machine when such components are used, and other support programs. It also provides tools for implementing runlevel-like functionality similar to that of sysvinit.

s6-linux-init-maker
The program must be run as root, so that it can create files and directories with appropriate owner, group and permissions, and must be invoked with a pathname as its argument. It creates a directory at the specified pathname, which must not exist beforehand, containing several init system components:


 * A subdirectory named, which contains:
 * An s6 scan directory image.
 * An empty directory named.
 * A subdirectory named, that might be empty.
 * A subdirectory named, containing shell scripts named , and . For s6-linux-init version 1.0.3.0 and later, this subdirectory also a shell script named.
 * A subdirectory named, containing sysvinit compatibility execline scripts.

To use these components to make an init system, they must be copied to appropriate filesystem locations. The script contained in the  subdirectory can be e.g. renamed and copied to a directory that matches an   kernel parameter. For example, if the bootloader is configured to pass an  parameter to the kernel, then the  file generated by  must be copied to  and renamed as. The, and  subdirectories must be copied to the  program's base directory. For the sysvinit compatibility scripts, see here. Care must be taken to ensure that owner, group and permissions of files and subdirectories are preserved when cpoying them to their destination place, e.g. by using GNU or BusyBox with the   option, or the  program from s6-portable-utils.

The generated init system needs at least three files that must be supplied by the user to complete it: a stage2 init, a shutdown file and a runlevel changer file, all of which must be executable. The stage2 init is used by the program, the shutdown file is used by the shutdown daemon, and the runlevel changer file is used by the runlevel changer service. For s6-linux-init version 1.0.3.0 and later, a fourth executable file can be supplied by the user if needed, the final shutdown file. It is also used by the shutdown daemon if present.

accepts a set of options that customize all init system components. For the full description of, please consult the HTML documentation in the package's subdirectory. A summary of each init system component and some of 's options that customize it follows.

The stage1 init
The script contained in the  subdirectory of the directory created by  is a stage1 init. 's stage1 init runs as process 1 during the machine's boot sequence, and is an execline script that wraps an invocation of a program supplied by the package, also named.

expects to access the contents of a certain base directory, and performs these actions:
 * It sets the PATH environment variable to a specified or default value.
 * It sets the working directory to.
 * It sets the file mode creation mask to a specified or default value using a POSIX  call.
 * It makes itself the leader of a new process group using a POSIX  call.
 * It unmounts any filesystem that might be mounted at, and mounts a read-write tmpfs with options ,   and.
 * If an  option was passed to, it assumes that a tmpfs is already mounted at , and remounts it with the previously mentioned options. This is useful when an initramfs is used to mount the tmpfs, and writes data to it that must be preserved.
 * If an  option was passed to, it assumes that a tmpfs is already mounted at  and does nothing. This is useful when an initramfs is used to mount the tmpfs, and it should remain as the (read-write) rootfs of the machine.
 * If a  option followed by a pathname was passed to, it mounts a devtmpfs at the supplied pathname.
 * If an  option followed by a pathname was passed to, it dumps the enviroment set up by the kernel to a specified enviroment store. The environment store is an environment directory suitable for.
 * It copies the subdirectory of the base directory to the tmpfs, preserving owner, group and permissions of files and subdirectories.
 * It unsets all enviroment variables except PATH.
 * It adjusts the enviroment according to the subdirectory of the base directory, as if by an  invocation.
 * It redirects its standard input to.
 * It redirects its standard output and error to the catch-all logger's FIFO.
 * (version 1.0.4.0 and later) If a  option was passed to, it will instead create a pipe, close its reading end, and pass the file descriptor number of its writing end to  after a   (notify readiness) option. The child process that will execute the stage2 init is spawned before closing the reading end of the pipe; the process will therefore inherit the corresponding file descriptor, so that it can use it to wait for 's readiness notification. This allows setting up the resulting init system without a catch-all logger.
 * It spawns the stage2 init as a session leader using a POSIX  call.
 * (version 1.0.3.0 and later) It uses a Linux  system call with an   command, to ask the kernel to send a   signal to process 1 when the ++ key combination is pressed.
 * (version 1.0.4.0 and later) It uses a Linux  system call with a   request, to ask the kernel to send a   signal to process 1 when the key combination that corresponds to keyboard signal is pressed (usually configured to be +).
 * It replaces itself with using a POSIX   call, passing it the   (divert signals) and   (do not periodically scan the scan directory) options, and passing  as the pathname of the scan directory.

If finds that its process ID is not 1, it replaces itself with.

Aspects of the stage1 init that can be customized via options are:
 * The pathname of 's base directory: . Default:.
 * The value the PATH environment variable is initially set to: . This value affects all programs invoked by the stage2 init, and, and will be the initial value of PATH for all the init system's supervision tree processes. Default:.
 * The initial value of the file mode creation mask for all the starting processes: . Default: 0022.
 * Whether a devtmpfs filesystem will be mounted: . If this option is not specified, no devtmpfs is mounted by . Otherwise, it must be followed by the pathname of the filesystem's mountpoint.
 * What to do about the read-write tmpfs:  or.
 * (version 1.0.4.0 and later) Whether a catch-all logger will be used:.
 * The pathname of a read-write directory for storing the kernel's environment variables (i.e. the environment store): . If this option is not specified, the environment set up by the kernel is discarded before  replaces itself with.

All these options, if specified, are passed as-is to (via the generated  script). checks that the pathname specified after options,   and   is absolute.

The stage2 init
The stage2 init must be provided by the user, must be an executable file named, and located in the subdirectory of 's base directory. Unless has been invoked with the   option,  runs with its standard output and error redirected to the catch-all logger's FIFO, i.e. all messages will be logged to the logging directory. Otherwise, its standard output and error are redirected to the machine's console.

is invoked with at least one argument: an initial runlevel name. All arguments of the stage1 init are also passed verbatim to, after the initial runlevel name. scans its argument list, and if one of the arguments is the word,  ,  ,   or  , then it is interpreted as the initial runlevel name and passed to  as the first argument —which means that it will be repeated later in the argument list—. Otherwise, if a  option followed by a runlevel name was passed to, then it is interpreted as the initial runlevel name and passed to  as the first argument. Otherwise, the word  is passed as the first argument.

copies the file named from a directory that can be specified with the   option, to the  subdirectory of its generated directory as the stage2 init. If no  option is specified, directory  is used on Gentoo. The package installs an example stage2 init in, that is a shell script containing only comments.

Aspects of the stage2 init that can be customized via options are:
 * The name of the initial rulnevel, if it was not specified in the kernel command line: . Default: the word.

This option, if specified, is passed as-is to (via the generated  script).

The scan directory image
The init system's scan directory image is the subdirectory of of 's base directory, which is ccopied by  to the read-write tmpfs mounted at. This copy then becomes 's scan directory when it starts running as process 1. Therefore, the init system's scan directory's absolute pathname will be.

The scan directory image must contain at least these service directories:
 * One for the shutdown daemon, which must be named.
 * One for the catch-all logger, if one is used. For s6-linux-init version 1.0.4.0, if present, it must be named.
 * One for the runlevel changer service, if the program is going to be used. If present, it must be named.

The scan directory image generated by satisfies this requirements, and can optionally contain a service directory for an early getty service, named. This service, if present, allows logging in to the machine from its console as early as possible. The scan directory image also contains diverted signal handlers, as well as the  and  files used for 's finish procedure. These two files simply print an "s6-svscan crashed. Rebooting." or "s6-svscan exited. Rebooting." message, respectively, and perform a forced reboot of the machine with an command.

Aspects of the scan directory image that can be customized via options are:
 * Whether an early getty service will be present: . If this option is not specified, there will be no early getty service, and any  setup must be done by the user-provided stage2 init. Otherwise, it must be followed by a suitable invocation (program name and arguments) of some  implementation, such as, for example,   for Gentoo. The generated service directory will contain a  execline script with the specified invocation.

The catch-all logger
The catch-all logger generated by is an  process that, on Gentoo, logs to (automatically rotated) logging directory. This means that the logdir is placed in the read-write tmpfs mounted by. The standard output of the process is redirected to, and  redirects 's standard error to the machine's console, using an   option (console holder) passed by.

The file of the logger's s6 service directory opens the corresponding FIFO for reading, and then invokes  with the   option, so that it cannot be killed by the   signal, with a   option, which makes it signal readiness to its  parent process using file descriptor 3 for the notification channel, and with the   (blocking) option, which makes  stop reading from the FIFO while it has unflushed buffers. This avoids unbound memory use if there is a lot of output to write.

For s6-linux-init version 1.0.4.0 and later, the catch-all logger is optional. If one is not used, all messages that would be logged are printed to the machine's console instead.

Aspects of the catch-all logger that can be customized via options are:
 * (version 1.0.4.0 and later) Whether a catch-all logger will be used: . If this option is specifed, no s6 service directory is generated for the catch-all logger in the scan directory image.
 * The process' effective user and group:  . Default:  runs as root. If this option is specified, it must be followed by an account database username. The  program from the s6 package is used in the generated service directory's  script to change to a non-privileged user.
 * How logged lines of text are timestamped:  . Default: timestamps in external TAI64N format are used, as generated by 's t directive.
 * Whether the catch-all logger also prints logged lines to the machine's console:  (the number one). This is generally useful to debug a system at a glance, but if a failing program keeps sending error messages, it may interfere with comfortable usage of kernel virtual terminals. This can be avoided by not using  for any  process. If this option is used, the standard output of the  process is redirected to the console instead of, and a "1" directive is used for printing logged lines.

creates an subdirectory in the  subdirectory of its generated directory, with an owner and group that are suitable for 's effective user and group, and appropriate permissions.

The runlevel changer service
The runlevel changer service generated by is named, and is an  process that executes a user-provided file. The -  mechanism allows executing the file in a controlled, reproducible environment, i.e. the one set up for the init system's supervision tree processes. This is similar to the service that s6-rc uses for oneshots. The file runs with its standard input and output redirected to, and its standard error logged by the catch-all logger, if one is used.

This service is used by the program.

Aspects of the runlevel changer service that can be customized via options are:
 * The pathname of the base directory, where the user-provided script is expected: . Default: . It is used to construct  the argument list for.

The shutdown service and daemon
The shutdown service generated by is a supervised  process. It is used by the and  programs. The program is a shutdown daemon that takes care of performing the shutdown sequence. It runs as a long-lived process, expects to access the contents of a certain base directory, and performs these actions:


 * It reads from a control FIFO, waiting for either machine shutdown requests, or shutdown cancellation requests. A shutdown request consists of an action that can be halt, poweroff, reboot or the special action S, a time value that specifies a delay until actual shutdown, and another optional time value that specifies a grace period.
 * If a shutdown request is received, it waits until the specified shutdown delay expires, while it keeps reading from the control FIFO.
 * If a shutdown cancellation request is received, it cancels any pending machine shutdown that has been previously requested.
 * If the shutdown delay expires and the shutdown request has not been canceled, it starts the shutdown sequence by executing a shutdown file as a child process, and waits until it terminates. The shutdown file is an executable file that must be provided by the user, must be named, and must be located in the subdirectory of the base directory. Because  is part of the init system's supervision tree,  runs with the same environment that was set up for , with its standard input redirected to , and its standard output and error logged by the catch-all logger, if one is used.
 * If the action specified in the shutdown request was S, it does nothing and starts reading again from the control FIFO. This allows the implementation of a behaviour that is similar to sysvinit's single user mode. Otherwise:
 * It redirects its standard output and error to, i.e. the machine's console.
 * It creates an execline script named in its s6 service directory.
 * It stops all processes from the supervision tree except the catch-all logger, if one is used, and itself, by renaming the corresponding service directories with a name that starts with a dot ('.'), and performing the equivalent of an command. The renaming of the servicedirs prevents  from restarting their corresponding  process after they exit.
 * It syncs all disks, flushing all the dirty system buffers, using a POSIX  call.
 * It kills all remaining processes by sending them a  signal followed by a   signal, using POSIX   and   calls, and waits for the expiry of the grace period specified in the shutdown request.
 * If the shutdown request specified a duration for the grace period, that value is used.
 * Otherwise, if a  option followed by time value in milliseconds was passed to, the specified value is used as the duration of the grace period.
 * Otherwise, the duration of the grace period is 3 seconds.
 * It kills all remaining processes by sending them a  signal using a   call. Then, if  did not get killed by the signal, it exits.
 * The shutdown service's corresponding process restarts.
 * notes that there is a file named in its service directory, redirects its standard output and error to, and replaces itself with it using a POSIX   call.
 * The execline script unmounts all mounted filesystem according to, and remounts the rootfs read-only, using auxiliary program.
 * (version 1.0.3.0 and later) The execline script executes a final shutdown file as a child process, and waits until it terminates. The final shutdown file is an executable file that must be provided by the user, must named, and must be located in the subdirectory of the base directory. Because  is part of the init system's supervision tree,  runs with the same environment that was set up for , with its standard input redirected to , and its standard output and error redirected to the machine's console.
 * The execline script invokes the program with an   option (force), and an ,   or   option, according to the action specified in the shutdown request (i.e. halt, poweroff or reboot).

's control FIFO must be located in the s6 service directory, and must be named, owned by root, and have permissions 0600 (i.e. the output of should display  ) to restrict unprivileged users from shutting down the machine. The service directory generated by satisfies all these conditions.

For further information about, please consult the HTML documentation in the package's subdirectory. copies the files named and  from a directory that can be specified with the   option, to the  subdirectory of its generated directory as the shutdown and final shutdown files. If no  option is specified, directory  is used on Gentoo. The package installs example shutdown and final shutdown files in, that are shell scripts containing only comments.

Aspects of the shutdown service that can be customized via options are:
 * The pathname of 's base directory: . Default:.
 * (version 1.0.4.0 and later) Whether a catch-all logger is being used: . If this option is specified,  does not give special treatment to the service directory named  during the shutdown sequence. Otherwise, this directory is assumed to be that of the catch-all logger, and  does not attempt to rename it and stop the service during the shutdown sequence.
 * The default grace period: . Default: 3 seconds. If this option is specified, it must be followed by a time value in milliseconds. Any value greater than 5 minutes is treated as.

The  and   options, if specified, are passed as-is to  (via the generated  script in the s6 service directory). The  option is converted to a   option with the same value and also passed to. checks that the pathname specified after option  is absolute.

The diverted signal handlers
The diverted signal handlers generated by  are execline scripts that make the init system react to signals sent to process 1. The effect of diverted signals is:
 * : does nothing.
 * : does nothing.
 * : reboots the machine using an command.
 * : does nothing.
 * : powers off the machine using an command.
 * : halts the machine using an command.
 * (version 1.0.4.0 and later) : powers off the machine using an  command.
 * (version 1.0.4.0 and later) : does nothing.

Runlevels
s6-linux-init allows the implementation of runlevel-like functionality similar to that of sysvinit. An s6-linux-init runlevel normally represents a service set, and entering a runlevel normally means to start all services in the corresponding set, and stopping all services not in it. Each runlevel has an alphanumerical identifier. The package uses two components to implement runlevels: the program, and the runlevel changer service.

What happens exactly when a runlevel is entered is defined by a runlevel changer file that must be provided by the user. The runlevel changer service generated by expects this file to be an executable file named, and located in the  subdirectory of the service's base directory. It is normally an execline or shell script that relies on some service manager to actually perform the necessary service transitions.

The program accepts a runlevel identifier as its argument, and uses an s6-sudo -e -T 3600000 command to connect to the runlevel changer service's  socket (absolute pathname  on Gentoo), and pass the identifier to it. The  option avoids passing variables from 's enviromnent to the the  script, and the   option prevents it from running for more than an hour. The service then executes the runlevel changer file with the received identifier as its argument.

For compatibility with sysvinit, if is invoked with 0 or 6 as the runlevel identifier, after passing it to the runlevel changer and waiting for the changer file to terminate, it uses an s6-linux-init-hpr -h or s6-linux-init-hpr -p command, respectively, to initiate machine shutdown.

Integration of with OpenRC can be achieved by having the script execute the  program when invoked. In this case, s6-linux-init runlevels are OpenRC runlevels.

For further information about, please consult the HTML documentation in the package's subdirectory.

copies the file named from a directory that can be specified with the   option, to the  subdirectory of its generated directory as the runlevel changer file. If no  option is specified, directory  is used on Gentoo. The package installs an example runlevel changer file in, that is a shell script containing only comments that illustrate integration with both OpenRC and s6-rc.

s6-rc support
See here.

Shutdown and reboot
s6-linux-init provides the and  programs, that can be used in combination with the init system components generated by  to shut down the machine. The former conforms to the LSB shutdown interface, modeled after sysvinit's , and the latter provide equivalent functionality to that of sysvinit's , and.

s6-linux-init-shutdown
accepts a time specification, an optional message to be shown to logged in users, and the  (halt after shutdown),   (reboot after shutdown),   (cancel shutdown),   (do not really shutdown; only warn),   (grace period between   and  ) and   (access control) options, with the same meaning as for sysvinit's. For compatibility with the LSB, it accepts  (ask the rc subsystem to skip checking filesystems with  after next boot) and   (ask the rc subsystem to make  check filesystems after next boot, even if they are marked clean) options, that it ignores. It also accepts  (halt),   and   (poweroff) options, that combine with   according to the following table:

Unless it was invoked with the  option,  connects to the shutdown service's FIFO and sends a shutdown request, or shutdown cancellation request if the   option has been specified, to. If no,  ,   or   option was specified, it sends a special 'S' shutdown request, that only makes  execute the shutdown script, but not actually shut down the machine. This allows the implementation of a behaviour that is similar to sysvinit's single user mode.

If it was invoked with the  option,  performs access control using file  just like sysvinit's. POSIX,   and   calls are used to read user process records (i.e.   objects with  ) from the user accounting database ( for GNU libc), and their   user field is matched against account usernames in. If the duration of the grace time specified with the  option is greater that 5 seconds, it is capped to that value.

For further information about, please consult the HTML documentation in the package's subdirectory.

s6-linux-init-hpr
must be invoked either with an  option, a   option, or an   option, to halt, poweroff, or reboot the machine, respectively. Without other options, it first writes a shutdown record to the user accounting log file ( for GNU libc), using the libc's  function. Then, it prints a warning about the system going down to logged in users. And finally, it sends a shutdown request to, specifying that machine shutdown should be initiated immediately. That is, s6-linux-init-hpr -h is equivalent to s6-linux-init-shutdown -h now, s6-linux-init-hpr -p , to s6-linux-init-shutdown -p now , and s6-linux-init-hpr -r , to s6-linux-init-shutdown -r now.

The shutdown record is a runlevel record (i.e. a  object with  ) that has   set to "shutdown" (or "reboot" if  was invoked with the   option),   set to the empty string,   set to "~",   set to 's process ID,   set to 's session ID (as returned by a POSIX   call),   set to the current time, and   set to the name returned by the POSIX   call (or the empty string if the call fails).

If is invoked with a   (capital 'w') option, it does not print the warning to logged in users. And, just like sysvinit's, and , if it is invoked with a   (small 'w') option, it only writes the shutdown record to the user accounting log file, without actually shutting down the machine, and if it is invoked with a   option, no shutdown record is written to the user accounting log file.

If is invoked with an   (force) option, it syncs all disks, flushing all the dirty system buffers, using the POSIX   call, and directly performs the shutdown action requested by the ,   or   option, using the Linux   system call. No shutdown record is written to the user accounting log file, no warning is printed a to logged in users, and options,   and   are ignored. If is also invoked with an   option, the syncing of disks is skipped.

For further information about, please consult the HTML documentation in the package's subdirectory.

sysvinit compatibility scripts
creates the following execline scripts in the subdirectory of its generated directory:
 * , which calls the program with at least the   (base directory) and   (file mode creation mask) options.
 * , which calls the program with the   option (halt) and all the supplied arguments.
 * , which calls the program with the   option (poweroff) and all the supplied arguments.
 * , which calls the program with the   option (reboot) and all the supplied arguments.
 * , which calls the program with all the supplied arguments.
 * , which calls the program with all the supplied arguments.

These compatibility scripts are provided as replacements of the sysvinit programs of the same name in pure s6-based setups, and are installed by the Gentoo ebuild in if the   USE flag is set. On Gentoo, however, this does not allow having both and sys-apps/s6-linux-init installed, and therefore, switching between init systems with a reboot. In fact, installing sys-apps/s6-linux-init with this USE flag set on a machine with sys-apps/openrc installed, or with with   also set, results in a blocker. So generally sys-apps/s6-linux-init should be installed with this USE flag unset. The subdirectory of 's generated directory could be copied to  using, for example,, and then scripts could be run using absolute pathname ${script_name} (replacing ${script_name} with the actual the script name).

Support programs
s6-linux-init provides two support programs for init system components created by.

The program is used by 's  and  files for printing messages, and is an exact duplicate of  from. Its inclusion in s6-linux-init avoids creating a runtime dependency on that package.

The program is used by the  execline script created by the shutdown daemon, and it unmounts all filesystems, processing  in reverse order, starting with the most recently mounted partition and ending with the rootfs. It behaves in a similar way to that of the program from  when the   option is specified. Its inclusion in s6-linux-init again avoids creating a runtime dependency on that package. For s6-linux-init version 1.0.3.0 and later, skips the unmounting of the first instance of a devtmpfs, sysfs and proc filesystem it finds in, which would usually correspond to ,  and , respectively, so that they are available for the final shutdown file,.

Historical notes
Before version 1.0.0.0, the s6-linux-init package could be used to create an s6 and s6-rc-based init system with a different design, see here for a summary. accepted a different set of options that the one described in this article, and its generated directory had a different structure. That design has been deprecated by the release of version 1.0.0.0, and became unsupported with upstream's release of version 2.10.0.0 of the s6 package.

Unmerge
If s6-linux-init's programs and components generated by are being used as the init system, an alternative one must be installed in parallel, and the machine rebooted to use it (possibly by reconfiguring the bootloader), before the package is removed, or otherwise the machine will become unbootable.

External resources

 * Adélie Linux, a distribution of Linux and musl that supports using s6-linux-init + OpenRC as its init system, as an alternative to sysvinit + OpenRC (currently in beta stage).