Manage Linux services with systemd: systemctl, journalctl, units and timers, including the differences between Debian, Ubuntu and RHEL!
Linux
Published on
Karl Certa Systems & network administrator5 years in IT, from support to sysadmin, now Ops. Learning cloud, and writing everything down here. Focused on IaC & cloud AWS SAA, Kubernetes next LinkedIn karlcerta.fr GitHub Karl Certa
Systemd is the service manager and PID 1 of nearly every Linux distribution. It starts services, handles their dependencies, collects their logs in the journal and schedules tasks through its timers.
🐧 What changes between distributions
The systemctl commands are the same everywhere. What varies is the systemd version shipped, so the options available, and the choices each distribution makes. To check yours: systemctl --version.
📌 Distribution
📦 Systemd version
⚠️ Distribution specifics
🌀 Debian 12 bookworm
252
rsyslog is no longer installed by default, no /var/log/syslog
🌀 Debian 13 trixie
257
Default config moved under /usr/lib/systemd/
🟠 Ubuntu 22.04 LTS
249
SSH uses socket activation since 22.10
🟠 Ubuntu 24.04 LTS
255
ssh.socket listens instead of ssh.service
🟠 Ubuntu 26.04 LTS
259
Support for legacy cgroup v1 removed for good
🔴 RHEL / Rocky / Alma 9
252
SysV scripts are still supported
🔴 RHEL / Rocky / Alma 10
257
SysV scripts deprecated, convert them to units
Alpine and Devuan are the exception: they run OpenRC or sysvinit, so none of the commands here apply.
⚙️ Service management
📌 Action
🧠 Command
▶️ Start
sudo systemctl start <unit>
⏹️ Stop
sudo systemctl stop <unit>
🔁 Restart
sudo systemctl restart <unit>
🔄 Reload the config
sudo systemctl reload <unit>
🚀 Enable at boot
sudo systemctl enable <unit>
⚡ Enable and start
sudo systemctl enable --now <unit>
🚫 Disable at boot
sudo systemctl disable --now <unit>
🔒 Block any start
sudo systemctl mask <unit>
🔓 Remove the block
sudo systemctl unmask <unit>
♻️ Pick up a modified unit
sudo systemctl daemon-reload
🏷️ Service names per distribution
This is where commands copied between distributions break.
📌 Service
🌀 Debian / Ubuntu
🔴 RHEL / Rocky / Alma / Fedora
🟢 openSUSE
🔐 SSH
ssh (+ ssh.socket on Ubuntu)
sshd
sshd
⏰ Cron
cron
crond
cron
🌐 Apache
apache2
httpd
apache2
🛡️ Firewall
ufw or nftables
firewalld
firewalld
🕐 Time sync
systemd-timesyncd
chronyd
chronyd
🔍 Status and inventory
📌 Action
🧠 Command
📊 Detailed status
systemctl status <unit>
✅ Is it running?
systemctl is-active <unit>
🚀 Is it enabled at boot?
systemctl is-enabled <unit>
📋 Loaded services
systemctl list-units --type=service
🗂️ All installed services
systemctl list-unit-files --type=service
❌ Failed services
systemctl --failed
📄 Effective unit content
systemctl cat <unit>
📜 Reading a service journal
journalctl is part of systemd. The systemd-journald daemon captures the output of every service and indexes it per unit, which is what makes the -u filter possible. It picks up where systemctl status stops, since that only shows the last ten lines.
📌 Action
🧠 Command
📖 Logs of a service
journalctl -u nginx
🔟 Last 50 lines
journalctl -u nginx -n 50 --no-pager
👀 Follow live
journalctl -u nginx -f
🔀 Follow several services
journalctl -f -u nginx -u php8.2-fpm
🕐 Since a point in time
journalctl -u nginx --since "2 hours ago"
🔴 Errors only
journalctl -u nginx -p err
🥾 Current / previous boot
journalctl -b / journalctl -b -1
🆘 Last errors with context
journalctl -xe
For journal disk usage and trimming, see the Disk space cheatsheet.
📄 Anatomy of a unit
[Unit]Description=Application backupAfter=network-online.target # Waits for the network to be truly reachableWants=network-online.target # Soft dependency, not blocking[Service]Type=simple # simple: process stays in the foreground # oneshot: runs then exitsUser=backup # Never leave root without a reasonExecStart=/opt/scripts/backup.shRestart=on-failure # no, on-failure, alwaysRestartSec=30 # Delay before restarting[Install]WantedBy=multi-user.target # Target that pulls the service in at boot
📌 Action
🧠 Command
➕ Add an override
sudo systemctl edit <unit>
📝 Copy the whole unit
sudo systemctl edit --full <unit>
🔙 Back to the original
sudo systemctl revert <unit>
📂 Locations and priority
📌 Path
🧠 Purpose
📊 Priority
/etc/systemd/system/
Your units and overrides
Highest
/usr/lib/systemd/system/
Units shipped by packages
Lowest
~/.config/systemd/user/
User units (--user)
Session
On Debian and Ubuntu, /lib/systemd/system/ is still visible: since the /usr merge it is only a symlink to /usr/lib/systemd/system/.
⏱️ Timers, the cron alternative
📌 Action
🧠 Command
📋 List active timers
systemctl list-timers
▶️ Enable a timer
sudo systemctl enable --now backup.timer
🧪 Trigger it manually
sudo systemctl start backup.service
📅 Test an expression
systemd-analyze calendar "Mon *-*-* 02:30:00"
# /etc/systemd/system/backup.timer[Unit]Description=Daily backup[Timer]OnCalendar=*-*-* 02:30:00Persistent=true # Catches up a missed run if the machine was off[Install]WantedBy=timers.target