Linux System Services with systemd — Services, Targets, Timers & Startup
Posted: Sat Jun 13, 2026 11:32 am
Linux System Services with systemd — Services, Targets, Timers & Startup
A clear, beginner-friendly guide to managing what runs on your system, with copy-ready commands (AlmaLinux 9 / RHEL 9)
─────────────────────────────────────────
The big idea — "units"
systemd manages everything as units. A unit is just "one thing systemd looks after." The types you'll meet most:
─────────────────────────────────────────
1 Service Management — start, stop, check
These are the everyday commands. Replace nginx with any service name.
The core four
Reload without a full restart
Quick yes/no checks
Tip: "status" is your best friend — the top line shows running/stopped, and the bottom shows the last log lines, which usually explain any failure.
─────────────────────────────────────────
2 Startup Services — what runs at boot
"Start now" and "start at boot" are two separate things. start runs it this moment; enable makes it come back automatically after a reboot.
Control boot behaviour
See what starts at boot
Stop something from ever starting (stronger than disable)
Tip: Fewer enabled services = faster boot and smaller attack surface. Audit the enabled list and disable anything you don't actually need.
─────────────────────────────────────────
3 Targets — the system's "mode"
A target is the overall state the system boots into. If you've heard of old "runlevels," targets replace them. The two you care about most:
Switch mode right now (without rebooting)
Tip: On a server you usually want multi-user.target as default — no point loading a graphical desktop you never use.
─────────────────────────────────────────
4 Timers — scheduling jobs the modern way
A timer runs a service on a schedule — it's the systemd replacement for cron. The advantage: built-in logging, dependency handling, and it can catch up on jobs missed while the machine was off.
A timer always comes in two files with the same name: a .timer (when to run) and a .service (what to run).
See existing timers
Example — run a backup script every day at 2am
Create the service file /etc/systemd/system/backup.service:
Create the timer file /etc/systemd/system/backup.timer:
Enable and start the timer
Tip: Persistent=true means if the machine was off at 2am, the job runs as soon as it powers back on. That's something plain cron can't do.
─────────────────────────────────────────
5 Reading Logs — journalctl
When a service misbehaves, its logs live in the systemd journal.
Tip: "journalctl -xe" right after a failed start gives the most detail on why a service refused to come up.
─────────────────────────────────────────
Quick Reference Cheat Sheet
Which services do you keep enabled on your servers — and have you moved any cron jobs over to systemd timers yet? Share your setup below.
A clear, beginner-friendly guide to managing what runs on your system, with copy-ready commands (AlmaLinux 9 / RHEL 9)
─────────────────────────────────────────
─────────────────────────────────────────What is systemd, in plain words?
systemd is the "manager" that boots your Linux system and keeps background programs (services) running. When you start a web server, mount disks, or schedule a job, systemd is the thing actually doing it behind the scenes. The command you use to talk to it is systemctl.
The big idea — "units"
systemd manages everything as units. A unit is just "one thing systemd looks after." The types you'll meet most:
- .service — a background program (e.g. sshd.service, nginx.service)
- .target — a group of units / a system state (e.g. multi-user.target)
- .timer — a schedule that triggers a service (the modern cron)
- .socket / .mount — network sockets and mounted filesystems
─────────────────────────────────────────
1 Service Management — start, stop, check
These are the everyday commands. Replace nginx with any service name.
The core four
Code: Select all
systemctl start nginx # start it now
systemctl stop nginx # stop it now
systemctl restart nginx # stop then start (full restart)
systemctl status nginx # is it running? show recent logsCode: Select all
systemctl reload nginx # re-read config, keep running (no downtime)
# use restart only if reload isn't supported by the serviceCode: Select all
systemctl is-active nginx # active / inactive
systemctl is-enabled nginx # starts at boot? enabled / disabled─────────────────────────────────────────
2 Startup Services — what runs at boot
"Start now" and "start at boot" are two separate things. start runs it this moment; enable makes it come back automatically after a reboot.
Control boot behaviour
Code: Select all
systemctl enable nginx # start automatically at every boot
systemctl disable nginx # don't start at boot
systemctl enable --now nginx # enable AND start right now (one step)Code: Select all
systemctl list-unit-files --type=service # all services + enabled/disabled
systemctl list-unit-files --state=enabled # only the enabled onesCode: Select all
systemctl mask nginx # block it completely, even manual start
systemctl unmask nginx # undo the mask─────────────────────────────────────────
3 Targets — the system's "mode"
A target is the overall state the system boots into. If you've heard of old "runlevels," targets replace them. The two you care about most:
- multi-user.target — full system, networking, no graphical desktop (servers)
- graphical.target — everything above PLUS a desktop login screen
Code: Select all
systemctl get-default # what it boots into now
systemctl set-default multi-user.target # boot to console (no GUI) - typical server
systemctl set-default graphical.target # boot to desktopCode: Select all
systemctl isolate multi-user.target # drop to console now
systemctl isolate graphical.target # bring up the desktop now─────────────────────────────────────────
4 Timers — scheduling jobs the modern way
A timer runs a service on a schedule — it's the systemd replacement for cron. The advantage: built-in logging, dependency handling, and it can catch up on jobs missed while the machine was off.
A timer always comes in two files with the same name: a .timer (when to run) and a .service (what to run).
See existing timers
Code: Select all
systemctl list-timers --all # all timers, next/last run timesCreate the service file /etc/systemd/system/backup.service:
Code: Select all
[Unit]
Description=Daily backup job
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.shCode: Select all
[Unit]
Description=Run backup daily at 2am
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.targetCode: Select all
systemctl daemon-reload # tell systemd about the new files
systemctl enable --now backup.timer
systemctl list-timers backup.timer─────────────────────────────────────────
5 Reading Logs — journalctl
When a service misbehaves, its logs live in the systemd journal.
Code: Select all
journalctl -u nginx # all logs for one service
journalctl -u nginx -e # jump to the newest entries
journalctl -u nginx -f # live tail (follow new logs)
journalctl -b # logs since the last boot
journalctl -p err -b # only errors since boot─────────────────────────────────────────
Quick Reference Cheat Sheet
- Start / stop — systemctl start|stop nginx
- Restart / reload — systemctl restart|reload nginx
- Status — systemctl status nginx
- Enable at boot — systemctl enable --now nginx
- Disable at boot — systemctl disable nginx
- Is it running? — systemctl is-active nginx
- Starts at boot? — systemctl is-enabled nginx
- List enabled — systemctl list-unit-files --state=enabled
- Default target — systemctl get-default
- Set console boot — systemctl set-default multi-user.target
- List timers — systemctl list-timers --all
- Reload unit files — systemctl daemon-reload
- Service logs — journalctl -u nginx -e
- Live logs — journalctl -u nginx -f
Which services do you keep enabled on your servers — and have you moved any cron jobs over to systemd timers yet? Share your setup below.