SystemD – What is SystemD used for?

systemd is the init system and service manager on nearly every major Linux distribution. It runs as process ID 1, starts services at boot, restarts them when they fail, and collects logs through journald. You control it with systemctl and read logs with journalctl. The current release is systemd 262.
Short version
systemctl status nginx # is the service running?
sudo systemctl enable --now nginx # start now and at every boot
sudo systemctl restart nginx
systemctl cat nginx # show the unit file
journalctl -u nginx -f # follow the service log
systemd-analyze blame # what slows down boot?In this article, you will learn what systemd does, how unit files, targets and control groups work, and which commands you need day to day.
Table of Contents
- Short version
- What is SystemD used for?
- Why do people dislike SystemD?
- Why is SystemD controversial?
- What is SystemD vs init?
- Should I use Grub or SystemD?
- How to use SystemD
- SystemD - Init
- Unit-Files
- Targets
- Control-Groups
- Logging - JournalD
- FAQ
- How do I check if a service is running with systemd?
- How do I make a service start at boot?
- How do I check if my system uses systemd?
- What is the difference between systemd and systemctl?
- How do I create my own systemd service?
- Summary
What is SystemD used for?
systemd manages the processes on a Linux machine from boot to shutdown. It starts services in parallel, mounts filesystems, brings up devices and sockets, and keeps track of every process in a control group. It also ships tools for logging (journald), scheduled jobs (timers), hostnames, time and more.
Whether you run a large server or a laptop, the everyday tasks look the same:
- start, stop, restart and enable services
- restart crashed services automatically
- read logs per service
- limit CPU and memory per service
- find out what makes boot slow
Why do people dislike SystemD?
Mostly because of its scope. systemd started as an init system and grew into a large suite that also handles logging, networking, DNS resolving, login sessions and more. Critics say this breaks the Unix idea of small tools that do one job. Others dislike that journald stores logs in a binary format, so you need journalctl instead of grep on a text file.
None of this makes it slow or insecure by itself. For most admins the unit-file syntax is simpler than the old init shell scripts.
Why is SystemD controversial?
Distributions adopted it between 2012 and 2015, and it replaced the init system that everyone knew. Because other components such as GNOME started to depend on it, some users felt they could not avoid it. A few distributions, for example Devuan, Alpine and Void, still ship other init systems.
What is SystemD vs init?
The classic System V init starts services one after another by running shell scripts in /etc/init.d. systemd describes services in declarative unit files, starts them in parallel based on dependencies, and tracks them with control groups. That is why boot is usually faster and why systemd can reliably stop every process of a service. systemd 260 removed support for the old SysV init scripts, so services need native unit files now.
Should I use Grub or SystemD?
You don’t have to choose, because they do different jobs. A bootloader such as GRUB loads the kernel. After that, the kernel starts systemd as the first process. If you want a simpler bootloader, systemd also ships systemd-boot for UEFI systems.
How to use SystemD

Next, we will cover a couple of ways in which you can use systemd on Linux systems. These are just a few examples that you can try out yourself. It takes some time to get used to the syntax, but once you have it down, systemd is easy to work with.
SystemD - Init
This is the first process started by the kernel and gets the process id 1. It manages the boot process and tasks like creating sockets, setting up hardware, mounting disks, etc.
systemd works with units of different types. Next to the service itself, there also exist:
- timer
- mount
- socket
- path
- device
- target
- slice
Furthermore, you can manage other processes with SystemD:
- start
- stop
- restart
- kill
Unit-Files
There are different paths for existing unit files:
| Path | Info |
|---|---|
| /usr/lib/systemd/system | predefined SystemD files (do not modify) |
| /etc/systemd/system | Location for custom unit files |
| /run/systemd/system | For the runtime relevant files |
Important information about the paths: SystemD will always prefer /etc/ to /usr/lib/. This is why we place custom unit files there.
You can visit the unit file of a specific service by visiting the path or with the command:
systemctl cat <service>For example, OpenVPN:
root@max-desktop:~$ systemctl cat openvpn
# /lib/systemd/system/openvpn.service
# This service is actually a systemd target,
# but we are using a service since targets cannot be reloaded.
[Unit]
Description=OpenVPN service
After=network.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/true
WorkingDirectory=/etc/openvpn
[Install]
WantedBy=multi-user.targetAs we can see, the unit file defines a description, the start order (After=), the command to run (ExecStart=) and the target that pulls it in at boot (WantedBy=). We can view all properties of the service, including the defaults that are not in the file, with:
systemctl show <service>For example, here again, are the first lines of the output of OpenVPN:
root@max-desktop:~$ systemctl show openvpn
Type=oneshot
Restart=no
NotifyAccess=none
RestartUSec=100ms
TimeoutStartUSec=infinity
TimeoutStopUSec=1min 30s
TimeoutAbortUSec=1min 30s
TimeoutStartFailureMode=terminate
TimeoutStopFailureMode=terminate
RuntimeMaxUSec=infinity
WatchdogUSec=0
WatchdogTimestamp=n/a
WatchdogTimestampMonotonic=0
RootDirectoryStartOnly=no
RemainAfterExit=yes
GuessMainPID=yes
MainPID=0
ControlPID=0
FileDescriptorStoreMax=0
NFileDescriptorStore=0
StatusErrno=0
Result=success
ReloadResult=success
CleanResult=success
UID=[not set]
GID=[not set]
NRestarts=0
OOMPolicy=stop
ExecMainStartTimestamp=Sat 2022-09-17 13:00:55 CEST
ExecMainStartTimestampMonotonic=9823235
ExecMainExitTimestamp=Sat 2022-09-17 13:00:55 CEST
ExecMainExitTimestampMonotonic=9824084
ExecMainPID=1164
ExecMainCode=1
ExecMainStatus=0If we want to change a unit, we should not edit the packaged file in /usr/lib/systemd/system. Instead, we run:
sudo systemctl edit <service>This opens an empty drop-in file at /etc/systemd/system/<service>.service.d/override.conf. Only the options you put there change, and package updates do not overwrite them. If you really want a full copy of the original file to edit, add the --full option.
As an example, let’s say we want a service to restart by itself when it crashes. We open the editor for the service and add:
[Service]
Restart=on-failure
RestartSec=5systemctl edit reloads the configuration for us when you save. If you edit a unit file by hand, you need to reload the unit files yourself:
sudo systemctl daemon-reloadAnd finally, restart the service:
sudo systemctl restart <service>With this command, systemd will try to reload the service’s own configuration. If the service does not support reloading, it will restart the service:
sudo systemctl reload-or-restart <service>In the above commands, we learned how to control services manually. SystemD also allows you to permanently enable or disable services so that they either start automatically when needed or are not available at all. The following table will show the available commands:
| Command | Function |
|---|---|
| enable | Starts a service automatically at boot |
| disable | Stops a service from starting automatically at boot |
| is-enabled | Check if a service is enabled |
| reenable | Disables a service and then enables it again |
| mask | Completely blocks a service so nothing can start it, be careful |
| unmask | Removes the mask from a service |
Usage example:
sudo systemctl enable --now <service>The --now option starts the service right away as well.
Targets
Targets are the different states in which the system can boot.
systemd replaces the well-known run levels. The older principle is retained, only the run levels are given names instead of numbers:
| Target | Effect |
|---|---|
| halt.target | Stops the system without powering it off |
| poweroff.target | Physically shuts down the system (power off) |
| rescue.target | Single-user mode |
| multi-user.target | Multiuser mode |
| graphical.target | Multiuser mode with graphical interface |
| reboot.target | Reboots the system |
You can switch to another target by using the following command:
systemctl isolate example.targetReboot the system:
systemctl rebootPuts the system into hybrid sleep, which saves the state to disk and suspends to RAM:
systemctl hybrid-sleepPowers off the system:
systemctl poweroffThe classic shutdown command is still available and accepts a time and a message. This reboots the system immediately:
sudo shutdown -r nowThere are many different parameters to use this command. You can look them up on the man page.
You can display the current target the system is booting into with the following command:
systemctl get-defaultAdditionally, you can change the default target:
sudo systemctl set-default example.targetThe different runlevels can also be viewed here:
ls -la /usr/lib/systemd/system |grep runle*root@max-desktop:~$ ls -la /usr/lib/systemd/system |grep runle*
lrwxrwxrwx 1 root root 15 Apr 18 22:12 runlevel0.target -> poweroff.target
lrwxrwxrwx 1 root root 13 Apr 18 22:12 runlevel1.target -> rescue.target
drwxr-xr-x 2 root root 4096 Jan 28 2022 runlevel1.target.wants
lrwxrwxrwx 1 root root 17 Apr 18 22:12 runlevel2.target -> multi-user.target
drwxr-xr-x 2 root root 4096 Jan 28 2022 runlevel2.target.wants
lrwxrwxrwx 1 root root 17 Apr 18 22:12 runlevel3.target -> multi-user.target
drwxr-xr-x 2 root root 4096 Jan 28 2022 runlevel3.target.wants
lrwxrwxrwx 1 root root 17 Apr 18 22:12 runlevel4.target -> multi-user.target
drwxr-xr-x 2 root root 4096 Jan 28 2022 runlevel4.target.wants
lrwxrwxrwx 1 root root 16 Apr 18 22:12 runlevel5.target -> graphical.target
drwxr-xr-x 2 root root 4096 Jan 28 2022 runlevel5.target.wants
lrwxrwxrwx 1 root root 13 Apr 18 22:12 runlevel6.target -> reboot.target
-rw-r--r-- 1 root root 803 Apr 18 22:12 systemd-update-utmp-runlevel.serviceControl-Groups
systemd organizes tasks in control groups (cgroups). This is used for resource control in Linux, and this allows available resources to be limited, prioritized, counted, and isolated.
The following commands are, therefore, very useful for analyzing and optimizing system performance:
systemd-analyzeThis command can be used to determine boot performance.
root@max-desktop:~$ systemd-analyze
Startup finished in 12.712s (firmware) + 328ms (loader) + 8.240s (kernel) + 6.634s (userspace) = 27.916s
graphical.target reached after 6.631s in userspaceAs we can see, we get a breakdown of the timings of how long each task takes to start.
With the additional command blame we get a very detailed list of how long which single process needs to start up:
systemd-analyze blameOutput:
root@max-desktop:~$ systemd-analyze blame
5.573s NetworkManager-wait-online.service
3.244s plymouth-quit-wait.service
2.285s fwupd.service
467ms logrotate.service
392ms lm-sensors.service
385ms accounts-daemon.service
362ms snapd.service
290ms systemd-resolved.service
279ms networkd-dispatcher.service
247ms networking.service
213ms dev-nvme0n1p3.device
182ms apparmor.service
178ms ModemManager.service
174ms systemd-journal-flush.service
168ms udisks2.service
161ms NetworkManager.service
152ms com.system76.Scheduler.service
128ms apport.service
127ms e2scrub_reap.service
116ms rsyslog.service
115ms smartmontools.service
114ms wpa_supplicant.service
105ms systemd-cryptsetup@cryptswap.service
100ms gpu-manager.service
....If we want to see all control groups, we can use:
systemd-cglsor
systemctl statusWe will get a tree-based output with all the necessary information:
root@max-desktop:~$ systemd-cgls
Control group /:
-.slice
├─user.slice
│ └─user-1000.slice
│ ├─user@1000.service
│ │ ├─session.slice
│ │ │ ├─dbus-broker.service
│ │ │ │ ├─3119 /usr/bin/dbus-broker-launch --scope user
│ │ │ │ └─3120 dbus-broker --log 4 --controller 10 --machine-id 04d8535513777afc7bb291c362dd90a7 --max-bytes 100000000000000 --max-fds 25000000000000 --max-matches 50000000>
│ │ │ ├─xdg-document-portal.service
│ │ │ │ ├─3761 /usr/libexec/xdg-document-portal
│ │ │ │ └─3773 fusermount3 -o rw,nosuid,nodev,fsname=portal,auto_unmount,subtype=portal -- /run/user/1000/doc
│ │ │ ├─xdg-desktop-portal.service
│ │ │ │ └─3753 /usr/libexec/xdg-desktop-portal
│ │ │ ├─pipewire-pulse.service
│ │ │ │ └─3112 /usr/bin/pipewire-pulse
│ │ │ ├─wireplumber.service
│ │ │ │ └─3111 /usr/bin/wireplumber
│ │ │ ├─plasma-xdg-desktop-portal-kde.service
│ │ │ │ └─3861 /usr/lib/x86_64-linux-gnu/libexec/xdg-desktop-portal-kde
│ │ │ └─pipewire.service
│ │ │ └─3106 /usr/bin/pipewire
│ │ ├─background.slice
│ │ │ ├─plasma-kactivitymanagerd.service
│ │ │ │ └─3546 /usr/lib/x86_64-linux-gnu/libexec/kactivitymanagerd
│ │ │ ├─plasma-kscreen.service
│ │ │ │ └─3610 /usr/lib/x86_64-linux-gnu/libexec/kf5/kscreen_backend_launcher
│ │ │ ├─plasma-baloorunner.service
│ │ │ │ └─5633 /usr/lib/x86_64-linux-gnu/libexec/baloorunner
│ │ │ ├─plasma-kglobalaccel.service
│ │ │ │ └─3452 /usr/bin/kglobalaccel5
│ │ │ └─tracker-miner-fs-3.service
│ │ │ └─3148 /usr/libexec/tracker-miner-fs-3
│ │ ├─app.slice
│ │ │ ├─app-\\x2fusr\\x2fbin\\x2fkorgac-d27ecb9065d646918a10df1c4fa798fe.scope
│ │ │ │ └─3599 /usr/bin/korgac -session 10dfe2702d000165869202400000083140007_1663442587_18526
│ │ │ ├─gvfs-goa-volume-monitor.service
│ │ │ │ └─3171 /usr/libexec/gvfs-goa-volume-monitor
│ │ │ ├─app-dbus\\x2d:1.2\\x2dorg.gnome.OnlineAccounts.slice
│ │ │ │ └─dbus-:1.2-org.gnome.OnlineAccounts@0.service
│ │ │ │ └─3174 /usr/libexec/goa-daemon
│ │ │ ├─xdg-permission-store.service
│ │ │ │ └─3765 /usr/libexec/xdg-permission-store
│ │ │ ├─com.system76.SystemUpdater.Local.service With the systemd-cgtop command, we get a list of all control groups sorted by the current resource utilization:
systemd-cgtopNow, why is this important to us? Now we can analyze the resource utilization of individual processes and, if necessary, adjust the process’s priority or change the resource limit.
The man page gives us many possibilities to manage this:
man systemd.resource-controlFor example, if we want to set the memory limit of a specific service, we can use:
sudo systemctl set-property example.service MemoryMax=1GMemoryLimit= is deprecated and only works on the old cgroup v1 hierarchy, so use MemoryMax=.
Logging - JournalD
journald collects the logs of the kernel, of services and of the boot process in one place. Whether they survive a reboot depends on the Storage= setting in /etc/systemd/journald.conf. With the default auto, logs are kept on disk if the directory /var/log/journal exists and only in RAM otherwise. Ubuntu and most other distributions create that directory, so their logs persist.
You can use JournalD with the following command:
journalctlWe can further refine the output by adding filters, for example, with a specific time:
journalctl --since yesterdayWe can refine it even more by specifying an exact time period from to:
journalctl --since "2026-11-01 08:00" --until "2026-11-02 18:00"Another way to filter is to follow specific services:
journalctl -u exampleWe can also follow a specific service and filter just for this one:
journalctl -fu exampleWe could also filter just for kernel events:
journalctl -kOr only the messages of the current boot, or only errors:
journalctl -b
journalctl -p errJournal logs can grow large. This trims them to 500 MB:
sudo journalctl --vacuum-size=500MFAQ
How do I check if a service is running with systemd?
Run systemctl status <service>. It shows whether the service is active, its main process ID and the last log lines. For scripts, systemctl is-active <service> prints just active or inactive.
How do I make a service start at boot?
Run sudo systemctl enable <service>, or sudo systemctl enable --now <service> to also start it immediately. systemctl is-enabled <service> tells you the current state.
How do I check if my system uses systemd?
Run ps -p 1 -o comm=. If it prints systemd, you are on systemd. Distributions such as Ubuntu, Debian, Fedora, Arch and RHEL use it by default.
What is the difference between systemd and systemctl?
systemd is the system and service manager that runs as process ID 1. systemctl is the command line tool you use to talk to it, for example to start, stop or enable services.
How do I create my own systemd service?
Create a file such as /etc/systemd/system/myapp.service with a [Unit], a [Service] section containing ExecStart=/path/to/your/program, and an [Install] section with WantedBy=multi-user.target. Then run sudo systemctl daemon-reload and sudo systemctl enable --now myapp.
Summary
systemd is the standard successor to the classic System V init daemon and gives the admin a lot of useful information and tools that speed up everyday work. If you want to learn more about other in-depth Linux topics, make sure to visit Max Wilke’s blog.
- systemd is the init system and service manager on most Linux distributions. It starts services in parallel and runs as process ID 1.
- Unit files describe services, timers, mounts and more. Put your changes in
/etc/systemd/system. - Control groups let you limit and measure resources per service, and journald collects the logs.
- Some admins dislike systemd for its large scope and binary logs, but it is the default on nearly every major distribution.
🐧 There are some related articles!
👉 Top Things to do after installing Kali Linux
👉 Linux on Windows - The Complete WSL 2 Tutorial Series
👉 Create Generalized Windows Images with FOG Server
👉 Install FOG Server on Ubuntu
👉 Install Kali Linux on Windows - Complete Guide
👉 The Complete Kali Linux and Windows Dual Booting Guide
👉 Cronjob - The Complete Guide to Cronjobs
👉 Open Bitlocker Drive on Linux - Quick & Easy
More posts
All Linux

