s6-rc
Software
skarnet.org

The s6-rc-compile program

s6-rc-compile is a service database compiler. It takes a series of service definitions in the source format, and compiles them into a directory, which is the compiled format.

The administrator can then examine that compiled database via s6-rc-db, put it into a place where it will be registered at boot time as the current compiled database by s6-rc-init, or even live update the current service database via s6-rc-update.

Interface

     s6-rc-compile [ -v verbosity ] [ -h fdhuser ]  [ -b ] compiled source...

Exit codes

Options

Source format

s6-rc-compile scans every source directory to find service definition directories in it. It ignores every file that is not a directory, or that starts with a dot. For every service definition directory that it finds, it creates a service with the same name as the directory. Names cannot be duplicated and cannot contain a slash or a newline; they can contain spaces and tabs, but using anything else than alphanumerical characters, underscores and dashes is discouraged - the s6-rc programs will handle weird names just fine, but other tools, especially shell scripts, may not. Names are also forbidden to use the reserved s6rc- and s6-rc- prefixes.

Every service definition directory service is expected to contain the following files:

For every service

For bundles

It is possible to use bundle names in a contents.d directory or a contents file. However, if s6-rc-compile detects a cycle in bundle definitions, it will complain and exit 1.

For atomic services

It is unnecessary to manually define complete sets of dependencies in the dependencies.d directory or the dependencies file, because s6-rc will properly handle dependency chains. If A depends on B, no matter the underlying implementation of B, and the current implementation of B depends on C, then you should just put B in A/dependencies.d; when starting the set, s6-rc will start C first, then B, then A. If the underlying implementation of B changes and does not depend on C, then you will just have to modify the dependencies for B, and the definition of A will still be correct.

Of course, if A depends on C anyway, you should add both B and C to A/dependencies.d.

If s6-rc-compile detects a cycle in dependencies across services, it will complain and exit 1.

For oneshots

up and down are interpreted by execlineb, but that does not mean they have to be entirely written in the execline language. The execlineb lexer is only used because it can compile a Unix command line from a text file and store the compiled result, whereas a shell would have to be invoked everytime the script is run. There are many ways to write up and down scripts:

Don't think you have to learn all the intricacies of the execline language just because the up and down scripts get lexed by it. You don't.

For longruns

The s6-rc service definition directory for a longrun service is similar to a s6 service directory, but there are a few differences:

The following files must or may appear in a longrun definition directory:

Be aware that service directories will be relocated, and copied at boot time, so if your run or finish scripts refer to files in the service directory (probably in the data or env subdirectories!), they should use relative paths, not absolute ones.

Note that you cannot create a ./down file for s6-supervise in a generated service directory. Even if such a file exists in the definition directory, it will be ignored - it will not be replicated in the service directory. This is intentional: s6-rc internally uses ./down files in the service directories it manages, to mark longrun services that are down.

The producer-for, consumer-for and pipeline-name files are used to set up automatic longrun pipelining.

Longrun pipelining

Users of supervision suites know about logged services: a service acts as a producer, and is coupled with another service, its logger; the supervision system automatically maintains an open pipe between the producer's stdout and the logger's stdin.

s6-rc comes with an extension of this mechanism. Rather than only allowing two longrun services to be pipelined, it can set up an indefinite number of longrun services this way.

s6-rc-compile will detect pipelines, and set up the service directories so that every producer's stdout is connected to its consumer's stdin, and that the pipes are not broken whenever one element in the chain dies.

A service can only be declared as a producer for one other service, but it can be declared as a consumer for several other services: the consumer-for can have several lines. This means that one service can only send its output to one consumer, but it can read its input from several producers. If there are several producers to a service, they will all write to the same Unix pipe that the service reads.

This means that what s6-rc calls pipelines are really funnels: you can collapse multiple data streams into a single data stream, at every step of your processing chain. The pipeline terminology remains for history reasons: previous versions of s6-rc could not handle multiple producers.

s6-rc-compile checks for pipeline consistency. It must see a producer-for file in the producers' definition that is consistent with the consumer-for file in the consumer's definition. It will detect and reject cycles as well as collisions.

The pipe linking a set of producers with a consumer is created and stored at run-time in a s6-fdholder-daemon instance managed by an automatically generated longrun service named s6rc-fdholder.

Compiled database usage

A complete example

The examples/source subdirectory of the s6-rc package contains a set of service definition directories, which is actually a working, valid set for a Linux system running busybox and the skarnet.org packages; of course, only the service definition set has been kept, and private information has been removed, so it won't work out-of-the-box without the proper specific files, notably configuration in /etc - but nevertheless, you can browse the source and understand what it does, and adapt it to your own needs. It will compile as is with s6-rc-compile, and you can examine the resulting compiled database with s6-rc-db.