Guide to use systemd with Yocto Project

What is systemd

Systemd is an initialization software for the GNU/Linux operating system, also known as the system daemon. Developed to improve service management, systemd allows for parallel service startup and simplifies dependencies between them. It replaces the traditional SysVinit startup system, optimizing efficiency and reducing the load on the shell. In systemd, system resources, such as services and devices, are represented as units configured through specific files. This approach unifies service behavior across various Linux distributions, making their use more consistent and manageable via the systemctl command.

By following this guide, you will learn the basics of using systemd in the Yocto Project build.

systemd and yocto project

Systemd Commands

Systemd, also known as the system daemon, is an initialization software for the GNU/Linux operating system.

Development goals:

  • To provide a better framework for representing dependencies between services
  • To implement parallel service startup during system initialization
  • To reduce the workload on the shell and replace the SysV-style init

systemd provides a series of system components for the GNU/Linux operating system to unify the configuration and behavior of services across various GNU/Linux distributions and eliminate differences in their usage.

Installing systemd in Yocto Project

If systemd is not enabled by default in your Yocto Project final image you are very likely still using SystemV. Add the following lines to the local.conf to enable systemd as default init manager.

DISTRO_FEATURES:append = " systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED += "sysvinit"
VIRTUAL-RUNTIME_init_manager = "systemd"
VIRTUAL-RUNTIME_initscripts = "systemd-compat-units"

Unit

In systemd, a unit is a configuration object that represents and manages system resources, such as services, mount points, devices, etc. Units are defined by configuration files that specify how they should be started, stopped, and managed. Each unit has a configuration file with a specific extension indicating the unit type.

Unit types

The systemctl command is the primary tool for managing systemd, and it is a combination of the previous service and chkconfig commands.

  • Service: Manages system services and daemons. Examples include nginx.service for the Nginx web server and sshd.service for the SSH daemon.
  • Socket: Manages network or Unix domain sockets used to activate services based on sockets. Examples include cups.socket.
  • Device: Represents kernel devices managed by udev or other device managers.
  • Target: Represents a boot phase or a group of units. Examples include multi-user.target and graphical.target.
  • Timer: Manages timers that can activate other units at regular intervals or specific times. Examples include apt-daily.timer.

The usage of the systemctl command is - systemctl [OPTIONS...] COMMAND [UNIT...].


Content of a systemd unit file

Sections

In systemd, the names written in square brackets, such as [Unit], [Service], [Install], etc., are called sections. Each section groups related directives that configure specific aspects of the unit. These sections are used in unit configuration files (.service, .socket, .target, etc.) to organize various settings.

Common Sections

[Unit] Contains general directives that describe the unit and its dependencies. Examples of directives:

  • Description=: A human-readable description of the unit.
  • After=: Specifies units that must be started before this one.
  • Requires=: Lists the units that are required for this unit to start.

[Service] Used in .service files to configure services. Examples of directives:

  • ExecStart=: The command to execute to start the service.
  • ExecStop=: The command to execute to stop the service.
  • Restart=: Configures if and when the service should be restarted in case of failure.

[Install] Contains directives related to installing the unit, such as when and how it should be started. Examples of directives:

  • WantedBy=: Specifies the targets in which this unit should be started.
  • RequiredBy=: Specifies the targets that require this unit.

[Socket] Used in .socket files to configure sockets. Examples of directives:

  • ListenStream=: Specifies the network or file socket address.
  • Accept=: Configures whether systemd should create an instance for each incoming connection.

[Mount] Used in .mount files to configure mount points. Examples of directives:

  • What=: Specifies the device or filesystem to mount.
  • Where=: Specifies the mount point in the filesystem.

[Timer] Used in .timer files to configure timers. Examples of directives:

  • OnCalendar=: Configures when the timer should be triggered.
  • Unit=: Specifies the unit to activate when the timer fires.

Options

The options of systemd, often called directives, are specific configurations used in systemd unit files to define the behavior of a unit. These directives are found within sections in the unit configuration files (such as [Unit], [Service], [Install], etc.). Options allow you to control various aspects of the unit, such as how to start a service, what dependencies it has, and how to handle errors.

[Unit]

  • Description=: Provides a brief description of the unit.
  • Documentation=: Link to documentation related to the unit.
  • After=: Defines units that must be started before this one.
  • Requires=: Specifies units required by this unit. If one of these units is not active, this unit will not start.
  • Wants=: Similar to Requires=, but does not cause startup failure if the specified unit is not active.

[Service]

  • ExecStart=: Command to execute to start the service.
  • ExecStop=: Command to execute to stop the service.
  • ExecStartPre= ExecStartPost=: These directives execute one or more commands before/after executing the command specified in ExecStart=.
  • ExecReload=: Command to execute to reload the service.
  • Restart=: Defines the service restart conditions. Possible values include no, on-success, on-failure, on-abnormal, on-watchdog, on-abort, always.
  • Type=: Specifies the service type. Common values include simple, forking, oneshot, dbus, notify, idle.
  • User=: Runs the service as the specified user.
  • Group=: Runs the service as the specified group.

[Install]

  • WantedBy=: Specifies the targets in which this unit should be started.
  • RequiredBy=: Specifies the targets that require this unit.
  • Alias=: Creates an alias for the unit.

Creating a service

To create a service, you need to use the following key-value pairs:

Type=

  • notify – Configure the type of the “.service” unit, which can be one of the following:
  • simple – The service starts as the main process. This is the default setting.
  • forking – The service calls forked processes and runs as part of the main daemon.
  • exec – Similar to simple. The service manager will start this unit immediately after executing the main service binary. Subsequent units must remain blocked until this point before continuing startup.
  • oneshot – Similar to simple, but the process must exit before systemd starts follow-up services.
  • dbus – Similar to simple, except the daemon acquires the D-Bus bus name.
  • notify – Similar to simple, except the daemon sends a notification message using sd_notify or an equivalent call after startup.
  • idle – Similar to simple, except service execution is delayed until all active jobs are dispatched.

ExecStartPre= Additional commands executed before the commands in ExecStart.

ExecStartPost= Additional commands executed after the commands in ExecStart.

ExecStop= Commands and arguments executed when stopping the service.

ExecStopPost= Additional commands executed after stopping the service.

TimeoutSec= A shorthand to configure both TimeoutStartSec and TimeoutStopSec simultaneously.

Restart=

  • on-failure – Configures whether to restart the service when the service process exits, is terminated, or times out:
  • no – The service will not be restarted. This is the default setting.
  • on-success – Restarts only when the service process exits cleanly (exit code 0).
  • on-failure – Restarts only when the service process does not exit cleanly (non-zero exit code).
  • on-abnormal – Restarts if the process terminates with a signal or when a timeout occurs.
  • on-abort – Restarts if the process exits due to an unexpected signal not specified as a clean exit condition.
  • on-watchdog – If set to on-watchdog, the service restarts only if the watchdog timeout expires.
  • always – Always restarts.

Service example

[Unit]
Description=saveDate

[Service]
Type=oneshot
# Executes the shell command between ' '
ExecStart=/bin/sh -c 'date >> /home/root/data.log'

[Install]
WantedBy=default.target

Explanation: The program logs into the file data.log the string printed by the date command of bash, containing the current date and time.

[Unit]

  • Description=saveDate: A description of the service.

[Service]

  • ExecStart=: The main command that the service executes.
  • Type=: Specifies that the service should run only once and terminate.

Execution prefixes

“@” If the executable path is prefixed with “@”, the second specified token will be passed as argv[0] to the executed process (instead of the actual file name), followed by the additional specified arguments. This prefix is used to instantiate service units.

“-” If the executable path is prefixed with “-”, a command exit code that is normally considered a failure is logged, but has no further effect and is considered equivalent to success. This prefix indicates that the service unit is disabled.

“:” If the executable path is prefixed with “:”, environment variable substitution is not applied. It can be used to separate specific parts of a service unit or indicate something specific within a service unit definition.

“+” If the executable path is prefixed with “+”, the process runs with full privileges.

“!” This prefix is used in some special situations with systemd, such as to force the activation of a service or override a default configuration.

“!!” This prefix is used to ignore service execution errors in systemd.


Useful setup commands

Below are listed and explained the commands primarily used in the context of service and process management on Linux-based systems, particularly those using systemd as the init system:

  • systemctl status – Can be used in various contexts to check the status of a service or component.
  • systemctl status <name> -l – Used to obtain detailed status of a specific service, and with the -l option, it avoids line truncation, showing the full log.
  • systemctl enable <name> – Enables a specific service to start automatically at boot. Ensures that the service will start automatically at the next system reboot.
  • systemctl disable <name> – Disables a specific service from starting automatically at boot. Ensures that the service will not start automatically at the next system reboot.
  • systemctl start <name> – Immediately starts the specified service without changing the service’s startup settings.
  • systemctl stop <name> – Immediately stops the specified service.
  • journalctl -n <name> – Shows the logs related to a specific unit.
  • systemctl daemon-reload – This command reloads the daemon configuration files. Useful when unit files have been modified.

In conclusion, systemd streamlines service management on GNU/Linux systems, offering powerful tools to start, stop, and monitor system resources. By organizing services and components into units, it provides a standardized and efficient way to configure system behavior. With commands like systemctl, administrators can easily manage service dependencies, handle errors, and ensure a smooth and stable operation. The flexibility and robustness of systemd make it a crucial part of modern Linux environments, simplifying administration while improving system performance and reliability.

Author: Sara Cavallini – ©2024 Copyright – KOAN sas

Share this post: