Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

systemctl list services: list-units vs list-unit-files, the Filters That Matter, and the Output You Can Script

Sean

Platform Writer

Sep 13, 2026
7 min read

To list services with systemctl, use systemctl list-units —type=service for what is loaded and running now, and systemctl list-unit-files —type=service for every service installed on the system and whether it starts at boot. The two commands answer different questions, which is why they disagree: a service can be installed and disabled, so it appears in the second list and not the first, or running from a transient unit, so it appears in the first and not the second. Add —state=running, —state=enabled or —all to narrow either one, and —no-legend —plain to get output a script can parse.

systemctl list services: list-units vs list-unit-files, the Filters That Matter, and the Output You Can Script

Every reference page shows the two commands. Fewer explain why they return different sets, and almost none show the output shape that matters when you are writing a health check or a deploy script rather than reading a terminal. This post is the two commands, the mental model that makes their differences obvious, the filters, and the scripting flags.

Table of contents

Two lists, two questions

systemd keeps two things: unit files on disk, and units it has loaded into memory. A unit file is the definition, in /usr/lib/systemd/system or /etc/systemd/system. A loaded unit is the live object systemd is tracking, with a state. Most of the time a service has both, but not always, and the gap between them is what the two commands expose.

# What systemd is currently tracking: loaded units, with their live state
systemctl list-units --type=service

# What is installed on disk, and whether it is enabled to start at boot
systemctl list-unit-files --type=service

list-units answers: what is running, or has run, or failed, right now. list-unit-files answers: what could run, and what will run at boot. If you want to know whether nginx is up, use the first. If you want to know whether nginx will come back after a reboot, use the second.

Reading the columns

list-units prints five columns for each service.

  • UNIT: the name, ending in .service.
  • LOAD: whether the unit file was parsed successfully. loaded is normal; not-found means something references a unit that does not exist; masked means it has been deliberately blocked.
  • ACTIVE: the high-level state. active, inactive, failed, activating.
  • SUB: the low-level state, which for services is usually running, exited, or dead. A oneshot service that finished its job shows active (exited), and that is not a problem.
  • DESCRIPTION: the text from the unit file.

list-unit-files prints the name, STATE and, on newer versions, PRESET. STATE is about boot: enabled means a symlink in a .wants directory will start it; disabled means it will not; static means it has no install section and is only started as a dependency; masked means it cannot be started at all. Note that enabled says nothing about whether it is running now, and running says nothing about whether it is enabled.

The filters that actually get used

# Only services that are running right now
systemctl list-units --type=service --state=running

# Everything loaded, including inactive and dead ones
systemctl list-units --type=service --all

# Only services that failed
systemctl list-units --type=service --state=failed
# or, shorter
systemctl --failed

# Services enabled to start at boot
systemctl list-unit-files --type=service --state=enabled

# Services installed but disabled
systemctl list-unit-files --type=service --state=disabled

# One service, both questions at once
systemctl status nginx
systemctl is-active nginx
systemctl is-enabled nginx

Without —all, list-units hides units that are inactive and have not failed, which is why a service you stopped a minute ago seems to vanish from the list. It is still loaded; it is just being filtered. The show running services post narrows this further for the case where you only want what is up.

The —failed shortcut is the one to run first when a box is misbehaving. It prints exactly the services systemd considers broken and nothing else, and it is the fastest route to the journal entry you need.

Why the names do not match between distributions

The service name is whatever the unit file is called, and packagers do not agree. The SSH daemon is ssh.service on Debian and Ubuntu and sshd.service on Fedora and RHEL. The system logger is rsyslog.service on some and syslog.service as an alias on others. Nginx and Postgres are consistent, but Postgres is often a template, [email protected], rather than a single unit.

When you do not know the name, ask systemd rather than guessing:

systemctl list-units --type=service --all | grep -i ssh
systemctl list-unit-files | grep -i postgres

And if a service you just installed does not appear in either list, run systemctl daemon-reload so systemd rescans the unit directories. The daemon-reload post covers when that is needed and when it is not.

Output you can script

The default output is for humans: a header row, a legend at the bottom, coloured bullets, and columns padded to the terminal width. Scripts need none of that.

# Plain, no header, no legend, no colour, no truncation
systemctl list-units --type=service --state=running --no-legend --plain --no-pager

# Just the unit names
systemctl list-units --type=service --state=running --no-legend --plain | awk '{print $1}'

# A health check that exits non-zero if anything failed
if [ "$(systemctl list-units --type=service --state=failed --no-legend --plain | wc -l)" -gt 0 ]; then
  echo 'failed services present'; exit 1
fi

# Machine-readable, on systemd 245 and later
systemctl list-units --type=service --output=json

The awk on the first column is safe because unit names never contain spaces. The —output=json form is the right one for anything that will be parsed by a program rather than a shell, and it is available on every current long-term-support distribution.

What this looks like without a server

Every command in this post exists because a virtual machine has a process supervisor and you are responsible for reading it. That is the correct tool when the box is the product. When the app is the product, the process list is one line: the service, its current deploy, and whether it is healthy. On RunxBuild a Node, Python, Go or Docker service has that status, its runtime logs and its deploy history on one page, and a failed deploy is a rollback rather than a journalctl session. The systemd knowledge still matters, because the box you are debugging today is usually one somebody else set up, but it is worth knowing which of your services actually need a box under them.

How this fits the rest of the stack

list-units for now, list-unit-files for boot, —failed first when something is wrong, and —no-legend —plain when a script is reading. If the reason you are listing services is to work out what a server is running so you can move it, the RunxBuild hosting calculator turns that inventory into line items: a service plan per process that needs one, a managed database for the one that stores things, and storage and bandwidth beside them. List the services, decide which ones need a server, and give the rest somewhere simpler to live.

Useful related references:

FAQ

How do I list all services with systemctl?

systemctl list-units —type=service —all shows every loaded service with its live state. systemctl list-unit-files —type=service shows every installed service and whether it is enabled to start at boot. Use the first for what is running and the second for what is installed.

What is the difference between list-units and list-unit-files?

list-units shows units systemd has loaded into memory, with their active state. list-unit-files shows unit definitions on disk, with their boot state. A disabled service appears only in the second; a transient unit appears only in the first. They answer different questions and are expected to disagree.

How do I list only running services?

systemctl list-units —type=service —state=running. Add —no-legend —plain if a script is going to parse the result, and pipe to awk to print just the unit names.

How do I list enabled and disabled services?

systemctl list-unit-files —type=service —state=enabled for services that start at boot, and —state=disabled for those that do not. Enabled means a boot symlink exists; it does not mean the service is running right now. Use systemctl is-active for that.

Why does a service not show up in systemctl list-units?

Without —all, list-units hides inactive units that have not failed, so a stopped service disappears from the list. Add —all. If a newly installed service is missing from both lists, run systemctl daemon-reload so systemd rescans the unit directories.

#systemctl list services#systemctl list-units#systemctl list-unit-files#list running services linux#systemd services