How Linux Implements the Runit Init Scheme
This article explains how the Linux operating system implements the
runit initialization scheme, an alternative to systems like
systemd and SysVinit. Best known for its primary role in Void Linux,
runit handles process initialization, supervision, and
shutdown using small, modular components adhering to the Unix
philosophy. Below is an overview of the three-stage initialization
cycle, the service supervision tree, service directory management, and
the control mechanisms that make runit fast, reliable, and
resource-efficient.
The Three-Stage Boot Process
When the Linux kernel finishes booting, it starts the primary init
process, PID 1, targeting /sbin/init (which is a symlink to
/usr/bin/runit or /etc/runit/init). Once
executed, runit organizes the machine's life cycle into
three distinct, sequential stages handled by three executable shell
scripts located in /etc/runit/.
Stage 1: System Initialization
Stage 1 executes /etc/runit/1. This stage runs once at
boot to perform essential hardware and system preparation tasks:
- Mounting the root filesystem in read-write mode.
- Mounting virtual filesystems such as
/proc,/sys, and/dev. - Initializing system clocks, setting the hostname, and loading core kernel modules.
- Starting essential device managers like
udevoreudev.
Stage 1 must exit successfully (with return code 0) before the system moves on. If it fails, the boot process halts to prevent file corruption.
Stage 2: Runtime and Service Supervision
Upon the successful completion of Stage 1, runit moves
to /etc/runit/2. This stage represents the live, running
state of the operating system.
Instead of handling individual services directly,
/etc/runit/2 launches runsvdir, the primary
service supervision daemon. runsvdir runs continuously
until the system is instructed to shut down or reboot. If the script
/etc/runit/2 crashes or terminates unexpectedly,
runit immediately restarts it.
Stage 3: Shutdown and Reboot
When an administrator triggers a reboot or power-off,
runit terminates Stage 2 and executes
/etc/runit/3. This script handles system shutdown
tasks:
- Halting active user sessions.
- Sending termination signals (
SIGTERMfollowed bySIGKILL) to all supervised processes. - Unmounting or remounting filesystems as read-only.
- Executing the final system call to power down or reboot the machine.
Service Supervision:
runsvdir and runsv
The supervision architecture of runit relies on a clear
parent-child hierarchy managed by two core programs:
runit (PID 1)
└── runsvdir
├── runsv (service A)
│ └── service A daemon
├── runsv (service B)
│ └── service B daemon
└── runsv (service C)
├── service C daemon
└── logger daemon
runsvdir: Continuously monitors a target directory (typically/var/service/). For every sub-directory found inside,runsvdirspawns an individualrunsvprocess. If a sub-directory is removed,runsvdirinstructs the correspondingrunsvprocess to exit.runsv: Directly supervises a single service. It runs an executable script namedruninside the service's directory. Becauserunsvruns as the direct parent of the service daemon, it captures exit codes instantly through standard Unix signals without polling. If the daemon crashes or exits,runsvimmediately restarts it.
Services in runit are configured to run in the
foreground. This eliminates the need for daemons to fork themselves into
the background, avoiding orphaned processes and PID file tracking
issues.
Service Management in Void Linux
Void Linux uses simple filesystem primitives to enable, disable, and control services:
- Service Repository (
/etc/sv/): Contains templates and definitions for all available services. Each service directory contains an executablerunscript, optionalfinishscripts (run when the service terminates), and aconffile for environment variables. - Active Services (
/var/service/): Contains symbolic links to folders in/etc/sv/. Enabling a service requires only creating a symlink:ln -s /etc/sv/dhcpcd /var/service/runsvdirscans this directory every five seconds, detects the new link, and launches arunsvprocess for it automatically. Removing the symlink signalsrunsvdirto stop the service.
Control Interface: The
sv Command
Administrative control over services is handled using the
sv utility, which communicates with the individual
runsv supervisors via named pipes (FIFOs) located in the
service directories.
Common commands include:
sv status <service>: Queries the supervisingrunsvinstance for process status, PID, and uptime.sv up <service>/sv down <service>: Starts or stops a service by sending the appropriate control commands torunsv.sv restart <service>: Sends aSIGTERMfollowed by restarting therunscript.sv pause <service>/sv cont <service>: SendsSIGSTOPandSIGCONTsignals to suspend and resume service execution.
Logging
runit manages logs without a monolithic centralized
logging daemon. A service directory can optionally contain a
sub-directory named log with its own executable
run script.
When present, runsv creates a UNIX pipe connecting the
standard output of the primary service directly to the standard input of
the logger script. Void Linux typically couples this with utilities like
vlogger or socklog (a syslog
replacement), providing segregated, low-overhead logging that isolates
individual service failures.