systemctl: Service Management
- Explain what systemd and units are, and why services are managed centrally
- Inspect a service's current and boot-time state with systemctl — and keep the two states separate in your head
- Start, stop, restart, and reload services at runtime
- Make a service survive a reboot — the distinction RHCSA tests most
- Diagnose a service that won't start using status and journalctl -u
- Know where unit files live, and when daemon-reload and mask enter the picture
Why services need a manager
Understand what systemd does and the vocabulary you'll use throughout
A service is a program that runs in the background — a web server, a database, an SSH daemon. Unlike the commands you type, nobody is sitting at a terminal to launch these. Someone has to start them at the right time, in the right order, restart them if they crash, and bring them back after a reboot.
That someone is systemd, the first process Linux starts at boot (PID 1 — run
ps -p 1and there it is). Think of systemd as an air-traffic controller for your machine: every background program is an aircraft, and systemd decides what takes off, in what order, and what gets cleared to fly again after the airport reopens (a reboot).systemd describes each thing it manages as a unit. The type you'll meet first is the service unit, written
name.service— for examplenginx.service(the.servicesuffix is optional when typing;nginxworks). There are other unit types — timers, mount points, targets — but services are the daily bread. You talk to systemd through one command:systemctl.One idea underpins this whole lesson, so meet it before any command: a service has two completely independent states.
- Is it running right now? — the runtime state (
active/inactive). - Will it start itself at the next boot? — the boot state (
enabled/disabled).
Every combination is possible: running-but-disabled (works until the next reboot, then silently gone), stopped-but-enabled (down now, will return at boot), and so on. Most real-world service confusion — and most graded-lab point losses — comes from checking one of these states and assuming it implies the other. It never does.
Check yourself
A service is 'active' right now. What, if anything, does that tell you about whether it will be running after a reboot?
- Is it running right now? — the runtime state (
Inspect before you touch
Read a service's state before changing anything
The golden rule of operations: look before you leap. Before you restart anything — especially on a machine you share with other admins or graders — establish what state it's in now.
systemctl statusis the full report; it answers both of the two questions at once, if you know which words to read.systemctl status nginx○ nginx.service - The nginx HTTP server Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; preset: disabled) Active: inactive (dead)Two words carry the meaning, on two different lines. Active: inactive (dead) — not running right now (runtime state). disabled — tucked inside the Loaded: line — will not start at the next boot (boot state). This service is asleep and not set to wake up on its own. The Loaded: line also shows you where the unit file lives — more on that later. The full status report is for humans. In scripts — and for quick checks — you want a one-word answer, and systemctl has a dedicated question for each state:
systemctl is-active nginx; systemctl is-enabled nginxinactive disabled
is-active reports the runtime state; is-enabled reports the boot state. Each also sets an exit code (0 when active/enabled), so they slot straight into if statements — if systemctl is-active -q nginx; then ...is the standard health-check idiom. Keeping these two questions separate is the single most important habit in this lesson.systemctl list-units --type=service --state=running | head -6UNIT LOAD ACTIVE SUB DESCRIPTION chronyd.service loaded active running NTP client/server crond.service loaded active running Command Scheduler dbus-broker.service loaded active running D-Bus System Message Bus sshd.service loaded active running OpenSSH server daemon systemd-journald.service loaded active running Journal Service
- --type=service
- only service units — filter out mounts, sockets, timers
- --state=running
- only units in this state; try failed for the trouble list
The wide view: every service currently running. Useful when you land on an unfamiliar box and want to know what it does — a machine's running services are its job description. Swap --state=running for --state=failed and you get the trouble list instead. Check yourself
Which subcommand tells you whether a service will start automatically after a reboot?
Start, stop, restart (runtime)
Change what is running right now — without touching boot behaviour
Now the verbs that change things. This family acts immediately, on the currently-running system — and none of them touch what happens at the next boot. That's not a limitation; it's a design you can lean on: you can bounce a service all day during debugging without accidentally changing its boot behaviour.
sudo systemctl start nginxSuccess is silent — no output means it worked. This trips up beginners who expect a confirmation message; in the Unix tradition, no news is good news. Note the sudo: reading state is open to everyone, but changing it is root's job. Re-run systemctl status nginx and the report now says Active: active (running). sudo systemctl restart nginx- restart
- stop then start — always works; connections drop briefly
- reload
- re-read config without stopping — no dropped connections, if the service supports it
- stop
- halt the running service now; boot behaviour unchanged
Stop, then start, one command — the workhorse after a config change. Its gentler sibling reload asks the service to re-read configuration WITHOUT stopping: on a busy web server, reload picks up the new config while active connections survive. Not every service supports reload; restart always works. When you're unsure: restart is the safe default, reload is the production-polite choice where it exists. Check yourself
You edited /etc/nginx/nginx.conf on a production server with live traffic. Which verb applies the change with the least disruption — and what's the trade-off?
Make it survive a reboot (persistence)
Set boot-time behaviour — the part RHCSA cares about most
enableis the other half of the story — the boot state. It's worth knowing what it physically does, because then the behaviour stops being magic:enablecreates a symlink in a directory systemd walks at boot. When boot reaches the multi-user stage, systemd starts everything linked intomulti-user.target.wants/. That symlink IS the persistence — you can literallylsit.And here's the symmetry that surprises people: just as
startdoesn't touch boot state, `enable` doesn't touch runtime state. Enable a stopped service and it stays stopped until the next boot. Since you almost always want both — running now AND at every boot — systemd provides a combined form.sudo systemctl enable --now nginxCreated symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
- enable
- mark the service to start at boot (creates the symlink shown)
- --now
- ALSO apply the runtime change immediately — start with enable, stop with disable
The output shows exactly what happened: a symlink from the boot-time wants/ directory to the real unit file. With --now, the service is ALSO started immediately. Both states set, one command — this is the complete "make it permanent" move, and the answer to most "configure a service" exam tasks. Check yourself
You ran
systemctl start nginx. After a reboot, nginx is down again. Which single command would have both started it and made it persist?When a service won't start: status + the journal
Diagnose a failing service instead of restarting it and hoping
Sooner or later,
startfails — a typo in a config file, a port already taken, a missing directory. The reflex to train: the error message systemctl prints is only the headline; the story is in the journal. systemd captures everything a service writes (its stdout, stderr, and log messages) into a central log — the journal — andjournalctl -u <unit>replays exactly one service's slice of it.sudo systemctl start nginx || systemctl status nginx --no-pagerJob for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details. × nginx.service - The nginx HTTP server Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled) Active: failed (Result: exit-code)A failed start tells you where to look next — and status now shows Active: failed. Note what failed means: systemd TRIED to start it and the service itself refused. The reason isn't in this output; it's in the service's own log lines, which the journal holds. journalctl -u nginx --since "5 min ago" | tail -3Jul 10 14:21:03 web01 nginx[4312]: nginx: [emerg] unknown directive "worker_procceses" in /etc/nginx/nginx.conf:2 Jul 10 14:21:03 web01 systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE Jul 10 14:21:03 web01 systemd[1]: nginx.service: Failed with result 'exit-code'.
- u
- only entries for this unit — the single most useful journalctl flag
- --since
- time filter: "5 min ago", "today", "2026-07-10 14:00" all work
There's the actual story: a typo — worker_procceses — at line 2 of nginx.conf, reported by nginx itself. Fix the typo, start again, done. The pattern generalizes to every service: status for the headline, journalctl -u for the cause. Without -u you get the whole system's journal; with it, one service's history, newest at the bottom. Sometimes the service never gets far enough to log anything, because the unit file itself is wrong: a misspelled directive, an
ExecStartthat points at nothing. systemd doesn't refuse a misspelled key; it logs a warning and ignores the line, soReztart=on-failuresilently means no restart policy at all.systemd-analyze verifyreads a unit file (and its drop-ins) and reports those problems without starting anything:printf '[Unit]\nDescription=demo\n\n[Service]\nExecStart=/usr/bin/sleep 60\nReztart=on-failure\n' > /tmp/demo.service systemd-analyze verify /tmp/demo.service/tmp/demo.service:6: Unknown key name 'Reztart' in section 'Service', ignoring.
- verify FILE...
- Load the unit file(s) and report syntax and reference errors: unknown keys, missing executables, bad dependencies. Starts nothing.
File, line number, problem: line 6's Reztartis not a key systemd knows, so the line is dropped and the unit would run with no restart policy. Fix the spelling and re-run untilverifyprints nothing. Make it a habit after every unit or drop-in edit, beforedaemon-reloadandstart: a clean verify is the cheapest proof that what you wrote is what systemd will do.Check yourself
systemctl status shows a service as 'failed' but the status output doesn't say why. What's your next command?
Now do it — take a service through its full lifecycle
Run the exact workflow a "configure and persist a service" lab grades
You have a real root shell. Take nginx through the complete lifecycle — baseline, make-permanent, verify, and the two-states check — saying each state transition out loud as you cause it. This is the exact sequence a graded "configure a service" task wants, and the verify step is the habit that earns the points.
Two box realities to expect. `nginx` may not be installed yet — on the RHEL lab base,
sudo dnf install -y nginxfirst (the exercise is the lifecycle, not the daemon). And `journalctl -u nginx` may be empty, because this host doesn't run journald —systemctl status nginxshows the recent lines inline, and flat logs live under/var/log. Theenable/start/is-enabled/is-activesteps — the ones a graded task checks — work here.systemctl is-active nginx; systemctl is-enabled nginxBaseline first, always: confirm where you're starting from (expect inactive and disabled). On an exam, this tells you what actually needs doing — sometimes half the task is already done. sudo systemctl enable --now nginxThe make-it-permanent move: running now, and set for every future boot. Watch for the Created symlink line — that's your boot persistence, spelled out. systemctl is-active nginx; systemctl is-enabled nginxVerify — never assume. Both words should now read active and enabled. That pair is the finished state, and checking it is what separates "I ran the command" from "I know it worked." journalctl -u nginx -n 5 --no-pager- n 5
- last 5 entries
- --no-pager
- print directly instead of opening less
Read the last five journal lines for the unit you just started — you'll see the startup messages you'd be hunting through if it had failed. Building the journalctl -u reflex on a HEALTHY service means you already have it when a broken one comes along.
- Active = running now. Enabled = starts at boot. They are fully independent — every combination is possible, and most service confusion comes from assuming one implies the other.
- Runtime verbs (
start/stop/restart/reload) never change boot behaviour;enable/disablenever change runtime state;--nowbridges the two in one command. enablephysically creates a symlink inmulti-user.target.wants/— persistence you canls.masklinks a unit to /dev/null so nothing can start it.- Silent output means success; verify with
is-active/is-enabled(they also set exit codes for scripting) rather than assuming. - When a start fails:
systemctl statusfor the headline,journalctl -u <unit>for the cause. After editing a unit file,daemon-reload; after editing a service's own config,reloadorrestart.
| Command | Runs now? | Starts at boot? |
|---|---|---|
systemctl start svc | Yes | No change |
systemctl stop svc | Stops it | No change |
systemctl enable svc | No change | Yes |
systemctl enable --now svc | Yes | Yes |
systemctl disable --now svc | Stops it | No |
systemctl mask svc | No change | Blocked entirely |
