Skip to content

svscan.8

Manvendra Bhangui edited this page Dec 13, 2024 · 15 revisions

NAME

svscan - start and monitor a collection of services

SYNOPSIS

svscan [ -vs ] [-n count] [ scandir ]

DESCRIPTION

svscan(8) starts one supervise(8) process for each subdirectory of the current directory, up to a limit of 1000 subdirectories as default. You can change the default by using -n count, in which case svscan will allocate memory for count service slots. You can override using current directory by passing scandir as an argument. If svscan is given a command-line argument dir, it switches to that directory when it starts.

svscan skips subdirectory names starting with dots. supervise must be in svscan's path. If the environment variable SETSID is set, svscan calls setsid(2) to become a session leader.

svscan optionally starts a pair of supervise processes, one for a subdirectory s, one for s/log, with a pipe between them. It does this if the name s is at most 255 bytes long and s/log exists. This makes any output on descriptor 1 of the supervised process s to be sent through the pipe to the supervise log process s/log. In this case the supervise process inherits only descriptor 2 from svscan. For every pipe it creates, svscan needs two free descriptors. Hence for n services with log subdir, svscan will require (**2 * **n + 3) descriptors. Make sure svscan has enough open file limit RLIMIT_NOFILE (see setrlimit(3), ulimit(1), softlimit(8), sysctl(8)). Without the log subdirectory, supervise inherits both descriptors 1 and 2 from svscan and hence standard open file limit will suffice for supervising large number of processes. The log supervise process additionally sets argv[2]=s to easily locate the process in ps(1) output like below

$ ps -ef | grep -E "svscan|supervise|COMMAND" | grep -E "svscan|qmail-smtpd|COMMAND"
    PID    PPID TT       USER     GROUP    COMMAND
 980727       1 ?        root     root     /usr/sbin/svscan /service
 980735  980727 ?        root     root     supervise qmail-smtpd.465
 980736  980727 ?        root     root     supervise log qmail-smtpd.465
 980741  980727 ?        root     root     supervise qmail-smtpd.25
 980742  980727 ?        root     root     supervise log qmail-smtpd.25
 980743  980727 ?        root     root     supervise qmail-smtpd.587
 980744  980727 ?        root     root     supervise log qmail-smtpd.587
 980747  980727 ?        root     root     supervise qmail-smtpd.366
 980749  980727 ?        root     root     supervise log qmail-smtpd.366

For every supervise log process it runs, svscan also sets SV_PWD=s as an environment variable. svscan also sets PPID environment variable as the process id of the parent for supervise proceses and any initialization command it runs.

svscan sets environment variable SCANDIR=scandir on startup. If scandir argument to svscan is omitted than it uses current working directory for the value of SCANDIR environment variable. svscan also sets the the environment variable PWD to scandir. It then writes its pid to the file .svscan.pid in /run/svscan, /var/run/svscan (whichever is found first) or the directory scandir if the system doesn't have a run tmpfs filesystem or if the environment variable DISABLE_RUN is set. The pid file is created exclusively. If the run directory is used, writing the pid file involves switching directories between the run filesystem and the scandir directory. svscan uses the pid file to prevent multiple copies of svscan to run for the same directory. If DISABLE_RUN is set, svscan will use scandir instead of /run or /var/run. If DISABLE_RUN is set, you can have an multiple invocation of svscan run for different scandir passed on the command line. svscan uses the /proc filesystem to verify if the pid belongs to a process named svscan, by opening the file /proc/pid/comm. svscan will start if the file does not exist, or if any process with pid pid does not exist, or if the pid belongs to a non-svscan process. The file .svscan.pid is deleted on SIGTERM.

After creating the pid file, svscan is designed to run forever. If it has trouble creating a pipe or running supervise, it prints a message to stderr; it will try again 60 seconds (or SCANINTERVAL environment variable if set) later. If the environment variable AUTOSCAN is set svscan checks for subdirectories again every 60 seconds. If it sees a new subdirectory, it starts a new supervise process. If it sees an old subdirectory where a supervise process has exited, it restarts the supervise process. In the log case it reuses the same pipe so that no data is lost. The default scan interval of 60 secs can be changed by setting SCANINTERVAL environment variable. You can also send a HUP signal to svscan to force a directory scan.

svscan can be run with a PID of 1 (init replacement) and reap child processes. This feature is exploited in docker/podman/kubernates environment. The INITCMD environment variable can be used to do service management. The biggest advantage of svscan is its simplicity. Unlike systemd(1), it is not complex and tied with multiple pieces of software to make it work. You can also use openrc from Gentoo to create a decent, simple service manager to start only the processes that you require.

If running as PID 1, svscan will automatically scan for new subdirectories when any of it's children or any orphaned process die. Hence, if running as PID 1, svscan will immediately restart a supervise process if it dies, rather waiting for 60 (or SCANINTERVAL) seconds. This behaviour can be enabled as default regardless of the PID of svscan by setting SCANNOW environment variable. Setting this variable enables a signal handler for SIGCHILD. If running as PID 1 or when TERMINATE_SESSION environment variable is set, svscan will relay SIGTERM to all children when it gets SIGTERM. It first sends SIGTERM to all non-log processes than waits for w1=2 seconds , followed by SIGTERM to all log processes and then wait for another w2=2 seconds. The default of 2 seconds for w1 and w2 can be changed by setting KILLWAIT1 and KILLWAIT2 environment variables. Instead of KILLWAIT1, KILLWAIT2 you can set KILLWAIT environment variable to have second SIGTERM after KILLWAIT/2 secs. You can also set KILLWAIT environment variable where w1 will be 0.5 * KILLWAIT seconds and w2 will be KILLWAIT seconds.

svscan can auto-start or auto-stop a service based on the presence or absence of s/down file. During each scan, svscan will automatically stop a running service if it finds s/down and the earlier status of the service was up. Similarly, svscan will automatically start a stopped service if it finds the file s/down missing and the earlier status of the service was down.

svscan output can be driven through multilog. If a directory (or symlink to a directory) named /service/.svscan exists and the environment variable SCANLOG is defined in /service/.svscan/variables, svscan will redirect its output on descriptors 1 and 2 to the supervised service run from the /service/.svscan/log directory. This simplifies svscan startup scripts and eliminates the use of readproctitle, which does not work on some platforms, e.g. FreeBSD. Redirecting svscan output through multilog also provides a much better solution than other svscan startup scripts which redirect output exclusively to console, which may cause problems to go undetected for a long time. The other big advantage of setting SCANLOG is that all supervise processes started by svscan (and also the children of supervise) inherit the descriptors 0, 1 and 2. Any output of these processes not redirected to a log file will get logged along with svscan log.

If INITCMD environment variable is defined and set to an empty string and if /service/.svscan/run exists and has the executable bit set, run is executed once during startup. INITCMD can be set to full path of an executable / script to override /service/.svscan/run. If WAIT_INITCMD environment variable is set, it will additionally wait for run to exit, before starting the scan of scandir. Typical use of INITCMD is to mount --bind /etc/indimail/resolv.conf as /etc/resolv.conf, to redirect all dns resolver requests, to locally running dnscache(8). A typical run script to exploit INITCMD is as below

#!/bin/sh
/usr/bin/mount --bind /etc/indimail/resolv.conf /etc/resolv.conf
/usr/bin/mount -l
if [ $PPID -eq 1 ] ; then
	openrc indimail
fi

As stated earlier, svscan can be made to terminate all supervise processes on SIGTERM when TERMINATE_SESSION environment variable is set. If /service/.svscan/shutdown exists, it will be executed when svscan receives a TERM signal. This can be used to terminate all supervise processes started by svscan without setting TERMINATE_SESION. A typical example of a shutdown script looks like below.

#!/bin/sh
exec 2>&1
/usr/bin/umount /etc/resolv.conf
/usr/bin/svc -dWx /service/*
/usr/bin/svc -dWx /service/*/log
/usr/bin/svc -dW /service/.svscan/log
/usr/bin/svc -dx /service/.svscan/log

You can pass -G argument to svc(8) to send signal to the entire process group of svscan.

The above can also be achieved by TERMINATE_SESSION environment variables as explained earlier.

On most Linux distros, svscan is started using a systemd(1) unit file /usr/lib/systemd/system/svscan.service. On FreeBSD, it is started using rc script in /usr/local/etc/rc.d/svscan. On Darwin, it is started by launchd(8) using /Library/LaunchDaemons/org.indimail.svscan.plist. On alpine linux, it is started by openrc using /etc/init.d/svscan when using the service(8) command. All of these use a wrapper named svscanboot(8) to start svscan. svscanboot uses envdir(8) to set environment variables from /service/.svscan/variables directory. Few examples of starting and stopping svscan are given below.

Linux
-----
sudo systemctl start/stop svscan
or
sudo systemctl start/stop indimail
or
sudo systemctl start/stop indimail-mta
or
sudo service svscan start/stop

FreeBSD
-------
sudo service svscan start/stop

Mac OSX
-------
sudo launchctl start/stop org.indimail.svscan

Universal
---------
sudo qmailctl start/stop

In a container environment, svscan is started through an entrypoint for docker/podman and starts as PID 1. This entrypoint is implemented using the docker-entrypoint(8) script in /usr/sbin.

OPTIONS

-n count
Allocate memory for count service slots. Without this option svscan will scan upto 1000 subdirectories in scandir.

-v
Display informational messages. Normally this is suppressed. You can toggle this by sending svscan USR1 signal. Setting this also sets VERBOSE environment variable, which gets inherited by all processes started by svscan. Informational messages can also be turned on by setting VERBOSE environment variable. Note that supervise uses VERBOSE environment variable.

-s
Suppress warning message. Normally this is printed on the standard error. You can toggle this by sending svscan USR2 signal. Setting this also sets SILENT environment variable, which gets inherited by all processes started by svscan. Warning messages can also be suppressed by setting SILENT environment variable. Note that supervise also uses the SILENT environment variable.

SEE ALSO

proc(5) mount(8) kill(2) setsid(2) supervise(8), svc(8), svok(8), svps(1), svstat(8), svctool(8), minisvc(8), svscanboot(8), readproctitle(8), fghack(8), pgrphack(8), multilog(8), tai64n(8), tai64nlocal(8), setuidgid(8), envuidgid(8), envdir(8), dnscache(8), softlimit(8), setlock(8), docker-entrypoint(8), systemctl(1) systemd(1) service(1) init(1) launchd(8) openrc-init(8) openrc-run(8) http://cr.yp.to/daemontools.html

Clone this wiki locally