Runit

Runit is daemontools-inspired process supervision suite that also provides a program suitable for running as process 1]]. It can be used as alternative to sysvinit or systemd, either by itself or in conjunction with OpenRC. It can also be used as a helper for supervising OpenRC services.

Environment variables

 * SVDIR - Directory will search for the services specified as arguments.
 * SVWAIT - Time will wait for a service to reach its desired state before timing out or killing it with a   signal.

Files

 * - Directory will search for the services specified as arguments if SVDIR is empty of unset.
 * - File will execute when the machine boots.
 * - File will execute and supervise when  exits.
 * - File will execute when the machine shuts down.
 * - File will execute when receiving a   signal.
 * - Used by to decide whether it should initiate machine shutdown when receiving a   signal or not.
 * - Used by to decide whether it should halt or reboot the machine.
 * - Symbolic link set by to 's current scan directory.
 * - Symbolic link set by to 's previous scan directory.
 * - 's initial scan directory when using.
 * - Service directory repository when using.
 * - 's scan directory when using.
 * - Service directory repository when using.
 * - 's scan directory when using OpenRC's runit integration feature.
 * - Symbolic link to 's scan directory when using.

OpenRC
See here.

Process supervision
For more in-depth information about the process supervision aspects of runit, see daemontools-encore. A summary follows.

The program that implements the supervisor features in runit is, and just like daemontools' , it takes the (absolute or relative to the working directory) pathname of a service directory (or servicedir) as an argument. A runit service directory must contain at least an executable file named, and can contain an optional, regular file named , and an optional subdirectory or symbolic link to directory named , all of which work like their daemontools counterparts. Unlike daemontools's, if there is a subdirectory, the same  process supervises both the  and  processes, and holds the reading and writing ends of the pipe that connects them itself. So if a service directory S is configured with a subdirectory to set up a logger for the 'main' supervised process, the output of  would show a runsv S process with two children. The logger is still controlled with (see later) by specifying an  pathname.

The service directory can also contain an optional, executable file named, that can be used to perfom cleanup actions each time the supervised process stops, possibly depending on its exit status information. calls with two arguments: the first one is 's exit code, or -1 if  didn't exit normally, and the second one is the least significant byte of the exit status as determined by POSIX. For instance, the second argument is 0 if exited normally, and the signal number if  was terminated by a signal. waits 1 second before starting or restarting, so that it does not loop too quickly if the processes exit immediately. A supervised process will run in its parent's session; making it a session leader requires using the  program with a   option inside. If receives a   signal, it behaves as if an sv exit command naming the corresponding service directory had been used (see later).

Just like daemontools', keeps control files in a subdirectory of the servicedir, named , and if it finds a simbolic link to directory with that name,  will follow it and use the linked-to directory for its control files. Unlike daemontools, also keeps human-readable files in the  directory, named  and, containing the process ID and status information about the supervised process. For further information please consult the man page.

The program allows supervising a set of processes running in parallel using a scan directory (or scandir), just like daemontools', so it will be the supervision tree's root. It also checks at least every 5 seconds the time of last modification, the inode, or the device, of the scandir, and performs a scan if any of them has changed, launching child processes for each new servicedir it finds, or old servicedir for which it finds its  process has exited, and sending a   signal to all  children for which their corresponding servicedir is no longer present. Unlike daemontools', accepts a second argument after the scan directory's pathname, that must be at least seven characters long, and works like daemontools 's last argument: it sets the number of characters of an automatically rotated log that  keeps in memory, and can be seen in the output of the  utility. The first 5 characters will remain as specified in the argument, the rest will shift to the left as new messages are sent to 's standard error. Unlike, also writes a dot to the log every 15 minutes so that old messages expire. If a  option is passed as an argument,  makes its  children leaders of new sessions using the POSIX   call. If receives a   signal, it sends a   signal to each of its  children before exiting, making them exit too. For further information please consult the man page.

is the logger program provided by the runit package. It supports automatically rotated logging directories (or logdirs) in the same way daemontool's program does, but its user interface is quite different. Logging directory pathnames are supplied as arguments and don't need to start with a dot ('.') or slash ('/'). To prepend a timestamp in external TAI64N format to logged lines, must be invoked with a   option. A  option prepends a UTC timestamp of the form YYYY-MM-DD_HH:MM:SS.xxxxx, and a   option prepends a UTC timestamp of the form YYYY-MM-DDTHH:MM:SS.xxxxx. Other actions to be performed by on logged lines can be specified in a file inside the logging directory, named. Empty lines in this file or lines that start with '#' are ignored, every other line specifies a single action. Actions are carried out sequentially in line order. Actions starting with s, n, !, + and - behave like their daemontools' counterparts. Patterns in + and - actions have the same syntax as those from Bernstein daemontools', except that also accepts a plus sign ('+') as a special character that matches the next character in the pattern one or more times, and that prepended timestamps are not considered for matching against the patterns. can be forced to perform a rotation if it receives a  signal, and rereads the  files in the logdirs (after closing and reopening all logs) if it receives a   signal. For the full description of 's functionality please consult the respective man page.

is a chain loading program that can be used to modify a supervised process' execution state. It accepts a set of options that specify what to do; some of them work like daemontools', , , , and , and others are runit-specific. For example, chpst -n increments or decrements the nice value of the process (using POSIX ), chpst -/ changes the root directory before executing the next program in the chain (using Linux   on Gentoo), and chpst -b newname executes the next program in the chain as if it was invoked with the name newname (i.e. performs  substitution). This is useful for programs that have different behaviours depending on the name they are invoked with. If itself is invoked with the names, , , ,  or , it behaves as those daemontools programs. For the full description of 's functionality please consult its respective man page.

is runit's program for controlling supervised processes and querying status information about them. It accepts a subcommand and a set of service directory pathnames as arguments. Unless a pathname starts with a dot ('.') or slash ('/'), or ends with a slash, it is asumed to be relative to the directory specified as the value of the SVDIR environment variable, or to if SVDIR is empty or unset. The subcommand tells what to do. The up, down, once and exit subcommands behave like daemontools' svc -u svc -d  svc -o and svc -dx commands, respectively. The status subcommand is similar to daemontools', it displays whether the supervised process is running ('run') or not ('down'), or if its file is currently running ('finish'), whether it is transitioning to the desired state or already there ('want up' or 'want down'), its process ID (PID) if it is up (or 's PID if it is currently running), how long it has been in the current state, and whether its current up or down status matches the presence or absence of a  file in the servicedir ('normally up' or 'normally down'). If also shows if the supervised process is paused ('paused') because of a  signal, or has been sent a   signal ('got TERM') and  is waiting for its effect. Other subcommands allow reliably sending signals to the supervised process. In particular, sv alarm can be used to send a  signal to a supervised  process to force it to perform a rotation, and sv hup can be used to send it a   signal to make it reread the logging directories'  files. For the full description of 's functionality please consult the respective man page.

Example runit scan directory with and  files, as well as a  subdirectory and a symbolic link to a  directory elsewhere:

Service directory sets up process supervision for a hypothetical  program. Messages sent by the program to its standard error are collected by an also supervised process; a redirection of standard error to standard output (i.e.  ) is needed so that the pipe set up by  between those processes is used. A logging directory named and placed in the same directory as the scan directory is used. UTC timestamps are prepended to logged messages.

The  action in the  file sets the number of old log files  should maintain to 1.

Resulting supervision tree when is run as a background process in an interactive shell using this scan directory, assuming it is the working directory (i.e. launched with runsvdir . & ):

This shows that both the and  processes are supervised by the same  process. subdirectory contents:

Contents of the log directory and current log file:

The timestamp is in UTC, and the computer's operating system is assumed to be set to a UTC-3 timezone. Forcing to perform a rotation:

This shows that a log file with a name containing a TAI64N timestamp and ending in .s (meaning 'completely processed log file') was created, and that was truncated. Messages sent by 's process to 's standard output when manually started:

As shown by the output of, the process exits each time with an exit code of 0. Resulting supervision tree:

This shows that because has a  subdirectory, sv status shows the status of the  process too, after 's status ("run: log:"). After enough seconds have elapsed:

This shows that is currently executing 's  file ("finish:"). Reliably sending a  signal to 's  process:

This confirms that is stopped ("paused"). Reliably sending a  signal afterwards:

This confirms that received a   signal ("got TERM"), but it doesn't have any efect yet because the process is stopped. To resume it a  signal is needed:

The output of shows that after resuming execution,  was killed by the   signal that was awaiting delivery (signal 15), and because the process is supervised,  first executes, and then reexecutes. Messages sent by 's process to 's standard output when manually stopped:

As shown by, stopped the  process by killing it with a   signal (signal 15). The output of sv status shows that is executing the  script, and that when it exits, the service will stay down ("want down").

The check file
The program accepts a   option ('verbose') that makes it wait for the action requested by the specified subcommand to be completed, and then prints the resulting process' status, as if an sv status command had been used. The wait period's duration is the value of the SVWAIT environment variable (in seconds), or 7 seconds if SVWAIT is empty or unset. It can also be specified with a  option passed to, which overrides the value of SVWAIT. If the requested action completes before the expiry of the wait period, the status line is prepended with 'ok:' followed by a space. Otherwise, the command exits with a nonzero code and the status line is prepended with 'timeout:' followed by a space.

For the sv -v up command, and, if the supervised process is wanted up after the action (i.e. no sv once command was used before), the sv -v term and sv -v kill commands, the action is considered complete if considers the supervised process to be in 'run' state (i.e. sv status would print 'run:'). However, when the supervised process is executing a server program for example, it might not be ready to provide its service immediately after startup. Programs might do initialization work that could take some noticeable time before they are actually ready to serve, but it is impossible for the supervisor to know exactly how much. If there is some program-specific way to infer that it is ready, runit is able to take advantage of it by including an executable file named in the service directory. When using one of the aforementioned subcommands, after determines that the supervised process is in 'run' state (via the  file), it executes the  file if present, and waits for it to exit. This file is assumed to contain code that polls for readiness, and must exit with a 0 code if it considers the supervised process to be ready, and with a nonzero code otherwise. Just like or, the  file can have any format the kernel knows how to execute, and is normally a shell script. If determines that the process is ready,  will print an 'ok' status line and exit, otherwise it reexecutes  after waiting 420 milliseconds. In other words, during the wait period will periodically poll for readiness using ; if its exit code is never 0, on expiry of the wait period  will print a 'timeout' status line and exit.

In addition, the sv check command can be used to poll for readiness (periodically during a wait period) by executing the file, without changing the supervised process' state. The sv status command does not use the file. For the full description of the program please consult the respective man page.

Example service directory with a file:

This service directory sets up process supervision for a hypothetical program. It is assumed that the program can be polled for readiness using another program named. For demonstration purposes, the utility is used so that  does not exit too quickly. Using the sv check command after launching the supervision tree, assuming that the scan directory is the working directory:

Because of the file,  does not launch, so it considers its supervised process to be in 'down' state, so sv check exited immediately with an 'ok' status and without executing. Starting the supervised process using 's  option:

This shows that a process was spawned ("run: test-service:"), but the  program determined that it was not ready. The was executed 6 times before the expiery of the default 7 seconds wait period, so  finally gave up with a 'timeout' status. Polling again:

Between both commands  became ready, so this time the (single) poll was successful, and  exited immediately with an 'ok' status. Reliably sending a   signal using 's   option and a longer wait period:

This shows that a process was killed and then restarted (because it is supervised), but 8 polls were necessary until the  program determined that it was ready. Because the process became ready during the wait period, exited with an 'ok' status. Stopping the process using 's   option:

Making stop and exit using 's   option, assuming its supervising  parent process was already killed:

The sv program's LSB-like interface
also accepts a set of subcommands resembling LSB init script actions :


 * The sv start, sv stop and sv shutdown commands are equivalent to sv -v up , sv -v down and sv -v exit , respectively.
 * The sv force-stop and sv force-shutdown commands, or equivalently, sv Down and sv Exit (with capital 'D' and 'E'), behave like sv stop and sv shutdown, respectively, except that if the action requested by the specified subcommand does not complete during the wait period, the supervised process is sent a  signal on its expiry, as if an sv kill command had been used. The status line printed by  is prepended with 'kill:' followed by a space in that case.
 * The sv reload and sv try-restart commands are equivalent to sv -v hup, sv -v term respectively, except that the latter also sends a  signal to the supervised process after the   signal, as if an sv cont command had been used.
 * The sv restart command is equivalent to sv term followed by sv cont followed by sv -v up . Therefore, unlike sv try-restart, sv restart cancels the 'do not restart' effect of any previous sv once command.
 * The sv force-reload and sv force-restart commands behave like sv try-restart and sv restart, respectively, except that if the action requested by the specified subcommand does not complete during the wait period, the supervised process is sent a  signal on its expiry, just like what happens with sv force-stop and sv force-shutdown . The sv Term command (with capital 'T') is equivalent to sv force-reload.

As noted in section "The check file", the equivalences stated above imply that the,  ,  ,   and   subcommands make  execute the  file in the named service directories, if present, to poll for readiness.

The program can be invoked with the name of a service directory (with any   substitution mechanism), in that case, also its exit code tries to comply with the LSB specification: it is 2 for usage errors and 151 (in the "reserved for application use" range) for fatal errors, instead of 100 in both cases, it is 0, 3 or 4, as appropriate, if the subcommand is , and it is 1 on error (other than fatal errors) for other subcommands. This is useful if a symbolic link to representing a 'service name' is placed in directory, resembling an LSB initialization script: executing this 'initialization script' with an action argument results in actually executing  with a runit service directory of that name as an argument (e.g. /etc/init.d/foo try-restart will result in sv try-restart foo ).

For the full description of 's functionality please consult the respective man page.

Example service directory for a hypothetical program with a setup similar to that of section "The check file":

It is assumed that supports an   option that makes it ignore the   signal. Starting the supervised process using 's LSB-like interface:

This shows that sv start, being equivalent to sv -v up , also uses the file. The program was used to poll twice for readiness, and succeeded before the expiry of the 10 seconds wait period. Stopping the process using 's LSB-like interface:

This shows that sv stop, being equivalent to sv -v down , tried to stop the supervised process by sending it a  signal. Because ignores the signal, the stop action didn't complete before the expiry of the wait period, so  gives up with a "timeout" status. The status line confirms that the wanted supervised process's state is 'down' ("wanted down"), and that a  signal was sent ("got TERM"). Stopping the process using 's   subcommand:

This shows that, again, the stop action didn't complete before the expiry of the wait period, but this time a  signal was sent to the supervised process on expiry of the wait period. The file is then executed by, and its message confirms that  got killed by a   signal (signal 9).

Custom process control
The program allows the customization of the effect of some  subcommands to some degree. This is done by providing executable files in a subdirectory of the service directory named. The executable files must have single character names that map to an subcommand, the  man page details this mapping (it corresponds to the character that is written by  to 's  FIFO). The subcommands that can be customized this way are:


 * The ones that send signals to the supervised process (, ,  , etc.). In particular, if present, the control file that corresponds to customized sv term , , is also used by the sv down and sv exit commands.  executes the file, waits for it to finish, and then checks its exit code. If it is a nonzero code,  additionaly sends the corresponding signal to the supervised process. If it is 0, no signal is sent.
 * The  and   subcommands. A single control file,, is used for both subcommands.  executes the file and waits for it to exit, before executing the  file. The control file is also executed after  and before reexecution of  if the spuervised process unexpectedly stops running and gets restarted by , and is ignored for the sv once command if  or  are running. The control file's exit code is ignored.
 * The  and   subcommands.  executes the control file,  and, respectively, after sending the supervised process the   signal, or executing  if appropriate, and after sending the subsequent   signal, ignoring  if present (the control file for sv cont ), and waits for it to exit. The control file's exit code is ignored. For sv exit ,  exits after  exits.

Just like or, the files in the  subdirectory can have any format the kernel knows how to execute, and are normally shell scripts. In particular, should contain code that can stop the supervised process, and is useful if there is an alternative (and preferred) way to do so without sending a   signal. For further details about customizing the the effect of, please consult 's man page.

Example service directory with a subdirectory for customized control:

This service directory sets up process supervision for a hypothetical program. Messages sent by the program to its standard error are collected by an also supervised process; a redirection of standard error to standard output (i.e.  ) is needed so that the pipe set up by  between those processes is used. A logging directory named and placed in the same directory as the scan directory is used.

This control files do nothing but print a message for logging purposes.

This control file is executed when an sv hup command is used. It is assumed that prints a message of the form 'Message #N' each time it receives a   signal, where N is an increasing integer.

This is a deliberate misuse of the file, for demonstration purposes, because it doesn't actually stop. Both and  exit with a code that is the value of environment variable EXIT_STATUS. A chpst -e command is used each time these control files are executed, to modify the environment according to environment directory :

When chpst -e is executed, the value of EXIT_STATUS will be 1.

The file in the logging directory deselects messages that start with 'control/h:' for logging to the  file ('-' action), and selects them for logging to 's standard error ('e' action), which in this example is the interactive shell's controlling terminal. These would be the messages printed by the file. Contents of the file in the logging directory when the supervision tree is launched, assuming that the scan directory is the working directory:

This shows that was executed before. Using the sv hup command:

This shows that was executed.

This confirms that, because EXIT_STATUS is 1, exits with a nonzero code, so a   signal was also sent to, causing it to print messages to its standard error. Using the sv -v term command:

This shows that was executed, and because its exit code is 1, a   signal was also sent to. The signal killed the process, and because it is supervised, is reexecuted. And because there is also a file, it was executed as well, before. Using the sv -v down command:

The command shows an "ok" status and a "down" state, so it successfully stopped.

This shows that both and  were executed, in that order. Starting again with a modified environment directory, assuming the logging directory has been rotated with an sv alarm test-service/log command:

Repeating the sv hup commands:

This shows that, again, was executed, but this time, because EXIT_STATUS is now 0, the script exits with a 0 code, so no   signal was sent to. This is confirmed by the absence of logged messages from the process. Stopping with the sv -v down command:

This shows that, because contains no code to stop, and because its exit code is now 0,  times out ("timeout") and the supervised process' state is still "run". Stopping with the sv force-stop command:

This shows that because doesn't get stopped,  sends a   signal to the supervised process on expiry of the wait period, and exits with a "kill" status.

This confirms that is now in "down" state, and that, again, both  commands executed  and then.

From OpenRC
As of version 0.22, OpenRC provides a service script that can launch with -style logging, also named. On Gentoo, the scan directory will be. This script exists to support the OpenRC-runit integration feature, but can be used to just launch a runit supervision tree when the machine boots by adding it to an OpenRC runlevel using :

Or it can also be started manually:

Because the service script calls using absolute path, a symlink to the correct path must be created if using  :

And because is a tmpfs, and therefore volatile, servicedir symlinks must be created in the scan directory each time the machine boots, before  starts. The tmpfiles.d interface, which is supported by OpenRC using package opentmpfiles, can be used for this:

Alternatively, OpenRC's service could be used to start the supervision tree when entering OpenRC's 'default' runlevel, by placing '.start' and '.stop' files in  (please read  for more details) that perform actions similar to those of the  service script:

The  signal makes  send a   signal to all its  children before exiting, which, in turn, makes them stop their supervised processes and exit. The  signal that  sends by default would just make  exit.

From sysvinit
Following upstream's suggestion, Gentoo's packaging of runit provides a symbolic link to , that allows  to be launched and supervised by sysvinit by adding a 'respawn' line for it in. Used in this way, the supervision tree becomes rooted in process 1, which cannot die without crashing the machine.

Gentoo users wanting to use in this way will need to manually edit, and then call :

This will make sysvinit launch and supervise when entering runlevels 1 to 5.

The logging chain
A supervision tree where all leaf processes have a logger can be arranged into what the author of s6 calls the logging chain, which he considers to be technically superior to the traditional syslog-based centralized approach.

Since processes in a supervision tree are created using the POSIX  call, each of them will inherit 's standard input, output and error. A logging chain arrangement using runit is as follows:


 * Leaf processes should normally have a logger, so their standard output and error connect to their logger's standard input. Therefore, all their messages are collected and stored in dedicated, per-service logs by their logger. Some programs might need to be invoked with special options to make them send messages to their standard error, and redirection of standard error to standard output (i.e. 2>&1 in a shell script) must be performed in the servicedir's file.
 * Leaf processes with a controlling terminal are an exception: their standard input, output and error connect to the terminal.
 * , the loggers, and leaf processes that exceptionally don't have logger for some reason, inherit their standard input, output and error from, so their messages are sent wherever the ones from are.
 * Leaf processes that still unavoidably report their messages using  have them collected and logged by a (possibly supervised) syslog server.

If runit is used as the init system, and was invoked with no second argument, its standard input, output and error will be redirected to. If was invoked with a second argument, -like logging is turned on and messages sent to 's standard error will go to the log and can be seen using.

Runit as the init system
The runit package provides a program capable of running as process 1, also called, and a helper program,. If detects it is running as process 1, it replaces itself with  using the POSIX   call. Therefore, to use as the system's init, a   parameter can be added to kernel's command line using the bootloader's available mechanisms (e.g. a  command in some 'Gentoo with runit' menu entry for GRUB2). It is possible to go back to sysvinit + OpenRC at any time by reverting the change.

When the machine starts booting (if an initramfs is being used, after it passes control to the 'main' init), executes the  file as a child process, in a foreground process group with  as the controlling terminal, and waits for it to finish. This file is usually a shell script, and is expected to perform all one time initialization tasks needed to bring the machine to its stable, normal 'up and running' state. Gentoo's file is quite minimal, it only calls the  program to enter OpenRC's sysinit runlevel, and then its boot runlevel, emulating Gentoo's sysvinit setup.

When exits,  then executes the  file as a child process, makes it a session leader with the POSIX   call, and supervises it: if  is killed by a signal or its exit code is 111, then  will restart it, after sending a   signal to every remaining process in its process group. Gentoo's file is upstream's suggested one with minimal modifications. It is a shell script that uses the builtin utility to replace itself with, so this creates a supervision tree rooted in process 1. The scan directory will be for , and  for. The enviroment will be empty, except for the PATH variable, set to a known value in the script. will use -like logging, and, for, is also passed the   option.

Gentoo's packaging of runit expects for , or  for  , to be a repository of service directories. Services that need to be started when the machine boots require a symbolic link in the scan directory to the corresponding servicedir in that repository. Gentoo only provides service directories for 6 parallel supervised processes (with their symlinks in the scan directory); this allow users to get to a text console login, like with Gentoo's sysvinit setup. Service directories for anything else must be created by the administrator, either from scratch or taken from somewhere else (e.g. alternative ebuild repositories).

If receives a   signal, and the file  exists and has the execute by owner permission set, it will kill  (first by sending it a   signal and waiting, then by sending it a   signal) and then execute the  file. This file is usually a shell script, and is expected to perform all tasks needed to shut the machine down. If is killed by a signal or its exit code is 100,  skips execution of  and executes. will also execute if  exits (with an exit code other than 111). If exits,  will send a   signal to all remaining processes, and then check the file  to decide what to do next. If the file exists and has the execute by owner permission set, it reboots the machine. In any other case, it will power off the machine, or halt it if it can't power it off.

Gentoo's file performs an sv shutdown for , or an sv force-shutdown for  , on every servicedir of 's scan directory, and then calls the  program to enter OpenRC's shutdown or reboot runlevels, depending on whether a poweroff or reboot operation was requested to  via.

If receives a   signal (which is usually configured to happen when key combination ++ is pressed), and the file  exists and has the execute by owner permission set, it will execute it as a child process, and when it exits, behave as if it had received a   signal. Gentoo's prints a "System is going down in 14 seconds..." message using the  utility, makes sure file  exists and has the execute by owner permission set, waits 14 seconds and then exits. The result being that  will either halt or reboot the machine after 14 seconds, depending on.

All 's children run with their standard input, output and error initially redirected to.

Reboot and shutdown
The program can be used to shut the machine down. Unless it is running as process 1, it accepts one argument, which can be either 0 or 6:
 * If it is 0, will create the  and  files if any of them does not exist, set the execute by owner permission for the former, unset it for the latter, and send a   signal to process 1.
 * If it is 6, will create the  and  files if any of them does not exist, set the execute by owner permission for both of them, and send a   signal to process 1.

Therefore, if process 1 is, then runit-init 0 will power off the machine, and runit-init 6 will reboot it.

This means that is not directly compatible with sysvinit's, , , , and  commands. However, many programs (e.g. desktop environments) expect to be able to call programs with those names during operation, so if such thing is needed, it is possible to use compatibility shell scripts:

The runsvchdir program
Runit doesn't directly support any runlevel-like concept, but if the machine contains a set of directories, each one with a scan directory structure, then it is possible to have a behaviour similar to 'changing runlevels' if the scan directory argument of runsvdir is actually a symbolic link. The software package's author proposes creating a symbolic link to directory pointing to one of the aforementioned directories, which then becomes the current scan directory. Runit provides a program that can atomically modify this symlink, thereby switching the current scan directory used by. As a result, on 's next periodic scan, new supervised processes can be started, and some supervised processes can be stopped: new processes will be spawned for service directories present in the new scan directory but not in the old one, and running  processes will be sent   signals (resulting in the equivalent of an sv exit command) if their corresponding service directories are present in the old scan directory but not in the new one. Supervised processes that have service directories with the same name in both the old and new scan directory remain unaffected.

Using requires that the scan directory be specified to  as pathname, or a symbolic link that resolves to that pathname. This means that can affect only a single  process, which is normally the one started by  and supervised by process 1. accepts a pathname specifying the new scan directory as an argument, that must not start with a dot ('.'); it creates a symlink named that points to this pathname, renames  to, and then renames  to. This means that if the supplied pathname does not start with a slash ('/'), it will be interpreted as relative to. Therefore, if and  are runit scan directories, and  is currently a symbolic link to, then command runsvchdir runlevelB performs a 'runlevel change' to runlevelB. For further details on, please consult the respective man page.

Gentoo's packaging of runit version 2.1.1 supports this model: runsvdir's scan directory is, a symbolic link to. After package installation, a directory named is created, emulating a 'default runlevel', and initially  points to. Directory contains initially symbolic links to the 6 service directories for  processes installed in the servicedir repository.

Gentoo's packaging of runit version 2.1.2 does away with this runlevel-like setup.

Examples of usage (with a setup more similar to that of Void Linux rather than Gentoo's):

This shows that using with a pathname that  already points to has no effect.

This shows that also updated symbolic link.

Runit and service management
Runit doesn't have service manager features, i.e. it does not provide mechanisms for specifiying dependencies, service ordering constraits, etc. like OpenRC does using  functions in service scripts. If such things are needed, the desired behaviour must be explicitly enforced in the code of files; the software package's author provides some tips on how to do that. Sometimes, just doing nothing might be enough: if simply exits with an error status when there is an unmet required condition, and, perhaps with help from a  files that analyzes the exit code, the state the machine was in before  was executed is restored, the supervisor would just keep restarting the service until, after some convergence period, all its required conditions are met. The author of nosh calls this "the thundering herd solution".

Nevertheless, OpenRC and runit do not interfere with each other, so it is possible to use OpenRC-managed services on a machine where the init system is runit. In particular, once the supervision tree rooted in process 1 is launched, it is still possible to manually start individual OpenRC services using, or even entering OpenRC's 'default' runlevel manually:

Services from OpenRC's 'default' runlevel could be started automatically on boot using the existing service, moving it to the 'boot' runlevel:

Alternatively, can be modified to add the corresponding  invocation:

Note however that OpenRC services will not be supervised by runit.

Runit can be used without OpenRC's service management, but this requires alternative implementation of the functionality of its service scripts, especially those executed upon entering the 'sysinit', 'boot' and 'shutdown' runlevels, and replacing the Gentoo-provided and  files with custom ones, since they call the  program. It can be be useful to study those from runit-based distributions (e.g. see Void Linux's ones in their void-runit package sources).

OpenRC's runit integration feature
Starting with version 0.22, OpenRC can launch supervised long-lived processes using the runit package as a helper. This is an alternative to 'classic' unsupervised long-lived processes launched using the program. It should be noted that service scripts that don't contain  and   functions implicitly use.

OpenRC services that want to use runit supervision need both a service script in and a runit service directory. The service script must contain a  variable assignment to turn the feature on, and must have a 'need' dependency on the  service in its   function, to make sure the  program is launched (see here). It can contain neither a  function, nor a   function (but their   and   variants are OK), nor a   function; OpenRC internally invokes  when the service script is called with a 'start', 'stop' or 'status' argument.

The runit service directory can be placed anywhere in the filesystem, and have any name, as long as the service script (or the service-specific configuration file in ) assigns the servicedir's absolute path to the runit_service variable. If runit_service is not assigned to, the runit servicedir must have the same name as the OpenRC service script, and will be searched in the >=sys-process/runit-2.1.2 service directory repository,. The scan directory when using this feature is, and OpenRC will create a symlink to the service directory when the service is started, and delete it when the service is stopped.

Example setup for a hypothetical supervised test-daemon service, with and without a dedicated logger.

The service directories:

This launches program with effective user daemon and the maximum number of open file descriptors set to 5. This is the same as if performed a   call itself with   set to 5, provided that value does not exceed the corresponding hard limit. The program also periodically sends a message of the form "Logged message #N" to its standard error.

The redirection of 's standard error to standard output allows logging its messages using runit's. An automatically rotated logging directory named logdir will be used, and messages will have a UTC timestamp prepended to them.

Manually starting :

Make OpenRC's notion of the service's state catch up:

The resulting supervision tree so far:

Messages from the process with PID 2155 go to the logging directory:

Manually starting :

Make OpenRC's notion of the service's state catch up because of the service startup bug:

The scan directory:

Final supervision tree:

Since the process with PID 2250 doesn't have a dedicated logger, its messages go to 's standard error, are logged -style, and show up in ' output (for process 1931 in this case).

Unmerge
Service directories, additional scan directories, the symlink to, etc. must be manually deleted if no longer wanted after removing the package. Also, all modifications to sysvinit's must be manually reverted: lines for  must be deleted, and a telinit q command must be used afterwards. And obviously, if runit is being used as the init system, an alternative one must be installed in parallel, and the machine rebooted to use it (possibly by reconfiguring the bootloader), before the package is removed, or otherwise the machine will become unbootable.

External resources

 * Runit article on the Void Linux Wiki (a runit-based GNU/Linux distribution).
 * Runit article on the Arch Linux Wiki.
 * A thread about runit on the Gentoo Forums.
 * The flussence ebuild repository, providing an alternative runit packaging, and accompanying runit-scripts repository.
 * The powerman ebuild repository, providing an alternative runit packaging, service directory files for many services, and runit boot scripts.
 * Avery Payne's supervision-scripts project, compatible with runit.