This layer introduces s6-rc as init system.
git clone git://git.yoctoproject.org/poky
(cd poky && git checkout -b kirkstone origin/kirkstone)
git clone https://github.com/chris2511/meta-s6-rc.git
. poky/oe-init-build-env
bitbake-layers add-layer ../meta-s6-rc
TCLIBC = "musl" INIT_MANAGER = "s6" bitbake core-image-minimal
runqemu serialstdio nographic kvm
Or as usual put them into your conf/local.conf:
TCLIBC = "musl"
INIT_MANAGER = "s6"
The S6 system itself is thoroughly documented by its author.
This layer adds the s6rc.bbclass
, which allows to easily
create new services with dependencies. It populates the
/etc/s6-rc/tree
directory with services declared by the following
variables:
- S6RC_BUNDLES, S6RC_BUNDLE_% and S6RC_BUNDLE_%[ ]
- S6RC_ONESHOTS and S6RC_ONESHOT_%[ ]
- S6RC_LONGRUNS and S6RC_LONGRUN_%[ ] S6RC_LONGRUN_%_log[ ]
- S6RC_INITD_SYMLINKS
s6-init.bb
shows how to use them in practice.
Please read/know about the concepts documented in
s6-rc-compile
The S6RC_INITD_SYMLINKS variable declares a space separated
list of service names that will be put as symlinks to s6-startstop
to /etc/init.d/
. This enables SysV/Systemd feeling by providing:
/etc/init.d/<service> [start|stop|restart|enable|disable|status|pid| crashes|logs|logf]
The S6RC_DEBUG_BOOT variable set to anything != "" allows to debug
the boot sequence by setting the option -1
when calling
s6-linux-init-maker
S6RC_BUNDLES
contains a space separated list of bundle-names.
Each S6RC_BUNDLE_%
with % replaced by a bundle name contains a space separated
list of services and bundles that will be written to the
contents
file of the bundle.
Example:
S6RC_BUNDLES = "bundleA bundleB"
S6RC_BUNDLE_bundleA = "service1 service2"
S6RC_BUNDLE_bundleB = "svcx svcy bundleA"
will result in
/etc/s6-rc/tree/bundleA/type (which contains 'bundle')
/etc/s6-rc/tree/bundleA/contents (which contains 'service1\nservice2')
/etc/s6-rc/tree/bundleB/type (which contains 'bundle')
/etc/s6-rc/tree/bundleB/contents (which contains 'svx\nsvy\nbundleA')
Adding bundles, oneshots and longruns to bundles defined in other recipes,
for example the default
bundle, can be achieved by the
S6RC_[LONGRUN|ONESHOT|BUNDLE]_<name>[bundles]
variable.
Adding the longrun dropbear
to the default
and network
bundle
is done by
S6RC_LONGRUN_dropbear[bundles] = "default networking"
Non-existing bundles will be created on-the-fly.
All regular files recognized by s6-rc-compile can either be directly
added as S6RC_ONESHOT_runner-a[dependencies] = "runner-b bundle-x"
or provided as <service-name>.<property>
file.
In this example a runner-a.dependencies
will be used as runner-a/dependencies file verbatim.
This is especially useful for up
and run
files, which may become lengthy
and cumbersome to write in one line.
All atomic services may additionally contain the special file influences
which is the inverse of dependencies
:
All atomics listed in influences
of an other atomic
will depend on the other atomic.
S6RC_ONESHOTS
contains a space separated list of oneshot-names.
S6RC_ONESHOT_%[ ]
declares properties with % replaced by a oneshot-name
Properties for oneshots are those documented in the s6-rc-compile:
Example:
S6RC_ONESHOTS = "start mount-procsysdev networking"
S6RC_ONESHOT_start[up] = 'echo "init-stage2 starting."'
S6RC_ONESHOT_mount-procsysdev[dependencies] = "start"
will result in
/etc/s6-rc/tree/start/type (which contains 'oneshot')
/etc/s6-rc/tree/start/up (which contains 'echo "init-stage2 starting."')
/etc/s6-rc/tree/mount-procsysdev/type (which contains 'oneshot')
/etc/s6-rc/tree/mount-procsysdev/dependencies (which contains 'start')
An existing file ${S}/mount-procsysdev.up
will be copied verbatim to
/etc/s6-rc/tree/mount-procsysdev/up
S6RC_LONGRUNS
contains a space separated list of longrun-names.
S6RC_LONGRUN_%[ ]
declares properties with % replaced by a longrun-name
The functionality and behavior is analog to the oneshots, just with the
longrun properties.
The producer-for
and consumer-for
entries don't have to appear pairwise.
The s6rc class will resolve missing entries as it does with the influences
entry as the reverse of depends
.
This allows to declare dependencies unidirectional if depending services are
declared in different layers.
Longruns may have an additional verb filedescriptors
, which is an execline
script, creating filedescriptors via piperw
or s6-tcpserver-socketbinder
and storing them in the new fd-holder service called fdstore
. It canm be
done as usual as inline declaration or by a <longrun>.filedescriptors
file with s6-fdholder-store /service/fdstore/s [socket|write|read]:<name>
.
The all-in-one logger of templates also uses this mechanism.
The oneshot fdstore-fill
executes all filedescriptors
scripts.
Longruns using this mechanisms must depend on the fdstorage
bundle
to be sure the descriptors are ready. This is automatically done by the
s6rc.bbclass
A log service will always be setup, unless S6RC_LONGRUN_%[no-log]
exists. S6RC_LONGRUN_%_log[]
properties are evaluated
with the following property files:
- name:
<longrun-name>-log
- notification-fd: 3
- consumer-for:
<longrun-name>
- dependencies: mount-temp
- run:
umask {umask} s6-setuidgid {user} s6-log -d3 {script} {dir}
with {...} replaced by overrideable defaults:- umask: 0037
- user: logger
- script:
T s100000 n10
- dir:
/var/log/<longrun-name>
All properties can be overwritten (and not extended) by an explicit
value. For example: S6RC_LONGRUN_%_log[dependencies] = "mount-temp other"
Example:
S6RC_LONGRUNS = "getty syslogd"
S6RC_LONGRUN_getty[run] = "fdmove -c 2 1 /sbin/getty -L 0 console 2>&1"
S6RC_LONGRUN_getty[dependencies] = "mount-procsysdev hostname"
S6RC_LONGRUN_getty[down-signal] = "9"
S6RC_LONGRUN_syslogd[dependencies] = "mount-procsysdev"
S6RC_LONGRUN_syslogd[notification-fd] = "3"
S6RC_LONGRUN_syslogd_log[user] = "logger"
The syslogd/run
file is expected to be found in "${S}/syslogd.run"
S6RC_TEMPLATES
contains a space separated list of templates that
can be instantiated by the rc-dynamic command.
S6RC_TEMPLATE_%[ ]
declares service properties with % replaced by a template-name.
A run script is mandatory
A log service will be setup if S6RC_TEMPLATE_%_log[mode]
exists and contains a valid value. For template services, there are two log modes available "all-in-one" and "per-instance".
With all-in-one
a single log file service will be setup that can be used to collect the log entries of all service instances. For this to work, the log service stores a file descriptor in the s6-fdholder service fdstore
that must be retrieved by each service instance.
The file descriptor can be retrieved with s6-fdholder-retrieve /service/fdstore/s write:${TEMPLATE}-log
. See also Filedescriptor storage.
When instantiating templates inside a Oneshot
The mode per-instance
creates a minimal log service for each service instance. Stdout will be automatically forwarded to this log service.
After manually modifying the /etc/s6-rc/tree
the rc-recompile script
will do the s6-rc-compile, s6-rc-update, symlink
magic
as proposed in Managing compiled databases
just that rc-recompile
toggles between "compiledA" and "compiledB"
usage: rc-config [enable|disable] <serviceX|oneshotY|bundleZ>
Adds or removes the given services, oneshots and bundles
to the default
bundle, which is the default bundle when booting.
It first modifies the source tree in /etc/s6-rc/tree/default/contents
,
then adds or removes it to the compiled database by
s6-rc-bundle -f add default ...
and finally updates the live state by s6-rc -up -v2 change default
.
usage `rc-dynamic [setup|teardown]
Create an instance from an S6RC_TEMPLATE. The name of the dynamic service is instance@template The template from the directory /etc/s6-rc/templates/ is copied with the whole service name to /run/service. An envfile called env/instance is created inside the service with 2 variables:
- INSTANCE="<instance-name>"
- TEMPLATE="<template-name>"
The run and finish scripts may source it or the execlie way: envfile env/instance it and use the INSTANCE variable name for starting this specific instance. An optional executable file in the template: data/check-instance may be used to validate the instance name. It will be called with the instance-name as argument and must exit 0 if the instance is valid. If it exits non-zero, the instance creation fails.
The script /etc/init.d/s6-startstop
is never called directly, but called
via a symlink, which determines the service to act on.
It provides the following subcommands:
- enable: permanently enable and start the service
- disable: permanently stop and disable the service
- start: temporarily start the service and all its dependencies until reboot. After a reboot it returns to the enabled/disabled state
- stop: temporarily stop the service and all its dependencies until reboot. After a reboot it returns to the enabled/disabled state
- restart: same as start, but terminates the service if it is already running.
- status: prints the
s6-svstat
output - pid: prints the pid of the service
- crashes: prints the death tally of the service
- logs: prints the complete log
- logf: does a tail -f of the last logs