Systemd Tutorial for Beginners: Units, Services, Targets, and systemctl

Last reviewed: by
Systemd Tutorial for Beginners: Units, Services, Targets, and systemctl

Systemd is the system and service manager used by many modern Linux distributions. It is responsible for bringing the system to a usable state during boot, starting and stopping services, tracking dependencies, reading unit files, managing targets, and exposing tools such as systemctl, journalctl, and systemd-analyze.

If you are new to systemd, the most important idea is this: systemd manages units. A service is a unit, a target is a unit, a socket is a unit, and a timer is a unit. systemctl is the main command used to inspect and control those units.

The examples below were tested on an Ubuntu system running systemd 257. Your service names, default target, boot timings, and enabled units will be different.

NOTE
For daily administration, start with these commands: systemctl status service, systemctl list-units, systemctl get-default, systemctl list-dependencies target, and journalctl -u service.

Quick Command Summary

Task Command
Check systemd version systemctl --version
Check system state systemctl is-system-running
Show default target systemctl get-default
List active targets systemctl list-units --type=target --state=active
List running services systemctl list-units --type=service --state=running
List enabled services systemctl list-unit-files --type=service --state=enabled
Check service status systemctl status ssh.service
Show loaded unit file systemctl cat ssh.service
Show dependencies systemctl list-dependencies multi-user.target
Show service logs journalctl -u ssh.service -n 50
Validate a unit file systemd-analyze verify file.service
Run transient service systemd-run --unit=name command

1. Check systemd Version and System State

Use systemctl --version to confirm the systemd version and enabled build features.

bash
systemctl --version

Tested output:

text
systemd 257 (257.4-1ubuntu3.2)
+PAM +AUDIT +SELINUX +APPARMOR +IMA +IPE +SMACK +SECCOMP +GCRYPT -GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBCRYPTSETUP_PLUGINS +LIBFDISK +PCRE2 +PWQUALITY +P11KIT +QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK +BTF -XKBCOMMON -UTMP +SYSVINIT +LIBARCHIVE

Check the overall system state:

bash
systemctl is-system-running

Tested output:

text
degraded

degraded means at least one unit is failed or not healthy. It does not necessarily mean the system is unusable. Use systemctl --failed when you need to investigate failed units.

For a focused service-listing guide, see systemctl list services examples.


2. Understand systemd Unit Types

A systemd unit is a named object that systemd can manage. Unit names end with a suffix that shows the unit type.

Unit type Example Purpose
.service ssh.service A daemon or process managed by systemd
.target multi-user.target A group of units or desired system state
.socket ssh.socket Socket activation for a service
.timer apt-daily.timer Time-based activation, similar to scheduled jobs
.mount home.mount Filesystem mount unit
.path cups.path Start a unit when a path changes
.slice system.slice Resource-management grouping
.scope transient scope Externally created process grouping

Unit files are plain text configuration files. Common system unit locations include:

text
/etc/systemd/system
/run/systemd/system
/usr/lib/systemd/system
/lib/systemd/system

/etc/systemd/system is for local administrator changes and overrides. Distribution-provided units are usually under /usr/lib/systemd/system or /lib/systemd/system, depending on the distribution. For filesystem-related units, see mount a partition using systemd, mount filesystem without fstab using systemd, and mount filesystems in a specific order with systemd.

For command reference across Linux administration tasks, see the Linux commands cheat sheet.


3. List Active Targets

Targets group units into a desired state. For example, multi-user.target represents a non-graphical multi-user system state, while graphical.target includes graphical login/display services.

bash
systemctl list-units --type=target --state=active --no-pager

Tested output:

text
  UNIT                    LOAD   ACTIVE SUB    DESCRIPTION
  basic.target            loaded active active Basic System
  boot-complete.target    loaded active active Boot Completion Check
  cryptsetup.target       loaded active active Local Encrypted Volumes
  getty-pre.target        loaded active active Preparation for Logins
  getty.target            loaded active active Login Prompts
  graphical.target        loaded active active Graphical Interface
  integritysetup.target   loaded active active Local Integrity Protected Volumes
  local-fs-pre.target     loaded active active Preparation for Local File Systems
  local-fs.target         loaded active active Local File Systems
  multi-user.target       loaded active active Multi-User System
  network-online.target   loaded active active Network is Online

Notice that graphical.target and multi-user.target are both active on this host. Graphical systems commonly include the multi-user state as part of the boot dependency chain.


4. Check the Default Boot Target

The default target controls the state systemd tries to reach during boot.

bash
systemctl get-default

Tested output:

text
graphical.target

Show details for default.target:

bash
systemctl show -p Id -p Names -p FragmentPath -p UnitFileState default.target

Tested output:

text
Id=graphical.target
Names=graphical.target default.target runlevel5.target
FragmentPath=/usr/lib/systemd/system/graphical.target
UnitFileState=static

This system uses graphical.target as the default. If a server is configured to boot into multi-user.target, default.target normally points or aliases to multi-user.target. The target unit file itself is commonly stored under /usr/lib/systemd/system or /lib/systemd/system. If you are troubleshooting boot choices after a kernel change, see boot with an older kernel using grubby.

Show the multi-user.target unit file path:

bash
systemctl show -p Id -p Description -p FragmentPath multi-user.target

Tested output:

text
Id=multi-user.target
Description=Multi-User System
FragmentPath=/usr/lib/systemd/system/multi-user.target

For boot recovery workflows, see boot into single-user mode in RHEL/CentOS and boot into rescue mode.


5. List Running Services

Use systemctl list-units to list active service units.

bash
systemctl list-units --type=service --state=running --no-pager

Tested output:

text
  UNIT                          LOAD   ACTIVE SUB     DESCRIPTION
  accounts-daemon.service       loaded active running Accounts Service
  avahi-daemon.service          loaded active running Avahi mDNS/DNS-SD Stack
  colord.service                loaded active running Manage, Install and Generate Color Profiles
  containerd.service            loaded active running containerd container runtime
  cron.service                  loaded active running Regular background program processing daemon
  cups-browsed.service          loaded active running Make remote CUPS printers available locally
  cups.service                  loaded active running CUPS Scheduler
  dbus.service                  loaded active running D-Bus System Message Bus
  docker.service                loaded active running Docker Application Container Engine
  fwupd.service                 loaded active running Firmware update daemon
  gdm.service                   loaded active running GNOME Display Manager
  gnome-remote-desktop.service  loaded active running GNOME Remote Desktop
  ModemManager.service          loaded active running Modem Manager

Use this when you want to see currently running daemons. To see enabled services that start at boot, use systemctl list-unit-files.

bash
systemctl list-unit-files --type=service --state=enabled --no-pager

Tested output:

text
UNIT FILE                                  STATE   PRESET
accounts-daemon.service                    enabled enabled
anacron.service                            enabled enabled
apparmor.service                           enabled enabled
apport.service                             enabled enabled
avahi-daemon.service                       enabled enabled
blk-availability.service                   enabled enabled
bluetooth.service                          enabled enabled
cloud-config.service                       enabled enabled
cloud-final.service                        enabled enabled
cloud-init-local.service                   enabled enabled
cloud-init-main.service                    enabled enabled

6. Check Service Status

Use systemctl status service-name.service to inspect a service. This host has ssh.service running.

bash
systemctl status ssh.service --no-pager

Tested output:

text
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/usr/lib/systemd/system/ssh.service; enabled; preset: enabled)
     Active: active (running) since Sun 2026-06-07 13:55:41 IST; 7h ago
 Invocation: 36eb6d30595543eb802114499ea45ed3
TriggeredBy: ● ssh.socket
       Docs: man:sshd(8)
             man:sshd_config(5)
   Main PID: 1606 (sshd)
      Tasks: 1 (limit: 10052)
     Memory: 7M (peak: 20.9M, swap: 12.2M, swap peak: 12.2M)
        CPU: 942ms
     CGroup: /system.slice/ssh.service

Useful related commands:

bash
systemctl is-enabled ssh.service
systemctl is-active ssh.service

Tested output:

text
enabled
active

If a legacy service name is missing after migrating to newer releases, see unit network.service not found in RHEL 8 for an example of systemd-era service name changes.


7. View a Unit File with systemctl cat

Use systemctl cat to show the unit file and drop-ins that systemd is using.

bash
systemctl cat ssh.service --no-pager

Tested output:

text
# /usr/lib/systemd/system/ssh.service
[Unit]
Description=OpenBSD Secure Shell server
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target nss-user-lookup.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755

This is safer than opening random files manually because it shows the unit definition systemd actually loaded.


8. Understand Wants, Requires, Conflicts, Before, and After

Systemd dependency directives answer two different questions:

Directive Meaning
Wants= Start listed units too, but do not fail this unit just because a wanted unit fails
Requires= Stronger dependency; if the required unit fails to start, this unit is affected
Conflicts= Negative relationship; conflicting units cannot run together
Before= Ordering rule: this unit starts before the listed unit
After= Ordering rule: this unit starts after the listed unit

A common beginner mistake is assuming After= means dependency. It does not. After=network.target only controls ordering. If you also require another unit to start, combine ordering with Wants= or Requires= as appropriate.


9. View Target Dependencies

Use systemctl list-dependencies to see what belongs to a target.

bash
systemctl list-dependencies multi-user.target --plain --no-pager

Tested output:

text
multi-user.target
  anacron.service
  apport.service
  avahi-daemon.service
  console-setup.service
  containerd.service
  cron.service
  cups-browsed.service
  cups.path
  cups.service
  dbus.service
  dmesg.service
  docker.service
  e2scrub_reap.service
  grub-common.service
  grub-initrd-fallback.service
  ModemManager.service
  networkd-dispatcher.service

This helps explain why starting a target brings up many services. If you are using systemd to run operational scripts around boot or shutdown, see run a script after N minutes of boot, run a script before shutdown, and run a script at shutdown only.


10. Read Service Logs with journalctl

Systemd integrates with the journal. Use journalctl -u to read logs for one unit.

bash
journalctl -u ssh.service -n 5 --no-pager

Tested output:

text
Jun 07 14:27:41 server1 sshd-session[14020]: pam_unix(sshd:session): session opened for user golinuxcloud(uid=1000) by golinuxcloud(uid=0)
Jun 07 14:28:12 server1 sshd-session[14502]: Accepted publickey for golinuxcloud from 10.0.2.2 port 56873 ssh2: RSA SHA256:QctH5c77yvxCJMG6WUQfAfwvfxRR4VBhFK+1rAFsoCY
Jun 07 14:28:12 server1 sshd-session[14502]: pam_unix(sshd:session): session opened for user golinuxcloud(uid=1000) by golinuxcloud(uid=0)
Jun 07 15:35:13 server1 sshd-session[38996]: Accepted publickey for golinuxcloud from 10.0.2.2 port 61916 ssh2: RSA SHA256:QctH5c77yvxCJMG6WUQfAfwvfxRR4VBhFK+1rAFsoCY
Jun 07 15:35:13 server1 sshd-session[38996]: pam_unix(sshd:session): session opened for user golinuxcloud(uid=1000) by golinuxcloud(uid=0)

For a deeper log tutorial, see journalctl command examples and how systemd-journald logging works.


11. Analyze Boot Dependencies

systemd-analyze critical-chain shows the chain of units involved in boot timing.

bash
systemd-analyze critical-chain --no-pager

Tested output:

text
The time when unit became active or started is printed after the "@" character.
The time the unit took to start is printed after the "+" character.

graphical.target @1min 54.276s
└─power-profiles-daemon.service @1min 54.024s +250ms
  └─multi-user.target @1min 54.015s
    └─plymouth-quit-wait.service @11.932s +1min 42.081s
      └─systemd-user-sessions.service @11.840s +65ms
        └─network.target @11.769s
          └─NetworkManager.service @8.197s +3.569s
            └─dbus.service @6.391s +1.788s
              └─basic.target @6.360s
                └─sockets.target @6.360s
                  └─snapd.socket @6.342s +17ms

Use this to identify slow boot chains, but remember that not every long duration is a problem.


12. Create and Verify a Simple Service Unit

A basic oneshot service unit looks like this:

ini
[Unit]
Description=GoLinuxCloud demo oneshot service
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/bin/printf systemd-demo-ok\n
[Install]
WantedBy=multi-user.target

Before installing a custom unit, validate its syntax:

bash
systemd-analyze verify /tmp/glc-systemd-demo.service
echo "verify exit=$?"

Tested output:

text
verify exit=0

verify exit=0 means the unit file passed syntax validation. If the unit file has invalid directives or paths, systemd-analyze verify can report warnings or errors before you install it under /etc/systemd/system.

For practical service patterns, see run a systemd service as a specific user or group, run a script at startup with systemd, and run a script before the login prompt appears. If your job is schedule-based rather than boot-state-based, compare it with the crontab command examples.


13. Test a Transient Service with systemd-run

systemd-run starts a transient unit under /run/systemd/transient. This is useful for testing without creating a permanent unit file.

bash
systemd-run --unit=glc-systemd-demo-sleep /bin/sleep 20

Tested output:

text
Running as unit: glc-systemd-demo-sleep.service; invocation ID: 0f3abe383ea64c87acef24ec5f365441

Check the transient unit:

bash
systemctl status glc-systemd-demo-sleep.service --no-pager

Tested output:

text
● glc-systemd-demo-sleep.service - [systemd-run] /bin/sleep 20
     Loaded: loaded (/run/systemd/transient/glc-systemd-demo-sleep.service; transient)
  Transient: yes
     Active: active (running) since Sun 2026-06-07 21:29:13 IST; 1s ago
 Invocation: 0f3abe383ea64c87acef24ec5f365441
   Main PID: 108101 (sleep)
      Tasks: 1 (limit: 10052)
     Memory: 204K (peak: 1.6M)
        CPU: 27ms
     CGroup: /system.slice/glc-systemd-demo-sleep.service
             └─108101 /bin/sleep 20

Stop it when finished:

bash
systemctl stop glc-systemd-demo-sleep.service
systemctl is-active glc-systemd-demo-sleep.service

Tested output:

text
inactive

Frequently Asked Questions

1. What is systemd in Linux?

systemd is the system and service manager used by many Linux distributions. It starts the system, manages services, handles dependencies, tracks units, and provides tools such as systemctl and journalctl.

2. What is a systemd unit?

A systemd unit is a configuration object managed by systemd. Unit types include service, target, socket, mount, timer, path, slice, scope, device, automount, and swap units.

3. What is the difference between a service and a target in systemd?

A service unit describes a process or daemon. A target unit groups other units and represents a system state, such as multi-user.target or graphical.target.

4. How do I check the default boot target in systemd?

Use systemctl get-default. The default target is commonly represented through default.target, which aliases or links to a real target such as multi-user.target or graphical.target.

5. If a systemd system uses multi-user.target as the default boot target, which file is the default target symlink?

The default target is normally represented by /etc/systemd/system/default.target, which points or aliases to the selected target such as multi-user.target. The target unit file itself is commonly under /usr/lib/systemd/system or /lib/systemd/system depending on the distribution.

6. How do I check logs for a systemd service?

Use journalctl -u service-name.service. Add -n 50 for recent lines and --no-pager for non-interactive output.

Summary

Systemd manages Linux boot and services through units. A .service unit manages a daemon or process, while a .target unit groups units into a system state such as multi-user.target or graphical.target. Use systemctl to inspect services, targets, dependencies, and unit files, and use journalctl to read logs.

For beginners, the safest learning path is to inspect existing units first, validate custom unit files with systemd-analyze verify, and test temporary work with systemd-run before installing permanent units under /etc/systemd/system.

Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, …

  • Red Hat Certified System Administrator in Red Hat OpenStack
  • Certified Kubernetes Application Developer (CKAD)
  • Red Hat Certified Specialist in Ansible Automation
  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security