svsh is a command line shell for process supervision suites of the daemontools family. Currently, it supports daemontools, perp, s6 and runit. It provides a unified interface allowing easy inspection and manipulation of services (i.e. processes) managed by these supervisors.
svsh is not a supervisor in itself, but an external tool for interacting with existing process supervision suites. If you are unfamiliar with these suites, here's the gist: they manage a set of processes, making sure they are all up, and attempt to bring them up if they ever go down. Some of them are designed to run as a system's init process, i.e. process 1, thus providing an alternative to System V, systemd and others. They all provide a set of command line utilities that allow to launch processes in certain ways (such as with resouce limits), and to manipulate them once running. They are considered a "family", since they provide mostly the same utilities, and their configuration is mostly compatible. They are different from other inits and supervisors (like supervisord), not only in this structure, but in other key respects. An excellent overview of supervision suites and differences from traditional supervisors are posted on the s6 website.
With svsh, it is easy to get a complete view of your processes and their statuses. You can bring processes up, down, send them signals and view their output in real time. You don't need to remember the particular syntax of the control tools provided by your suite. Instead, you get a natural syntax that's easy to remember. Why execute perpctl -b /services q nginx
when you can just type restart nginx
?
svsh is written in Perl and currently targets UNIX-like operating systems that use procfs.
svsh releases are hosted in CPAN and can be installed like any other Perl module.
$ cpanm -S Svsh
$ cpan Svsh
Download the tarball, extract it, and build with:
$ perl Makefile.PL
$ make && make test
$ sudo make install
svsh is ready to rock right out of the box. No configuration or changes to your service directories are needed. Simply point it to your base directory (the directory from which your supervisor is running), and you instantly get a usable shell:
$ svsh --suite runit --basedir /etc/services
Once started, you get a list of all managed services, including their statuses, uptime or downtime durations, and process IDs.
process | status | duration | pid haproxy | up | 126s | 28444 nginx | down | 12s | - worker-1 | up | 126s | 28438 worker-2 | up | 126s | 28443 worker-3 | up | 55s | 28437 svsh>
The following commands are then available:
status | Prints an updated list of service statuses. |
---|---|
start | Starts a list of services, if they are not already up.svsh> start nginx haproxy |
stop | Stops a list of services, if they are not already down. They will not be restarted.svsh> stop nginx |
restart | Restarts a list of services. Most supervisors implement this with a QUIT signal.svsh> restart worker* |
signal | Sends a UNIX signal to a list of services. Not all signals are supported by all supervisors.svsh> signal hup nginx |
fg | Moves a service to the foreground, so that its output is followed on screen.svsh> fg worker-2 |
toggle | Toggles an svsh option. See list of options.svsh> toggle collapse |
The following commands are implemented by some supervisors:
rescan / update | Causes the supervisor to rescan the base directory for new or removed services. |
---|---|
terminate / shutdown | Terminates the supervisor and all services. |
All of the supported supervision suites do not enforce a logging scheme on managed services. While all of them provide a logging tool (daemontools provides multilog, perp provides tinylog and sissylog; s6 provides s6-log; runit provides svlogd), none of them enforce their usage. It is actually not uncommon among users of these suites to use a logging tool provided by one suite for services managed by another one. This means it is hard for an external program such as svsh to determine where log files are stored, if at all.
Currently, svsh will attempt to find the log file of a service by checking the pid of the associated log process, and if (and only if) that process is one of the supported loggers (multilog, tinylog, s6-log or svlogd), it will try to find the file descriptor used by that process under /proc/<pid>/fd. As long as your services are being logged by one of these tools, svsh should be able to tail their log files when the fg command is used.
svsh provides bash-like history so you can use your up arrow key to cycle back through past commands, or use Ctrl+R to search your history. The history file is saved under ~/.svsh_history.
Also, autocompletion is provided for all commands. Tap the tab key at any moment while typing in commands and arguments, and svsh will attempt to autocomplete your current word, or display a list if multiple options are available.
For this to work best, it is recommended to install Term::ReadLine::Gnu.
svsh makes it easy to manipulate multiple services at once. Wildcards are supported
by the start
, stop
, restart
and signal
commands. If, for example, you have
several services whose names start with "worker", you can stop them all by executing
stop worker*
. Wildcards are also supported at the beginning of the name, so
signal term *d
will send a TERM signal to all services whose names end with "d".
svsh> status process | status | duration | pid worker-1 | up | 9813s | 25984 worker-2 | up | 9813s | 25976 worker-3 | up | 4393s | 2990 svsh> stop worker* svsh> status process | status | duration | pid worker-1 | down | 2s | - worker-2 | down | 2s | - worker-3 | down | 2s | -
Often times you would like to run a certain service with X number of identical processes.
None of the supervision suites have any mechanism to allow this (none that I
know of at least), apart from creating identical copies of a service directory for every
process needed. While svsh can't help you with that, it provides a nice feature for collapsing
these identical services in the output of the status
command to just one line. This can
be very useful with lots of multi-process services.
Currently, svsh determines multi-process services if their names are postfixed with a dash
and a number. For example, if you have a service called "worker" that you need 3 processes
of which to run, you can create "worker-1", "worker-2" and "worker-3" service directories.
If the collapse
option is on, svsh will collapse all of these into
just one line, under the name status.
svsh> status process | status | duration | pid worker-1 | up | 9813s | 25984 worker-2 | up | 9813s | 25976 worker-3 | up | 4393s | 2990 svsh> toggle collapse process | status | duration | pid worker | 3 up | 9850s | -