Running svscan on Linux

by Rob Mayoff

svscan is a program in the daemontools package. The program starts instances of supervise and restarts them when they die.

The daemontools author, Dan Bernstein, provides the svscanboot shell script to start svscan at boot time. Here is the contents of svscanboot as of version 0.76 of daemontools:

#!/bin/sh
# WARNING: This file was auto-generated. Do not edit!

PATH=/command:/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin

exec </dev/null
exec >/dev/null
exec 2>/dev/null

/command/svc -dx /service/* /service/*/log

env - PATH=$PATH svscan /service 2>&1 | \
env - PATH=$PATH readproctitle service errors: ................................................................................................................................................................................................................................................................................................................................................................................................................

I use a different shell script to start svscan on my Linux systems. Here is my script, which I call rc.svscan:

#!/bin/sh

PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin

exec 0</dev/null 1>/dev/null 2>/dev/null

svc -dx /service/* /service/*/log

ln -fs /proc/$$/cmdline /var/log/svscan

exec csh -cf '
    exec env - PATH="$PATH" svscan /service |& \
    exec env - PATH="$PATH" argv0 readproctitle "service errors:\
" ................................................................................................................................................................................................................................................................................................................................................................................................................'

The big advantage of rc.svscan's use of csh is that the csh program running the script will replace itself with readproctitle (something that bash, ash, and the traditional Bourne shell cannot do). This means that readproctitle will have the same PID as the rc.svscan script that starts it.

If we use svscanboot to start the svscan/readproctitle pipeline, and we want to look at the "service errors" (the output from svscan and its supervise children), then we have to find the PID of readproctitle. Typically this means running something like this:

ps ax | grep readproctitle | grep 'service errors:'

Once we have the PID, we can cat /proc/PID/cmdline to see the service errors. But on a large system, ps can take a while to run, and some joker could run another copy of readproctitle that fools our grep commands.

When rc.svscan runs, it knows that readproctitle will have the same PID as the script itself. It uses that knowledge to make /var/log/svscan a symlink to /proc/PID/cmdline. So if we use rc.svscan to start svscan and readproctitle, then we never need to look up the PID of readproctitle. We can simply cat /var/log/svscan at any time to see the service errors.

Another change in rc.svscan from svscanboot is the use of the argv0 program from the ucspi-tcp package. rc.svscan uses it to set readproctitle's argv[0] to "service errors:" followed by a newline. This way, when we cat /var/log/svscan, the word readproctitle does not show up in the output, and the label "service errors:" appears on a separate line from the actual service errors.

mayoff@dqd.com