systemd Service Management¶
systemd is the init system and service manager on every modern Linux
distribution. This guide covers controlling services, reading logs, writing
your own units, and replacing cron with timers.
Tested on
AlmaLinux 9 / RHEL 9, but systemctl and journalctl behave identically
on Debian/Ubuntu.
Controlling services with systemctl¶
sudo systemctl start nginx # start now
sudo systemctl stop nginx # stop now
sudo systemctl restart nginx # stop + start
sudo systemctl reload nginx # reload config without dropping connections
sudo systemctl status nginx # current state + recent log lines
Enable vs. start¶
These are independent concepts that trip people up:
- start — run the service right now (does not survive reboot)
- enable — start it automatically at boot (does not run it now)
sudo systemctl enable nginx # start at boot, later
sudo systemctl enable --now nginx # enable AND start now (the usual one)
sudo systemctl disable --now nginx # disable AND stop now
Is it running? Will it start at boot?
Find and inspect units¶
systemctl list-units --type=service # currently loaded services
systemctl list-units --type=service --state=failed # what's broken
systemctl list-unit-files --type=service # all installed, with enable state
systemctl cat nginx # show the effective unit file(s)
Reading logs with journalctl¶
journalctl queries the systemd journal — structured, indexed logs for every
unit.
journalctl -u nginx # all logs for the nginx unit
journalctl -u nginx -f # follow live (like tail -f)
journalctl -u nginx -n 100 # last 100 lines
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx -p err # only error priority and worse
journalctl -u nginx -b # only this boot
Triage a failed service fast
Useful priority levels for -p: emerg, alert, crit, err, warning,
notice, info, debug.
Writing your own service unit¶
Suppose you have an app at /opt/myapp/run that should run as a dedicated user
and restart on failure. Create /etc/systemd/system/myapp.service:
[Unit]
Description=My Application
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/run
Restart=on-failure
RestartSec=5s
# Light sandboxing — cheap wins
NoNewPrivileges=true
ProtectSystem=full
ProtectHome=true
[Install]
WantedBy=multi-user.target
After creating or editing any unit file, reload the systemd manager so it picks up the change:
daemon-reload is mandatory
systemd caches unit files in memory. Edits to .service files have no
effect until you run sudo systemctl daemon-reload.
Override a unit without editing it¶
Don't edit vendor-shipped units in /usr/lib/systemd/system/ — they get
overwritten on package upgrade. Use a drop-in instead:
This opens an editor for /etc/systemd/system/nginx.service.d/override.conf,
where you add only the directives you want to change:
Scheduling work with timers¶
systemd timers are a modern replacement for cron, with the advantage of full journald logging and dependency handling.
Create the job as a normal service, /etc/systemd/system/backup.service:
Then a timer, /etc/systemd/system/backup.timer:
[Unit]
Description=Run nightly backup at 02:30
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true # run on next boot if the machine was off at 02:30
RandomizedDelaySec=300 # spread load — fire within 5 min of the target
[Install]
WantedBy=timers.target
Enable the timer (not the service):
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers # see next run time for all timers
Validate an OnCalendar expression
Verify your work¶
systemctl is-active myapp && echo "running"
systemctl is-enabled myapp && echo "starts at boot"
systemd-analyze verify /etc/systemd/system/myapp.service # lint the unit
systemctl list-timers --all
Summary¶
enable= at boot,start= now;enable --nowdoes both.- Use
journalctl -u <unit> -f/-eto follow and triage logs. - Put custom units in
/etc/systemd/system/, override vendor units withsystemctl edit, and alwaysdaemon-reloadafter changes. - Prefer systemd timers over cron for logged, dependency-aware scheduling.