Skip to content

svscan.8

Manvendra Bhangui edited this page Apr 1, 2024 · 10 revisions

NAME

svscan - starts and monitors a collection of services

SYNOPSIS

svscan [ -vs ] [ dir ]

DESCRIPTION

svscan(8) starts one supervise(8) process for each subdirectory of the current directory, up to a limit of 1000 subdirectories. You can override using current directory by passing dir as an argument. If svscan(8) is given a command-line argument dir, it switches to that directory when it starts.

svscan(8) skips subdirectory names starting with dots. supervise(8) must be in svscan's path. svscan(8) calls setsid(2) to become a session leader if the environment variable SETSID is set. When running as a session leader, svscan will terminate process group if the environment vairable TERMINATE_SESSION is set. This will terminate all supervise proceses started by svscan by calling kill(0, 15).

svscan(8) optionally starts a pair of supervise(8) 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. svscan(8) needs two free descriptors for each pipe. The log supervise process additionally sets argv2 as s to easily locate the process in ps(1) output like below

root    1588    1528  0 May05 ?      00:00:00 supervise qmail-smtpd.25
root    1589    1528  0 May05 ?      00:00:00 supervise log qmail-smtpd.25

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 SERVICEDIR=dir on startup. If dir is omitted than it uses current working directory for the value of SERVICEDIR environment variable. svscan also sets the the environment variable PWD to dir. It then writes its pid to the file .svscan.pid in /run/svscan, /var/run/svscan (whichever is found first) or the directory dir if the system doesn't have a run tmpfs filesystem. The pid file is created exclusively and involves switching directories between the run filesystem and the dir directory. svscan(8) uses the pid file to prevent multiple copies of svscan(8) to run for the same directory. If DISABLE_RUN is set, svscan(8) will use dir instead of /run or //var/run. svscan(8) uses the /proc filesystem to verify if the pid belongs to a process named svscan, by opening the file /proc/pid/comm. svscan(8) 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(8), 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(8) process. If it sees an old subdirectory where a supervise(8) process has exited, it restarts the supervise(8) 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. If running as PID 1, svscan will automatically scan for new subdirectories when any of it's children or any orphaned process die.

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. svscan(8) will direct its stdout and stderr 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 5.1. Redirecting svscan output through multilog also provides a much better solution than other svscan startup scripts which direct output exclusively to console, causing 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.

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 immediately restart a supervise process if it dies, rather waiting for 60 (or SCANINTERVAL) seconds. This behaviour can be enabled as default by setting SCANNOW environment variable. Setting this variable enables a signal handler for SIGCHILD. If running as PID 1, svscan will relay SIGTERM to all children when it gets SIGTERM. By default, it will send SIGTERM twice - first immediately and second one after 30 secs followed by SIGKILL after another 30 secs. The default of 30 seconds 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 and SIGKILL after KILLWAIT secs. Setting KILLWAIT overrides KILLWAIT1 and KILLWAIT2.

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. INITCMD can be set to full path of an executable or 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 dir. 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

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. A typical example of a shutdown script looks like this. The -G argument to svc(8) sends signal to the entire process group of svscan.

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

The above can also be achieved by setting SETSID and 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. 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(8) is started through an entrypoint for docker/podman and starts as PID 1. This entrypoint is implemented using the docker-entrypoint(8) script.

OPTIONS

-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(8) 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(8) uses 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