Systemd
Reference: systemd Docs · Freedesktop systemd Man Pages · Debian Wiki — systemd
systemctl — Service Management
Common Commands
# Start / stop / restart a service
sudo systemctl start servicename
sudo systemctl stop servicename
sudo systemctl restart servicename
# Reload config without full restart (if supported)
sudo systemctl reload servicename
# Enable at boot / disable
sudo systemctl enable servicename
sudo systemctl disable servicename
# Enable and start in one command
sudo systemctl enable --now servicename
# Check status
systemctl status servicename
# Is it running?
systemctl is-active servicename
# Is it enabled at boot?
systemctl is-enabled servicename
System State
# List all running services
systemctl list-units --type=service --state=running
# List all failed units
systemctl --failed
# List all units (running, stopped, failed)
systemctl list-units --type=service
# Reboot / shutdown / halt
sudo systemctl reboot
sudo systemctl poweroff
sudo systemctl halt
journalctl — Log Viewing
journalctl queries the systemd journal — the central log store for all services managed by systemd.
# View all logs (oldest first)
journalctl
# Follow live (like tail -f)
journalctl -f
# Logs for a specific service
journalctl -u servicename
# Follow logs for a service live
journalctl -fu servicename
# Last 50 lines for a service
journalctl -u servicename -n 50
# Since last boot
journalctl -b
# Logs from a previous boot (-1 = one boot ago)
journalctl -b -1
# Logs since a specific time
journalctl --since "2024-01-01 12:00:00"
journalctl --since "1 hour ago"
# Filter by priority (0=emerg, 3=err, 4=warning, 6=info, 7=debug)
journalctl -p err
# Show kernel messages
journalctl -k
# Disk space used by journal
journalctl --disk-usage
# Vacuum journal to limit size
sudo journalctl --vacuum-size=500M
sudo journalctl --vacuum-time=7d
Writing a Custom Service Unit
Service unit files live in /etc/systemd/system/. Units here override anything in /lib/systemd/system/.
Simple Service Example
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
Documentation=https://example.com/docs
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=myappuser
Group=myappuser
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/myapp --config /etc/myapp/config.yaml
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
# Environment variables
Environment=NODE_ENV=production
# Or load from file
EnvironmentFile=/etc/myapp/.env
[Install]
WantedBy=multi-user.target
# After creating the file, reload systemd and enable
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
Service Types
| Type | Use Case |
|---|---|
simple |
Process stays in foreground (most common) |
forking |
Process forks and parent exits (traditional daemons) |
oneshot |
Runs once and exits (scripts, setup tasks) |
notify |
Like simple but process signals when ready |
idle |
Like simple but waits until other jobs finish |
Restart Policies
Restart=no # Never restart (default)
Restart=on-failure # Restart only on non-zero exit
Restart=always # Always restart
Restart=on-abnormal # Restart on signal, timeout, watchdog
Timer Units (Systemd Cron Alternative)
Timers are the systemd alternative to cron. They require two files: a .timer and a matching .service.
# /etc/systemd/system/backup.service
[Unit]
Description=Run Backup Script
[Service]
Type=oneshot
User=youruser
ExecStart=/usr/local/bin/backup.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Daily Backup Timer
Requires=backup.service
[Timer]
OnCalendar=daily
OnCalendar=*-*-* 02:00:00 # Every day at 2am
Persistent=true # Run if missed (e.g. system was off)
[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
# Check timer status and next run time
systemctl list-timers
Targets (Runlevels)
Targets group units together — roughly equivalent to SysV runlevels.
# View current target
systemctl get-default
# Set default target
sudo systemctl set-default multi-user.target # no GUI
sudo systemctl set-default graphical.target # with GUI
# Common targets
# multi-user.target → like runlevel 3 (multi-user, no GUI)
# graphical.target → like runlevel 5 (multi-user + GUI)
# rescue.target → single user / rescue mode
# emergency.target → minimal emergency shell
Quick Troubleshooting
# Service won't start — see why
sudo systemctl status servicename
journalctl -u servicename -n 50 --no-pager
# Find unit file location
systemctl cat servicename
# Show all properties of a unit
systemctl show servicename
# Check for dependency issues
systemctl list-dependencies servicename