s6
Software
www.skarnet.org
The s6-svscan program
s6-svscan starts and monitors a collection of s6-supervise
processes, each of these processes monitoring a single service. It is designed to be either
the root or a branch of a supervision tree.
Interface
s6-svscan [ -d notif ] [ -X consoleholder ] [ -c max ] [ -t rescan ] [ scandir ]
- If given a scandir argument, s6-svscan switches to it. Else it uses
its current directory as the scan directory.
- It exits 100 if another s6-svscan process is already monitoring this
scan directory.
- If the ./.s6-svscan control directory does not exist,
s6-svscan creates it. However, it is recommended to already have a .s6-svscan
subdirectory in your scan directory, because it is used to configure s6-svscan
operation, see below.
- From this point on, s6-svscan never dies. It tries its best to keep
control of what's happening. In case of a major system call failure, which means
that the kernel or hardware is broken in some fashion, it executes into the
.s6-svscan/crash program. (But if that execution fails, s6-svscan exits
111.)
- s6-svscan performs an initial scan of its scan directory.
- s6-svscan then occasionally runs scans or reaps,
see below.
- s6-svscan runs until it is told to stop via
s6-svscanctl, or an appropriate signal (see below).
Then it executes into the .s6-svscan/finish program, if present; if
not, it exits 0.
Options
- -d notif : notify readiness on file descriptor
notif. When s6-svscan is ready to accept commands from
s6-svscanctl, it will write a newline to notif.
notif cannot be lesser than 3. By default, no notification is sent. Please
note that using this option signals shallow readiness: s6-svscan being
"ready" only means that it is ready to accept commands. It does not mean
that all the services it launches at start are themselves ready, or even started, or
even that the relevant s6-supervise processes have
been started. If you need to test for deep readiness, meaning that all the
services in the supervision tree have been started and are ready, you cannot rely
on this option.
- -X consoleholder : assume the output console is available
on descriptor consoleholder. If this option is given, and a s6-svscan-log
service exists, the s6-supervise process for that service
will be run with consoleholder as its standard error. This is mainly useful
for a setup done via s6-linux-init,
where all error messages go to the s6-svscan-log catch-all logger service by
default, except messages from this service itself, which fall back to consoleholder.
If you're not sure what to use this option for, or how, you don't need it.
- -c max : maintain services for up to max
service directories. Default is 500. Lower limit is 2. There is no upper limit, but:
- The higher max is, the more stack memory s6-svscan will use,
approximately 50 bytes per service.
- s6-svscan uses 2 file descriptors per logged service.
It is the admin's responsibility to make sure that s6-svscan has enough available
descriptors to function properly and does not exceed its stack limit. The default
of 500 is safe and provides enough room for every reasonable system.
- -t rescan : perform a scan every rescan
milliseconds. If rescan is 0 (the default), automatic scans are never performed after
the first one and s6-svscan will only detect new services when told to via a
s6-svscanctl -a command. Use of this option is
discouraged; it should only be given to emulate the behaviour of other supervision
suites. (-t5000 for daemontools' svscan, -t14000 for runit's
runsvdir.)
Signals
s6-svscan has special handling for the following signals:
- SIGCHLD
- SIGALRM
- SIGABRT
- SIGHUP
- SIGINT
- SIGTERM
- SIGQUIT
- SIGUSR1
- SIGUSR2
- SIGPWR (on systems that support it)
- SIGWINCH (on systems that support it)
Signals that are not in the above list are not caught by s6-svscan and will
have the system's default effect.
The behaviour for the first three signals in the list is always fixed:
- SIGCHLD : trigger the reaper.
- SIGALRM : trigger the scanner.
- SIGABRT : immediately exec into .s6-svscan/finish (or exit 0 if that script does not exist), without waiting for any processes to die
The behaviour for the rest of the list is configurable: on receipt of a
SIGFOO,
s6-svscan will try to run an executable .s6-svscan/SIGFOO file. For
instance, a .s6-svscan/SIGTERM executable script will be run on receipt of
a SIGTERM. If the file cannot be found, or cannot be executed for any reason, the
default behaviour for the signal will be applied. Default behaviours are:
- SIGHUP : rescan and prune the supervision tree, i.e. make sure that new
service directories visible from the scan directory have a
s6-supervise process running on them, and instruct
s6-supervise processes running on service directories
that have become invisible from the scan directory to stop their service and exit.
This behaviour can also be achieved via the
s6-svscanctl -an scandir command. This is the closest that s6-svscan
can get to the traditional "reload your configuration" behaviour.
- SIGINT : same as SIGTERM below.
- SIGTERM : Instruct all the s6-supervise to
stop their service and exit; wait for the whole supervision tree to die, without
losing any logs; then exec into .s6-svscan/finish or exit 0. This behaviour
can also be achieved via the s6-svscanctl -t scandir command.
- SIGQUIT : same as SIGTERM above, except that if a service is logged
(i.e. there is a foo service and a foo/log service)
then the logging service will also be killed, instead of being allowed to exit
naturally after its producer has flushed its output and died. This can solve
problems with badly written logging programs, but it can also cause loss of logs
since the logger may die before the producer has finished flushing everything. The
behaviour can also be achieved via the s6-svscanctl -q scandir command;
you should only use this if SIGTERM/-t fails to properly tear down the
supervision tree.
- Others: no effect if an appropriate executable file in .s6-svscan/
cannot be run.
The reaper
Upon receipt of a SIGCHLD, or a s6-svscanctl -z
command, s6-svscan runs a reaper routine.
The reaper acknowledges (via some
wait()
function), without blocking, every terminated child of s6-svscan, even ones it does not
know it has. This is especially important when s6-svscan is
run as process 1.
If the dead child is a s6-supervise process watched
by s6-svscan, and the last scan flagged that process as active, then it is restarted
one second later.
The scanner
Upon receipt of a SIGALRM or a
s6-svscanctl -a command, s6-svscan runs a
scanner routine. (It also runs it every rescan milliseconds
if the -t option has been given.)
The scanner scans the current directory for subdirectories (or symbolic links
to directories), which must be service directories.
It skips names starting with dots. It will not create services for more than
max subdirectories.
For every new subdirectory dir it finds, the scanner spawns a
s6-supervise process on it. If
dir/log exists, it spawns an s6-supervise process on
both dir and dir/log, and maintains a
never-closing pipe from the service's stdout to the logger's stdin.
This is starting the service, with or without a corresponding
logger.
Every service the scanner finds is flagged as "active".
The scanner remembers the services it found. If a service has been
started in an earlier scan, but the current scan can't find the corresponding
directory, the service is then flagged as inactive. No command is sent
to stop inactive s6-supervise processes (unless the administrator
uses s6-svscanctl -n or a SIGHUP), but
inactive s6-supervise processes will not be restarted if they die.
Notes
- s6-svscan is designed to run until the machine is shut down. It is
also designed as a suitable candidate for
process 1. So, it goes out of its way to
stay alive, even in dire situations. When it encounters a fatal situation,
something it really cannot handle, it executes into .s6-svscan/crash
instead of dying; when it is told to exit, it executes into
.s6-svscan/finish. Administrators should make sure to design
appropriate crash and finish routines.
- s6-svscan is a fully asynchronous state machine. It will read and
process commands at any time, even when the computer is in trouble.
- s6-svscan does not use malloc(). That means it will never leak
memory. However, s6-svscan uses opendir(), and most opendir()
implementations internally use heap memory - so unfortunately, it's impossible
to guarantee that s6-svscan does not use heap memory at all.
- Unless run with a nonzero -t option, which is only a legacy
feature used to emulate other supervision suites such as daemontools or runit,
s6-svscan never polls; it only wakes up on notifications.
The s6 supervision tree can be used in energy-critical environments.