Stage 3 · Build
systemd Service Management & Resource Control
Reloads, Restarts & Watchdogs
ExecReload, RestartSec, WatchdogSec, sd_notify, and zero-downtime restart patterns.
Reload vs Restart
Reload applies configuration changes without stopping the service. Restart stops and starts the service. Reload is preferred when the application supports it because it avoids downtime.
| Operation | Downtime | Use Case |
|---|---|---|
| reload | None | Configuration changes |
| restart | Brief | Binary updates, major changes |
| try-reload-or-restart | None or brief | Best of both |
# Reload (no downtime)
sudo systemctl reload nginx
sudo systemctl reload sshd
# Restart (brief downtime)
sudo systemctl restart nginx
# Try reload, fall back to restart
sudo systemctl try-reload-or-restart nginx
# Check if reload is supported
systemctl show nginx -p ExecReload
# ExecReload=/bin/kill -HUP $MAINPID
# Force restart
sudo systemctl kill nginx
sudo systemctl start nginxUse reload for configuration changes. Use restart for binary updates. try-reload-or-restart is the safest option.
ExecReload Configuration
# Signal-based reload (most common)
[Service]
ExecReload=/bin/kill -HUP $MAINPID
# Command-based reload
[Service]
ExecReload=/usr/bin/myapp --reload-config
# Multiple reload commands
[Service]
ExecReload=/bin/kill -HUP $MAINPID
ExecReload=/bin/kill -USR1 $MAINPID
# Reload with validation
[Service]
ExecReloadPre=/usr/bin/myapp --validate-config
ExecReload=/bin/kill -HUP $MAINPID
# Check reload behavior
systemctl show nginx -p ExecReload
# ExecReload=/bin/kill -HUP $MAINPID
systemctl show myapp -p ExecReload
# (not set) # reload not supportedExecReload tells systemd how to reload the service. Most services use SIGHUP. Some use custom reload commands.
Watchdog Monitoring
# WatchdogSec enables systemd watchdog
[Service]
WatchdogSec=30
# Service must notify systemd every 30 seconds
# If notification is missed, service is restarted
# The service must call sd_notify() with WATCHDOG=1
# This is typically done in the application code
# Watchdog with separate check
[Service]
WatchdogSec=30
NotifyAccess=main
# Restart on watchdog timeout
Restart=on-watchdog
RestartSec=5
# Check watchdog status
systemctl show myapp -p WatchdogUSec
# WatchdogUSec=30s
systemctl show myapp -p WatchdogTimestamp
# WatchdogTimestamp=Mon 2024-01-15 10:30:00 UTCWatchdog monitoring detects hung processes. The service must periodically notify systemd. If the notification is missed, systemd restarts the service.
sd_notify Protocol
# sd_notify messages
# READY=1 — Service is ready (for Type=notify)
# RELOADING=1 — Service is reloading
# STOPPING=1 — Service is stopping
# WATCHDOG=1 — Watchdog ping
# WATCHDOG=1 — Watchdog ping
# STATUS=... — Status text
# ERRNO=... — Error number
# BUSERROR=... — D-Bus error
# In application code (Python example):
# import sdnotify
# notifier = sdnotify.SystemdNotifier()
# notifier.notify("READY=1")
# notifier.notify("WATCHDOG=1")
# In shell script:
systemd-notify --ready
systemd-notify WATCHDOG=1
systemd-notify "STATUS=Processing request..."
# Notify access levels
[Service]
NotifyAccess=all # Allow any process to notify
NotifyAccess=main # Only main PID can notify
NotifyAccess=exec # Only exec'd processes can notifysd_notify lets applications communicate state to systemd. Use it for readiness detection and watchdog keepalives.
Zero-Downtime Patterns
# Pattern 1: ExecReload with graceful reload
[Service]
ExecStart=/opt/myapp/bin/server
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
# Pattern 2: Pre-start with config validation
[Service]
ExecStartPre=/opt/myapp/bin/server --validate-config
ExecStart=/opt/myapp/bin/server
Restart=on-failure
# Pattern 3: Socket activation for connection draining
[Service]
Type=notify
Accept=no
# systemd holds connections until service is ready
# Pattern 4: Try-reload-or-restart
# systemd tries reload first, falls back to restart
sudo systemctl try-reload-or-restart myapp
# Pattern 5: Stop → Wait → Start (manual control)
sudo systemctl stop myapp
# Wait for connections to drain
sleep 10
sudo systemctl start myappZero-downtime restarts require application support. Use ExecReload for graceful reloads, socket activation for connection draining.
Restart Management
# Restart policy
Restart=on-failure
RestartSec=5
# Rate limiting
StartLimitBurst=5
StartLimitIntervalSec=300
# Check restart count
systemctl show myapp -p NRestarts
# NRestarts=3
# Reset restart counter
systemctl reset-failed myapp
# View restart history
journalctl -u myapp | grep -i "started|stopped|failed"
# Override restart for specific cases
[Service]
Restart=on-failure
RestartSec=5
# Don't restart on specific exit codes
RestartPreventExitStatus=1 2 3
# Restart on specific exit codes
RestartForceExitStatus=SIGKILLRate limiting prevents restart loops. RestartPreventExitStatus prevents restart on specific exit codes. Always set RestartSec to avoid rapid cycling.
Type=notify with sd_notify READY=1 gives systemd accurate readiness information. This prevents routing traffic to a service that is not ready.
WatchdogSec only works if the application calls sd_notify WATCHDOG=1. Without application support, the watchdog triggers and restarts the service.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.