Systemd : Basic concepts

May 21, 2024 by Thibault Debatty | 527 views

Linux Sysadmin

https://cylab.be/blog/341/systemd-basic-concepts

Systemd is now the defacto standard init process on Linux systems. It is responsible for starting all required services… In this blog post we will present the basic concepts of systemd : basic usage, units and dependencies.

computer-launch-1600.jpg

Features

When the system boots, systemd is the first running process (pid 1).

systemd-pid-1.png

Systemd is then responsible for starting all required services.

VirtualBox_ubuntu-22.png

Unlike older init systems (System V and Upstart), Systemd provides additional features:

  • track the main service process and its child processes (using cgroups), and restart them if needed (like supervisor);
  • optimize the boot process by delaying service activation until they are required.

We will cover these features in the followup blog post.

Systemd also integrates other services that were previously separate systems:

  • cron to run tasks at a regular interval;
  • inetd to handle incoming network connections;
  • journald to hand log messages;
  • resolved to perform DNS requests;
  • udevd to manage connected devices.

Basic concepts and usage

Systemd configuration is defined in unit files. You can list systemd units with:

systemctl list-units --all

systemctl-list-units.png

  • the LOAD column indicates if the unit file was correctly found and parsed;
  • the ACTIVE column indicates if the unit was started;
  • the SUB column indicates if the current state of the unit. The value depends on the unit type (see below). For a service, it would show that the unit is currently running (or not).

You can get more information about a single Unit with:

sudo systemctl status <unit>

For example:

sudo systemctl status cron.service 

systemctl-status.png

Systemd has a built-in journal (logging) system. So you can get the log messages generated by a Unit with:

journalctl --unit=<unit>

systemd-journalctl.png

You can manually start or stop a Unit with the following command. Remember that this is a one-shot and will not restart the unit after a reboot:

systemctl start <unit>
systemctl stop <unit>

The following command allows to enable or disable a unit at boot (more about this below):

systemctl enable <unit>
systemctl disable <unit>

Unit types

As you may have noticed in the output of the systemctl list-units --all command, systemd defines diferent types of units. You can recognize them by their suffix:

  • service units are the classical services. They allow to start daemon processes.
  • target units are used to group units together using dependency definition (see below). As a consequence, all systemd units have a common parent (root), called default.target.
  • socket units represent an incoming network connection. There are used to start services only when required (when a network connection is received).
  • mount units represent mounted filesystems.
  • timer units allow to schedule jobs on a regular interval (like cron).

Unit files location

Systemd configuration is defined in unit files. These files can be found in different places:

  • the system unit directory is usually located in /usr/lib/systemd/system or /lib/systemd/system and is managed by your distribution maintainer (so you should not modify stuff here);
  • the system configuration directory is usually located in /etc/systemd/system and contains local configuration units;
  • there is also a special directory, usually located at /run/systemd/system that contains runtime unit definitions.

You can check the exact location of these directories on your system with:

systemctl -p UnitPath show

systemctl-unitpath.png

Unit definition

Unit files are regular text files, very similar to ini files. Here is a simplified example for a service Unit:

[Unit]
Description=Description of the Unit
Wants=otherunit.service

[Service]
Type=oneshot
ExecStart=/command/to/execute

In this simple example:

  • Wants list other units to activate when this unit is started (see below).
  • Type=oneshot indicates that this service is a short-lived process that will not keep running in the background (hence not a daemon). So systemd should not try to restart the process when it ends.

A simple example

To illustrate units, create the file /etc/systemd/system/test1.target with the following content:

[Unit]
Description=Test 1
Wants=test2.service

And the file /etc/systemd/system/test2.service with the following content:

[Unit]
Description=Test 2

[Service]
Type=oneshot
ExecStart=echo "hi!"

Each time you create or modify unit files, don’t forget to reload unit definitions:

sudo systemctl daemon-reload

You can now activate test1.target with:

sudo systemctl start test1.target

If all went well, test1.target should be activated, and test2.service should have been executed once :

systemctl status test1.target test2.service

Also, the messages of test2.service (“hi!”) should appear in the journal:

journalctl --unit=test2.service

systemd-example.png

Unit dependencies

In the previous example, we have shown how to define dependencies between units. There are actually other configuration directives to define dependencies:

  • Requires defines a “life-long” dependency. If A Requires B:
    • when A is started, systemd will start B
    • if B is stopped, systemd will stop A
  • Wants defines a start dependency. If A Wants B:
    • when A is started, systemd will start B
    • if B is stopped, A will keep running
  • Requisite defines a prior-start dependency. If A Requisite B:
    • when A is started, systemd will first start B
  • Conflicts defines … conflicting units. If A Conflicts B:
    • when A is started, systemd will stop B

Next to these explicit dependencies, systemd also supports implicit dependencies, based on names. This is for example used to link a resource unit to the corresponding service (we will cover this in the followup post).

You can view the unit dependencies with

systemctl list-dependencies

systemctl-list-dependencies.png

Enable and reverse dependency

Systemd uses multiple trees (a forest) to keep track of unit dependencies. This allows to easily determine which units must be started an when. The main tree, which is used for the boot process, starts with the default.target unit.

Next to direct dependencies that we have show above, you can also ‘attach’ your unit to some other parent unit. To do so you must:

  1. add an [Install] section in your unit definition, like this one:
[Install]
WantedBy=otherunit
  1. enable the unit.

systemd-dependencies.png

For example, create the file /etc/systemd/system/test3.service with the following content:

[Unit]
Description=Test3

[Service]
Type=oneshot
ExecStart=echo "hi!"

[Install]
WantedBy=test1.target

This service can be enabled, which will link the unit to its parent:

systemctl enable test3.service

When you enable test3.service, systemd automatically adds a Wants dependency from test1 to test3. This ensures that test3.service will also be activated when test1.target is started.

systemd-enable.png

Remember that only units with an Install section can be enabled.

If you want your unit to be started at boot, you should typically add an Install section and indicate that your unit is WantedBy another unit which you know will be activated on boot. Here is a list of some common target units, where you could “attach” your unit:

  • basic.target : Basic System
  • multi-user.target : Multi-User System
  • graphical.target : Graphical Interface
  • network-online.target : Network is Online

You can also list all targets on your system with

systemctl list-units --all --type=target

Going further

Want to know more about systemd? Have a look at our second post in the series, where we cover systemd process tracking and resource units

This blog post is licensed under CC BY-SA 4.0

This website uses cookies. More information about the use of cookies is available in the cookies policy.
Accept