Best viewed on desktop for optimal interactive experience
The Heartbeat of Linux
At the very core of every Linux system beats a special process - PID 1, the init system. This is the first process started by the kernel and the last one to die when the system shuts down. It's the ancestor of all other processes, the supervisor of system services, and the orchestrator of your system's lifecycle.
Think of the init system as the conductor of an orchestra. While the kernel provides the instruments (hardware resources), the init system coordinates when each musician (service) plays, ensuring they work in harmony. Some conductors (SysV Init) follow a strict, sequential score, while others (systemd) allow sections to play simultaneously for a faster, more dynamic performance.
The evolution from SysV Init to systemd represents one of the most significant changes in Linux history, transforming how we think about system initialization and service management.
Interactive Init Systems Comparison
Explore the differences between major init systems and how they manage your Linux system:
Linux Init Systems Comparison
systemd
Modern init system with parallel startup
Pros
Cons
Key Features
SysV Init
Traditional sequential init system
OpenRC
Dependency-based init system
Upstart
Event-based init replacement
Feature | systemd | SysV Init | OpenRC | Upstart |
---|---|---|---|---|
Boot Speed | ✅ Fast | ❌ Slow | ⚡ Medium | ⚡ Medium |
Parallel Start | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes |
Dependencies | ✅ Automatic | ❌ Manual | ✅ Automatic | ✅ Event-based |
Complexity | 🔴 High | 🟢 Low | 🟡 Medium | 🟡 Medium |
The Init Process Hierarchy
PID 1: The Immortal Process
// The kernel's handoff to init // kernel/init/main.c static int __ref kernel_init(void *unused) { // ... kernel initialization ... // Try to execute init programs if (!try_to_run_init_script("/sbin/init") || !try_to_run_init_script("/etc/init") || !try_to_run_init_script("/bin/init") || !try_to_run_init_script("/bin/sh")) return 0; panic("No working init found!"); }
Process Tree Structure
# View process tree pstree -p systemd(1)─┬─systemd-journal(289) ├─systemd-udevd(315) ├─systemd-network(420) ├─systemd-resolve(421) ├─sshd(890)───sshd(1234)───bash(1235) ├─nginx(1001)─┬─nginx(1002) │ └─nginx(1003) └─cron(1100)
SysV Init: The Traditional Approach
Architecture
# /etc/inittab - The master control file # Format: id:runlevels:action:process # Default runlevel id:3:initdefault: # System initialization si::sysinit:/etc/rc.d/rc.sysinit # Runlevel scripts l0:0:wait:/etc/rc.d/rc 0 l1:1:wait:/etc/rc.d/rc 1 l2:2:wait:/etc/rc.d/rc 2 l3:3:wait:/etc/rc.d/rc 3 l4:4:wait:/etc/rc.d/rc 4 l5:5:wait:/etc/rc.d/rc 5 l6:6:wait:/etc/rc.d/rc 6 # Terminal gettys 1:2345:respawn:/sbin/mingetty tty1 2:2345:respawn:/sbin/mingetty tty2
Runlevels
# Standard runlevels 0 - Halt/Shutdown 1 - Single user mode 2 - Multiuser without network 3 - Full multiuser with network 4 - Unused/Custom 5 - Multiuser with GUI 6 - Reboot # Change runlevel init 3 # Switch to runlevel 3 telinit 5 # Alternative command # Check current runlevel runlevel who -r
Service Scripts
#!/bin/bash # /etc/init.d/myservice # chkconfig: 345 85 15 # description: My custom service # Source functions . /etc/rc.d/init.d/functions case "$1" in start) echo -n "Starting myservice: " daemon /usr/bin/myservice touch /var/lock/subsys/myservice echo ;; stop) echo -n "Stopping myservice: " killproc myservice rm -f /var/lock/subsys/myservice echo ;; status) status myservice ;; restart) $0 stop $0 start ;; *) echo "Usage: $0 {start|stop|status|restart}" exit 1 esac exit 0
Service Management
# Start/stop services service httpd start service httpd stop service httpd restart service httpd status # Enable/disable at boot chkconfig httpd on chkconfig httpd off chkconfig --list # Update RC scripts update-rc.d apache2 enable update-rc.d apache2 disable
systemd: The Modern Powerhouse
Unit Files
# /etc/systemd/system/myapp.service [Unit] Description=My Application Service Documentation=https://myapp.example.com/docs After=network.target postgresql.service Requires=postgresql.service Wants=redis.service [Service] Type=notify ExecStartPre=/usr/bin/myapp-check ExecStart=/usr/bin/myapp --config /etc/myapp/config.yaml ExecReload=/bin/kill -HUP $MAINPID ExecStop=/usr/bin/myapp-shutdown Restart=on-failure RestartSec=5s User=myapp Group=myapp WorkingDirectory=/var/lib/myapp # Security settings PrivateTmp=true NoNewPrivileges=true ReadOnlyPaths=/etc ReadWritePaths=/var/lib/myapp ProtectSystem=strict ProtectHome=true # Resource limits LimitNOFILE=65536 LimitNPROC=4096 MemoryLimit=2G CPUQuota=50% [Install] WantedBy=multi-user.target
Unit Types
# Service units (.service) - System services systemd-networkd.service # Socket units (.socket) - Network sockets sshd.socket # Target units (.target) - Group of units multi-user.target # Mount units (.mount) - Filesystem mount points home.mount # Timer units (.timer) - Scheduled tasks backup.timer # Path units (.path) - Path monitoring config-monitor.path # Slice units (.slice) - Resource control groups user.slice # Device units (.device) - Device activation dev-sda1.device # Swap units (.swap) - Swap space swap.swap # Automount units (.automount) - On-demand mounting mnt-backup.automount
systemd Commands
# Service management systemctl start nginx systemctl stop nginx systemctl restart nginx systemctl reload nginx systemctl status nginx # Enable/disable services systemctl enable nginx systemctl disable nginx systemctl is-enabled nginx # System state systemctl is-system-running systemctl list-units systemctl list-units --failed systemctl list-unit-files # Targets (similar to runlevels) systemctl get-default systemctl set-default graphical.target systemctl isolate multi-user.target # Dependencies systemctl list-dependencies nginx systemctl show nginx # Logs journalctl -u nginx journalctl -f # Follow mode journalctl -b # Current boot journalctl --since "2024-01-01" journalctl -p err # Error priority # Analyze boot systemd-analyze systemd-analyze blame systemd-analyze critical-chain systemd-analyze plot > boot.svg
Timer Units (cron replacement)
# /etc/systemd/system/backup.timer [Unit] Description=Daily Backup Timer Requires=backup.service [Timer] OnCalendar=daily OnCalendar=*-*-* 02:00:00 Persistent=true RandomizedDelaySec=30min [Install] WantedBy=timers.target # /etc/systemd/system/backup.service [Unit] Description=System Backup [Service] Type=oneshot ExecStart=/usr/local/bin/backup.sh
Socket Activation
# /etc/systemd/system/myapp.socket [Unit] Description=MyApp Socket [Socket] ListenStream=8080 Accept=false [Install] WantedBy=sockets.target # Service starts on-demand when socket receives connection
OpenRC: The Elegant Alternative
Service Scripts
#!/sbin/openrc-run # /etc/init.d/myservice description="My custom service" command="/usr/bin/myservice" command_args="--config /etc/myservice/config" pidfile="/run/myservice.pid" command_background=true command_user="myservice:myservice" depend() { need net use logger after firewall before nginx } start_pre() { checkpath --directory --owner myservice:myservice /var/lib/myservice } stop_post() { rm -f /var/cache/myservice/* } reload() { ebegin "Reloading ${RC_SVCNAME}" start-stop-daemon --signal HUP --pidfile "${pidfile}" eend $? }
Runlevel Management
# Runlevels structure /etc/runlevels/ ├── boot/ # Boot-time services ├── default/ # Default runlevel ├── nonetwork/ # No network runlevel ├── shutdown/ # Shutdown services └── sysinit/ # System initialization # Add service to runlevel rc-update add nginx default rc-update del nginx default # List services rc-status rc-status --all # Service control rc-service nginx start rc-service nginx stop rc-service nginx restart
Comparison: SysV vs systemd vs OpenRC
Boot Performance
# Measure boot time # SysV Init: Sequential startup Boot time: ~30-60 seconds (typical) # systemd: Parallel startup systemd-analyze Startup finished in 3.241s (firmware) + 2.123s (loader) + 4.567s (kernel) + 8.234s (userspace) = 18.165s # OpenRC: Dependency-based parallel rc-status --time
Service Dependencies
# SysV Init: Numeric ordering /etc/rc3.d/ S01networking -> ../init.d/networking S02postgresql -> ../init.d/postgresql S03nginx -> ../init.d/nginx # systemd: Explicit dependencies After=network.target postgresql.service Requires=postgresql.service Wants=redis.service # OpenRC: Dependency functions depend() { need net postgresql want redis after firewall }
Resource Control
# SysV Init: Limited (via ulimit) ulimit -n 65536 # File descriptors nice -n 10 /usr/bin/myapp # Priority # systemd: Comprehensive cgroup integration CPUQuota=50% MemoryLimit=2G TasksMax=4096 IOWeight=100 # OpenRC: Basic cgroup support rc_cgroup_mode="unified" rc_cgroup_memory="2G" rc_cgroup_cpu="50%"
Process Supervision
systemd Restart Policies
[Service] Restart=always # Always restart Restart=on-failure # Restart on non-zero exit Restart=on-abnormal # Restart on signal/timeout Restart=on-abort # Restart on unclean signal Restart=on-watchdog # Restart on watchdog timeout RestartSec=5s # Delay between restarts StartLimitBurst=5 # Max restarts in interval StartLimitIntervalSec=60s
Watchdog Support
// Application with systemd watchdog #include <systemd/sd-daemon.h> int main() { // Notify systemd we're ready sd_notify(0, "READY=1"); // Get watchdog interval uint64_t usec; if (sd_watchdog_enabled(0, &usec) > 0) { uint64_t interval = usec / 2; // Ping at half interval while (running) { // Do work... // Ping watchdog sd_notify(0, "WATCHDOG=1"); usleep(interval); } } // Notify stopping sd_notify(0, "STOPPING=1"); return 0; }
Advanced Features
systemd Generators
# Generators create unit files dynamically at boot /usr/lib/systemd/system-generators/ ├── systemd-fstab-generator # Creates mount units from /etc/fstab ├── systemd-cryptsetup-generator # Encrypted volumes └── systemd-gpt-auto-generator # GPT partition discovery # Custom generator #!/bin/bash # /etc/systemd/system-generators/custom-generator UNIT_DIR="$1" cat > "$UNIT_DIR/generated.service" <<EOF [Unit] Description=Generated Service [Service] ExecStart=/usr/bin/generated-app EOF
Drop-in Directories
# Override or extend unit files without modifying originals /etc/systemd/system/nginx.service.d/ └── override.conf # Create drop-in systemctl edit nginx # Contents of override.conf [Service] # Override specific settings MemoryLimit=4G Environment="CUSTOM_VAR=value" # View effective configuration systemctl cat nginx
Template Units
# /etc/systemd/system/app@.service [Unit] Description=App Instance %i [Service] ExecStart=/usr/bin/app --instance %i User=app-%i [Install] WantedBy=multi-user.target # Usage systemctl start app@web.service systemctl start app@api.service systemctl enable app@{web,api,worker}.service
Migration Guide
Converting SysV to systemd
# SysV Init script #!/bin/bash # /etc/init.d/oldservice case "$1" in start) /usr/bin/oldservice --daemon ;; stop) killall oldservice ;; esac # Equivalent systemd unit # /etc/systemd/system/oldservice.service [Unit] Description=Old Service (migrated) After=network.target [Service] Type=forking ExecStart=/usr/bin/oldservice --daemon ExecStop=/usr/bin/killall oldservice PIDFile=/var/run/oldservice.pid [Install] WantedBy=multi-user.target
Troubleshooting
Common Issues
# Service fails to start systemctl status failed-service journalctl -u failed-service -n 50 systemctl reset-failed # Dependency issues systemctl list-dependencies --reverse service systemd-analyze verify /etc/systemd/system/*.service # Boot hangs # Add to kernel parameters: systemd.log_level=debug systemd.log_target=console # Emergency/Rescue mode systemctl emergency # Minimal environment systemctl rescue # Single user mode # Mask problematic services systemctl mask problem.service
Best Practices
- Use native unit files - Avoid SysV compatibility mode
- Set proper dependencies - Define After/Requires correctly
- Implement graceful shutdown - Handle SIGTERM properly
- Use security features - Sandboxing, namespaces, capabilities
- Monitor with journald - Centralized, structured logging
- Test unit files - Use systemd-analyze verify
- Document services - Add Description and Documentation
- Handle failures - Configure restart policies
Conclusion
The init system is the backbone of your Linux system, orchestrating the complex dance of services that bring your machine to life. While SysV Init served us well for decades with its simple, script-based approach, systemd has revolutionized system management with parallel startup, sophisticated dependency handling, and integrated logging.
Our interactive visualization demonstrated how these different philosophies translate into real-world boot sequences and service management. Whether you prefer the simplicity of SysV, the power of systemd, or the elegance of OpenRC, understanding your init system is crucial for effective Linux administration.
Remember: the best init system is the one that meets your needs and that you understand well enough to troubleshoot at 3 AM.
Next: Kernel Modules → ← Back to Boot Process