runit is a lightweight, cross-platform Unix init scheme with service supervision that provides a reliable alternative to traditional init systems. Developed by Gerrit Pape, runit provides a simple yet powerful approach to process supervision and system initialization, making it an excellent choice for embedded systems, containers, and servers requiring robust service management.
What is runit?
runit is a Unix init scheme that replaces the traditional SysV init system with a more reliable and simpler approach. It consists of three main phases and provides automatic service supervision, which means it constantly monitors running services and automatically restarts them if they fail. This makes Runit especially valuable for mission-critical applications where uptime is essential.
The system is specifically designed based on the philosophy of “do one thing and do it well”, focusing on process supervision and service management. Unlike systemd or other complex init systems, runit maintains simplicity while providing robust functionality.
Key Features of Runit
- Automated Service Supervision: Continuously monitors services and restarts failed processes
- Simple configuration: Uses plain shell scripts for service definitions
- Fast boot time: Parallel service startup reduces boot time
- Reliable Logging: Built-in logging mechanism with svlogd
- Cross-platform: Works on Linux, BSD and other Unix-like systems
- Small Footprint: Minimal resource usage and dependencies
runit architecture
Runit operates through three distinct phases:
Step 1: System Initialization
This phase handles one-time system initialization tasks such as mounting the file system, configuring network interfaces, and setting up the basic system environment. This is equivalent to the traditional /etc/rc.sysinit script.
Step 2: Service Supervision
The core of runit, this step starts the runswiddir program that monitors all services. It continuously monitors service directories and automatically starts, stops, and restarts services as needed.
Stage 3: System Shutdown
Handles graceful system shutdowns, including stopping all supervised services, unmounting file systems, and performing cleanup tasks.
install runit
Runit installation varies depending on your Linux distribution:
Ubuntu/Debian:
sudo apt-get update
sudo apt-get install runitCentOS/RHEL:
sudo yum install runit
# or for newer versions
sudo dnf install runitArch Linux:
sudo pacman -S runitFrom Source:
wget http://smarden.org/runit/runit-2.1.2.tar.gz
tar xzf runit-2.1.2.tar.gz
cd runit-2.1.2
package/installBasic runit commands
Runit provides several essential commands for service management:
SV – Service Control
sv The primary tool for controlling command services is:
# Start a service
sv start service_name
# Stop a service
sv stop service_name
# Restart a service
sv restart service_name
# Check service status
sv status service_name
# Get service uptime
sv up service_nameExample output:
$ sv status nginx
run: nginx: (pid 1234) 3600s
$ sv status down_service
down: down_service: 0s, normally uprunvdir – service directory monitor
Monitors service directories and starts runv for each service:
runsvdir /etc/serviceRunv – Single Service Supervisor
Supervises personal services:
runsv /etc/service/nginxCreating Runit Services
Creating services in runit involves setting up a services directory with an executable run script:
basic service structure
/etc/sv/myservice/
├── run # Main service script (required)
├── finish # Cleanup script (optional)
├── down # Prevents auto-start (optional)
└── log/ # Logging service (optional)
└── run # Log service scriptCreating a Simple Web Server Service
Let’s create a service for a simple Python HTTP server:
# Create service directory
sudo mkdir -p /etc/sv/webserver
# Create the run script
sudo tee /etc/sv/webserver/run << 'EOF'
#!/bin/sh
exec 2>&1
cd /var/www/html
exec python3 -m http.server 8080
EOF
# Make it executable
sudo chmod +x /etc/sv/webserver/run
# Enable the service
sudo ln -s /etc/sv/webserver /etc/service/service with logging
# Create log directory
sudo mkdir -p /etc/sv/webserver/log
# Create log run script
sudo tee /etc/sv/webserver/log/run << 'EOF'
#!/bin/sh
exec svlogd -tt /var/log/webserver
EOF
# Make it executable
sudo chmod +x /etc/sv/webserver/log/run
# Create log directory
sudo mkdir -p /var/log/webserverAdvanced Service Configuration
service with environment variables
# Create environment directory
sudo mkdir -p /etc/sv/myapp/env
# Set environment variables
echo "production" | sudo tee /etc/sv/myapp/env/NODE_ENV
echo "3000" | sudo tee /etc/sv/myapp/env/PORT
# Updated run script
sudo tee /etc/sv/myapp/run << 'EOF'
#!/bin/sh
exec 2>&1
exec chpst -e ./env -u appuser node /opt/myapp/server.js
EOFService with user privileges
sudo tee /etc/sv/database/run << 'EOF'
#!/bin/sh
exec 2>&1
exec chpst -u postgres:postgres /usr/bin/postgres -D /var/lib/postgresql/data
EOFservice management example
Service status monitoring
# Check all services
sudo sv status /etc/service/*
# Example output:
run: apache2: (pid 1456) 7200s
run: nginx: (pid 1234) 3600s
down: mysql: 120s, normally up
run: ssh: (pid 892) 86400sinteractive service control
# Start multiple services
for service in nginx mysql redis; do
sv start $service
echo "Started $service"
done
# Monitor service startup
watch 'sv status /etc/service/*'Logging with Svlogd
Runit includes svlogd, a powerful logging daemon that provides automatic log rotation and filtering:
Basic logging configuration
# Log configuration file
sudo tee /var/log/myservice/config << 'EOF'
s1000000 # Maximum log file size (1MB)
n10 # Keep 10 log files
t # Add timestamps
EOFlog filtering
# Filter logs by pattern
sudo tee /var/log/myservice/config << 'EOF'
+*error* # Include lines containing 'error'
-*debug* # Exclude lines containing 'debug'
s10000000 # 10MB log files
n5 # Keep 5 files
EOFTroubleshooting Runit Services
Common Issues and Solutions
service will not start
# Check if run script is executable
ls -la /etc/sv/myservice/run
# Check for syntax errors
sh -n /etc/sv/myservice/run
# Check service logs
sudo tail -f /var/log/myservice/currentService keeps restarting
# Check service status with details
sv status /etc/service/myservice
# Monitor service restarts
while true; do
sv status /etc/service/myservice
sleep 1
donedebugging service script
# Add debug output to run script
#!/bin/sh
exec 2>&1
echo "Starting service at $(date)"
echo "Environment: $(env)"
echo "User: $(whoami)"
exec /path/to/programPerformance and Resource Management
resource limitations
# Limit memory usage
sudo tee /etc/sv/myapp/run << 'EOF'
#!/bin/sh
exec 2>&1
exec chpst -m 100000000 -u appuser /opt/myapp/bin/myapp
EOFcpu limits
# Nice priority adjustment
exec chpst -n 10 -u appuser /opt/myapp/bin/myappMigration from other init systems
from systemd
Converting systemd service to runit:
# systemd service file
[Unit]
Description=My Web App
After=network.target
[Service]
Type=simple
User=webuser
WorkingDirectory=/opt/webapp
ExecStart=/opt/webapp/bin/server
Restart=always
[Install]
WantedBy=multi-user.targetEquivalent Runit Service:
# /etc/sv/webapp/run
#!/bin/sh
exec 2>&1
cd /opt/webapp
exec chpst -u webuser /opt/webapp/bin/serverbest practices
service design principles
- Keep the run script simple: Avoid complex logic in run script
- Use execution: Replace shell process with your program
- redirect stderr: Use
exec 2>&1To combine output streams - Avoid condemnation: Run the program in foreground mode
- Set working directory: Use
cdbefore executing the program
security considerations
# Run service as non-root user
exec chpst -u serviceuser:servicegroup /path/to/program
# Set environment cleanly
exec chpst -e ./env -u serviceuser /path/to/program
# Limit resources
exec chpst -m 100000000 -o 1000 -u serviceuser /path/to/programmonitoring and warning
service health checkup
#!/bin/bash
# health_check.sh
for service in $(ls /etc/service/); do
status=$(sv status "/etc/service/$service" 2>/dev/null)
if [[ $status == down* ]]; then
echo "ALERT: $service is down"
# Send notification
fi
doneautomatic service recovery
# /etc/sv/myservice/finish
#!/bin/sh
# Cleanup script that runs when service exits
echo "Service $1 exited with code $2 at $(date)" >> /var/log/myservice/finish.log
# Conditional restart logic
if [ "$2" -eq "100" ]; then
# Exit code 100 means don't restart
touch ./down
ficonclusion
Runit provides a robust, lightweight alternative to complex init systems while maintaining simplicity and reliability. Its service supervision capabilities, coupled with straightforward configuration and excellent performance characteristics, make it an excellent choice for a variety of deployment scenarios.
The system’s philosophy of simplicity does not compromise functionality – from basic service management to advanced logging and resource control, Runit provides all the tools needed for effective system administration. Whether you’re managing a single server or a complex distributed system, Runit’s reliable service supervision ensures that your applications remain available and functional.
By following the practices and examples outlined in this guide, you will be well-equipped to implement Runit into your infrastructure and take advantage of its powerful service supervision capabilities. Its lightweight nature and cross-platform compatibility make it particularly valuable for modern containerized environments and embedded systems where resource efficiency is important.
