s6 is a process supervision suite that also provides tools for service management (s6-rc) and system initialization/shutdown (s6-linux-init).
s6 software is all designed to be very modular and can be mixed and matched with other things. However, s6 software is also designed to work well with one another. In Artix, we take full advantage of what s6 offers and use all of the available tools to provide an /sbin/init, PID1, process supervisor suite, and service manager for users.
s6-linux-init is what actually initiates your system. It mounts a tmpfs onto
/run and copies the
/etc/s6/current/run-image directory into
/sbin/init then execs into the
s6-svscan program (provided by
s6) which functions as your PID1 for the lifetime of the machine. Once this is done, the stage 1 part of init is finished. In addition to being PID1,
s6-svscan is also the root of your process supervision tree. It monitors every service found and appropriately spawns an
s6-supervise for every service.
Additionally, during bootup the
rc.init script in the
/etc/s6/current/scripts directory gets executed.
s6 itself does not do service management, but only process supervision. In
rc.init, the actual service manager,
s6-rc is started. From that point, we launch the default runlevel defined by
s6-rc and begin the desired services.
On shutdown, every service in s6-rc is brought down, followed by killing all
s6-supervise processes and other processes, then unmounting everything, and finally killing
s6-linux-init on artix is compiled with the option to print messages to
/dev/console. By default, this is tty1. You can change
/dev/console to another location using a kernel parameter (see your bootloader's configuration) if you'd like.
s6 service packages are named
package_name-s6 and, when installed, will be available in
The s6 software suite comes with many different binaries, but in general you only need to directly interact with a small subset of them.
s6-rc- the main program for controlling and managing services
s6-rc-bundle- adding and deleting bundles without having to recompile the live database
s6-rc-bundle-update- helper script for removing and adding services to existing bundles
s6-rc-db- a tool for analyzing a compiled service database
Most of the files associated with the s6 software packages are installed in the
/etc/s6/current- the base directory for s6-linux-init
/etc/s6/current/scripts- Various startup/shutdown scripts executed by s6-linux-init
/etc/s6/rc- where compiled databases are stored; the current live database is always symlinked to
/etc/s6/rc.local- file for executing arbitrary shell commands on bootup (any shell scripts in /etc/local.d suffixed with *.start are executed on bootup and those with *.stop are executed on shutdown)
/etc/s6/s6.conf- a global s6 config file for setting certain values for startup s6-rc services
/etc/s6/skel- Contains the default startup/shutdown scripts that come with artix linux
/etc/s6/sv- the directory containing s6-rc source definitions
A key concept to using s6-rc is to understand the notion of "bundles." You can take their namesake literally. A bundle in s6-rc is any collection of services, oneshots, and even other bundles. These are quite similar to openrc's runlevels and are used in similar ways in Artix. The package,
s6-scripts, which contains essential startup oneshots and daemons for an Artix system internally uses many different bundles for convenience, but for users the main bundle they should concern themselves with is the
default bundle. This is started by s6-rc and in general users will want to add their services to this bundle.
Note: There is a bundle within
boot. This is a collection of startup/shutdown boot oneshots and daemons deemed essential for a working system. These are mostly provided by the
s6-scripts package with some optional dependencies that install themselves into the directory. If you are creating your own special bundles/runlevels, you may want to include
boot in there.
There are two kinds of bundles in s6-rc: those already defined in the source directories and live bundles.
default are defined in
/etc/s6/sv. They will always be created whenever an s6-rc database is generated. However, s6-rc allows you define a bundle on the fly without creating any sources directories via the
s6-rc-bundle tool. To create and add services to the default bundle, you can do the following:
# s6-rc-bundle add bundlename service1 service2 service3 etc.
To modify an already existing bundle, you can use the
s6-rc-bundle-update helper script. To add something to an existing bundle you can just execute:
# s6-rc-bundle-update add default service. To remove something from an existing bundle, do
# s6-rc-bundle-update delete default service4. To completely remove a bundle, you use the regular
s6-rc-bundle command like so:
# s6-rc-bundle delete bundlename.
Note: the *-s6 packages in Artix that are an optional dependency of s6-scripts install themselves inside the boot bundle. They do not need to be enabled manually or added to any other bundle.
Also note that s6-rc manages dependencies so it is not necessary to manually start all needed dependencies. When service
foo is started, all of its dependencies (if they are not already up) are automatically started. Here are some handy commands.
# s6-rc -d change service_name
# s6-rc -u change service_name
# s6-rc -a list
# s6-rc-db list all
Because s6-rc uses a database format, all *-s6 packages in Artix execute a libalpm hook ensuring that all newly installed scripts are immediately available in a new database. This consists of 3 main steps. First, it compiles a new database with a unique name generated by the
date command with
s6-rc-compile. Then, it executes
s6-rc-update to update the live database to the newly compiled database. Finally, it atomically updates the symlink to
/etc/s6/rc/compiled so on the next boot, the system executes the newest database. Additionally, there is logic to preserve bundles created with the
s6-rc-bundle command and recreate them in the new database (otherwise, users would have to manually recreate them).
Note that this will leave behind old database directories in
/etc/s6/rc. Feel free to remove them if they are not needed. If you wish to add your own services to
/etc/s6/sv, it is probably best to simply execute the libalpm hook manually
# sh /usr/share/libalpm/scripts/s6-rc-db-update-hook so all of the above boilerplate is handled for you.
s6-rc has three types of services: longrun, oneshot, and bundle. Most *-s6 packages are longrun services (AKA daemons). Oneshot services do exactly what their name implies: execute once on bootup and optionally on shutdown. Bundles are simply a collection of longruns, oneshots, and even other bundles. Every source directory will have a mandatory
type file that contains a single line defining what type the service is. Longrun services must contain a file called
run, oneshots must contain a file called
up, and bundles must contain a file called
In Artix, a typical service script comes with two different parts: the daemon itself and the logger daemon that uses the
s6-log tool. The scripts for the actual service
foo will be installed in the
/etc/s6/sv directory as
foo-srv. Additionally, a small logger daemon for that specific service will be installed in
foo-log will catch any output from
foo-srv and save it in
/var/log/foo directory. The
s6-log logger daemon is run as the
s6log user and group. To give a user permission to view logs, just add him to the
s6-log does log rotation for you and has many different configurable options.
When interacting with s6-rc, the name of
foo doesn't change (i.e. you still do
# s6-rc -u change foo). This starts both
foo-log and handles any of the dependencies for you.
This is a tree of a longrun directory structure (aka
/etc/s6/sv/foo-srv). In many scripts, only
foo-srv ├── conf (optional) ├── dependencies (optional) ├── notification-fd (optional) ├── producer-for (required for foo-log) ├── run └── type
A tree for a logger daemon longrun (aka
/etc/s6/sv/foo-log) looks like this.
foo-log ├── conf (s6-log directive options) ├── consumer-for ├── notification-fd ├── pipeline-line ├── run └── type