You need the live inventory
You rebooted your Fedora machine after a routine dnf upgrade and the web server is not answering. Or maybe you are auditing a fresh install and need a quick inventory of what is actually consuming resources. The terminal is open, but typing ps aux gives you a wall of process trees that tells you nothing about service lifecycles or dependency chains. You need the systemd view.
What systemd actually tracks
systemd does not just start programs. It tracks their entire lifecycle from boot to shutdown. A service unit file defines the executable, the dependencies, the restart policy, the resource limits, and the logging target. When you ask for running services, you are asking the systemd manager for a live snapshot of every unit that has successfully transitioned to an active state. Think of it like a building electrical panel. The breaker box shows which circuits are live, which are tripped, and which are permanently disabled at the hardware level. systemctl reads that panel directly instead of guessing by scanning process IDs.
Fedora splits service configuration into two layers. The package manager drops default unit files into /usr/lib/systemd/system/. Those files are read only. When you need to override a timeout or change a working directory, you create a drop-in snippet in /etc/systemd/system/. systemd merges them at runtime. The listing commands you run will reflect the merged result, not the raw package file.
Run systemctl list-units before you start guessing. The runtime state is the only truth that matters.
The standard listing commands
The default systemctl list-units command shows all loaded units, but it mixes sockets, mounts, timers, and services. You want only the service layer. The --type=service flag restricts the query to service units. Adding --state=running filters for processes that are currently executing.
Here is how to get a clean, scrollable list of every active service on your system.
systemctl list-units --type=service --state=running --no-pager
# --type=service restricts output to service units only
# --state=running shows only units that have successfully started
# --no-pager disables less so you can pipe or copy the output directly
The output prints four columns. The first column is the unit name. The second shows the loaded state (whether systemd found the unit file). The third shows the active state. The fourth shows the substate. You will see active (running) for daemons that stay alive, and active (exited) for one-shot services that do their job and terminate. Both are considered healthy.
If you need to see services that are loaded but not currently executing, swap the state flag. This is useful for finding services that are enabled but waiting for a trigger, or services that stopped after a crash.
systemctl list-units --type=service --state=inactive --no-pager
# --state=inactive shows units that are loaded but not running
# This catches services that stopped normally or failed to start
# Combine with --all to see units that systemd knows about but hasn't loaded yet
Convention aside: systemctl list-units only shows units currently loaded in memory. If a service was never started since boot, it will not appear unless you add --all. The --all flag forces systemd to scan the unit directories and report every known service, regardless of runtime state.
Check the runtime state first. Loaded units are the ones actually affecting your system.
Verify it worked
Listing services gives you a map. Verifying a specific service gives you the terrain. When you need to confirm that a particular daemon is healthy, check its status directly. The status command pulls the unit file metadata, the current state, the main process ID, and the last ten journal lines for that unit.
Here is how to inspect a single service and read its recent activity.
systemctl status httpd
# Queries the runtime state of the httpd unit
# Shows the main PID, memory usage, and cgroup tree
# Appends the last ten journal lines filtered to this unit
The output header tells you everything you need. Look for Active: active (running) in green. If you see Active: failed (Result: exit-code), the process crashed. If you see Active: inactive (dead), it simply stopped. The journal excerpt at the bottom shows the most recent log entries. If the output cuts off, press q to exit the pager.
Convention aside: systemctl status <unit> is faster than opening a separate terminal for journalctl. The x and e flags in journalctl -xe add explanatory annotations and jump to the end, but status gives you the exact slice you need without extra noise. Always check status before restarting. Restarting a failed service without reading the journal just repeats the same error.
Read the status header before you touch the service. The substate tells you whether the problem is configuration, permissions, or a missing dependency.
Common pitfalls and what the error looks like
Services fail for predictable reasons. The most common is a missing executable or a broken symlink in the unit file. systemd will refuse to start the unit and print a clear failure message. You will see this in the terminal or in the journal.
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; preset: disabled)
Active: failed (Result: exit-code) since Mon 2024-05-20 14:32:11 UTC; 3min ago
Process: 4521 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE)
Main PID: 4521 (code=exited, status=1/FAILURE)
The code=exited, status=1/FAILURE line means the program itself returned an error. Check the journal for the actual reason. SELinux denials are another frequent blocker. When a service tries to access a file or port that violates policy, systemd logs the failure and the audit subsystem records the denial.
journalctl -t setroubleshoot --no-pager -n 20
# Filters journal for SELinux troubleshooting messages
# --no-pager keeps output in the terminal
# -n 20 limits to the twenty most recent entries
You will see a one-line summary like SELinux is preventing /usr/sbin/httpd from name_bind access on the tcp_socket port 8080. Do not disable SELinux to fix this. Adjust the policy or the file context instead.
Another pitfall is masked units. Masking is systemd's way of permanently disabling a service by symlinking it to /dev/null. You cannot start a masked unit, even manually. The listing command will show Loaded: masked. If you need to unmask it, remove the symlink and reload the daemon.
systemctl unmask httpd
# Removes the /dev/null symlink that blocks the unit
# systemctl daemon-reload is usually automatic but run it if the state lingers
Check the journal before you restart. Guessing the cause wastes time and masks the real error.
When to use which listing method
Use systemctl list-units --type=service --state=running when you need a live inventory of daemons currently consuming resources. Use systemctl list-units --type=service --state=inactive --all when you are hunting for services that failed to start or stopped after a crash. Use systemctl list-unit-files --type=service when you want to see what is installed on disk and whether each service is enabled, disabled, or masked at boot. Use systemctl status <unit> when you need the exact runtime state, process tree, and recent log lines for a single service. Use journalctl -u <unit> --no-pager when the status output is truncated and you need the full historical log. Use ps aux | grep <service> only when you are debugging a rogue process that systemd does not manage.
Pick the command that matches your goal. Runtime state and disk state are different questions.