Difference between revisions of "XELK-AN-008: How to use systemd on an Embedded system"

From DAVE Developer's Wiki
Jump to: navigation, search
(32 intermediate revisions by 2 users not shown)
Line 3: Line 3:
 
{{AppliesToAxelEsatta}}
 
{{AppliesToAxelEsatta}}
 
{{AppliesToAxelLite}}
 
{{AppliesToAxelLite}}
 +
{{AppliesToAXEL Lite AN}}
 +
{{AppliesToSMARX AN}}
 +
{{AppliesToSBCX}}
 +
{{AppliesToSBC Axel AN}}
 
{{InfoBoxBottom}}
 
{{InfoBoxBottom}}
  
Line 24: Line 28:
 
Starting from [[Axel_Embedded_Linux_Kit_(XELK)#XELK_4.0.0|XELK 4.0.0]] the root file system generated by NXP Yocto recipes produces a root file system using [https://www.freedesktop.org/wiki/Software/systemd/ systemd].
 
Starting from [[Axel_Embedded_Linux_Kit_(XELK)#XELK_4.0.0|XELK 4.0.0]] the root file system generated by NXP Yocto recipes produces a root file system using [https://www.freedesktop.org/wiki/Software/systemd/ systemd].
  
Systemd is a ''System and Service Manager'' which has enough different settings and configuration from systemV which was used on all XELK BSPs up to [[Axel_Embedded_Linux_Kit_(XELK)#XELK_3.0.0|XELK 3.0.0]].
+
systemd is a ''System and Service Manager'' which has enough different settings and configuration from SystemV(SysV) which was used on all XELK BSPs up to [[Axel_Embedded_Linux_Kit_(XELK)#XELK_3.0.0|XELK 3.0.0]].
  
== Brief description ==
+
{{ImportantMessage|text=This application note '''is not a complete systemd user's guide''' but collects some useful hints that can be used for getting familiar with systemd. There is a plenty of documentation and User's Guide available for systemd, but some simple examples - that can be found here below - may simplify the systemd approach for beginners.}}
Systemd, differing from SystemV, manages not only services but many different objects called Unit. Unit are related to the resources that systemd can manage. Unit configurations are defined into the ''Unit files''.
 
  
Units categoris (identified by the file extension) are:
+
== Architecture ==
 +
 
 +
Here below, a picture (from [https://en.wikipedia.org/wiki/Systemd#Core_components_and_libraries wikipedia]) showing the main systemd components:
 +
 
 +
[[File: Systemd_components.png]]
 +
 
 +
== Configuring systemd ==
 +
 
 +
The most used commands on a Linux embedded system are the commands used for: start a service, looking at logging, evalutate the boot time and configuring the network interface.
  
    .service
+
In the following paragraphs, there are the related commands used for these tasks.
    .target
 
    .socket
 
    .device
 
    .mount
 
    .automount
 
    .swap
 
    .path
 
    .timer
 
    .snapshot
 
    .slice
 
    .scope
 
  
Major insteresting Units are '''services''' and '''targets'''. They will be analyzed in the following paragraphs.
+
=== Manage services  ===
  
== Services  ==
+
<code>systemctl</code> is the main command utility and primary tool for managing the systemd daemons/services such as ''start, restart, stop, enable, disable, reload & status''.
  
 
It is possible to display all '''started''' services with the following userspace command:
 
It is possible to display all '''started''' services with the following userspace command:
Line 52: Line 52:
 
  systemctl -t service
 
  systemctl -t service
  
It is possible to display all services (including '''disabled''' and '''stopped''' services):
+
It is possible to display all services (including '''disabled''' and '''stopped''' services) with:
  
 
  systemctl -t service --all
 
  systemctl -t service --all
  
=== Other useful service commands ===
+
==== service commands ====
  
 
Starting a service from userspace:
 
Starting a service from userspace:
Line 74: Line 74:
 
  systemctl disable ''<service_name>''
 
  systemctl disable ''<service_name>''
  
== Targets ==
+
==== mask a service ====
 +
 
 +
There is a third level for stopping a service other than ''stop'' and ''disable'': it is the command <code>mask</code>.
 +
 
 +
It stops the service and it will not possible to start it again using ''start''. Using <code>systemctl</code> it is possbile to ''mask/unmask'' a service:
 +
 
 +
<pre>
 +
root@imx6qxelk:~# systemctl mask emergency
 +
Created symlink /etc/systemd/system/emergency.service → /dev/null.
 +
</pre>
 +
 
 +
If we will try to start it:
 +
<pre>
 +
root@imx6qxelk:~# systemctl start emergency
 +
Failed to start emergency.service: Unit emergency.service is masked.
 +
</pre>
  
Targets are used byt systemd for having a synchronization point between different services at boot time or during runtime changes.
+
In this way, the service will not be used as a dependency in the ''Unit''
  
They can be used for set the system to a new state.
+
The reverse command is <code>unmask</code>:
 +
<pre>
 +
root@imx6qxelk:~# systemctl unmask emergency
 +
Removed /etc/systemd/system/emergency.service.
 +
</pre>
 +
 
 +
==== Migrating from SystemV to systemd ====
 +
 
 +
===== start =====
 +
 
 +
Considering a SystemV <code>script</code> executing the ''start()'' function as in the following example:
 +
<pre>
 +
start() {
 +
  echo "Starting My Custom Service..."
 +
  /usr/bin/myservice -D
 +
}
 +
</pre>
 +
 
 +
The related command is executed in the custom service <code>/usr/bin/myservice</code> with the same '''-D''' parameter. It is possibile to use the <code>ExecStart=</code>:
 +
 
 +
<pre>
 +
[Service]
 +
ExecStart=/usr/bin/myservice -D
 +
</pre>
 +
 
 +
===== restart =====
 +
 
 +
The same SystemV script may use special commands for restarting the service like <code>reboot()</code> function:
 +
 
 +
<pre>
 +
reboot() {
 +
  echo "Reloading My Custom Service..."
 +
  /usr/bin/myservice reload
 +
}
 +
</pre>
 +
 
 +
which is equivalent to use <code>ExecReload=</code>:
 +
 
 +
<pre>
 +
[Service]
 +
ExecReload=/usr/bin/myservice reload
 +
</pre>
 +
 
 +
===== stop =====
  
All services linked to a ''target'' are linked to the modification to the same target. These can be seen in a similar way of SystemV ''runlevels'' with many other added functionalities.
+
The <code>stop()</code> function in the script will become <code>ExecStop=</code>:
  
=== Target and  runlevels ===
+
SystemV:
  
Here below there is a list of power on/off targets and related SystemV runlevels:
+
<pre>
 +
stop() {
 +
  echo "Stopping My Custom Service..."
 +
  /usr/bin/myservice shutdown
 +
}
 +
</pre>
  
{| class="wikitable"
+
systemd:
|-
 
! Description !! SystemV (runlevel) !! Systemd (target)
 
|-
 
| System halt || 0 || runlevel0.target, poweroff.target
 
|-
 
| Single user mode || 1, s, single || runlevel1.target, rescue.target
 
|-
 
| Multi user || 2 || runlevel2.target, multi-user.target
 
|-
 
| Multi user with network || 3 || runlevel3.target, multi-user.target
 
|-
 
| Experimental || 4 || runlevel4.target, multi-user.target
 
|-
 
| Multi user with network, graphical mode || 5 || runlevel5.target, graphical.target
 
|-
 
| Reboot || 6 || runlevel6.target, reboot.target
 
|}
 
  
<code>multi-user</code> target can be identified as the <code>runlevel 3</code>.
+
<pre>
 +
[Service]
 +
ExecStop=/usr/bin/myservice shutdown
 +
</pre>
  
On the  
+
=== Configuring the network  interfaces===
  
/etc/systemd/system/''<target_name>''.target.wants
+
One of the most systemd configuration used is the '''Network configuration'''.
  
directory there is a list of services related to that target.
+
==== Wired interface ====
 +
systemd uses a slightly different configuration mechanism than SystemV. The configuration file is the following one with an example of configuration:
  
For example:
+
/etc/systemd/network/eth0.network
  
 
<pre>
 
<pre>
root@imx6qxelk:~# ls /etc/systemd/system/multi-user.target.wants/
+
[Match]
atd.service       busybox-syslog.service  gpuconfig.service  ofono.service systemd-networkd.service
+
Name=eth0
avahi-daemon.service  connman.service       mytest.service   psplash-quit.service systemd-resolved.service
+
 
busybox-klogd.service  crond.service       ntpdate.service   remote-fs.target
+
# Prevent the interface loading if the kernel boots from nfs
 +
KernelCommandLine=!nfsroot
 +
 
 +
[Network]
 +
Address=192.168.0.120
 +
Gateway=192.168.0.254
 +
DNS=192.168.0.1
 +
#DNS=8.8.8.8
 +
 
 
</pre>
 
</pre>
  
=== Active targets ===
+
'''Note:'''
  
It is possible to display all active targtes with:
+
The DNS is used only if the <code>systemd-resolved</code> service is enabled and the <code>/etc/resolv.conf</code> has a symbolic link to <code>/run/systemd/resolve/stub-resolv.conf</code>
 +
 
 +
<pre>
 +
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
 +
</pre>
  
systemctl -t target
+
==== Wireless interface ====
  
Changing a target
+
===== wpa_supplicant =====
 +
wpa_supplicant provides different services on systemd:
  
systemctl isolate graphical
+
* <code>wpa_supplicant.service</code> uses D-Bus, recommended with the ''NetworkManager''
 +
* <code>wpa_supplicant@interface.service</code> uses the interface name (like ''wlan0'') as parameter and executes the wpa_supplicant daemon on that interface. The configuration file is <code>/etc/wpa_supplicant/wpa_supplicant-interface.conf</code>
  
The actual target is shown with:
+
For enabling the interface at boot time it is required to ''enable'' the service:
  
  systemctl get-default
+
  systemctl enable wpa_supplicant@interface
  
Changing the default target:
+
===== wlan configuration example =====
  
systemctl set-default multi-user
+
Assuming ''wlan0'' as the wireless interface name, the configuration file examples are the following one:
  
== Unit files ==
+
/etc/systemd/network/wlan0.network
For a complete information on '''Unit''' please look to the [https://www.freedesktop.org/software/systemd/man/systemd.unit.html documentation page]
 
  
Here below you can find an extract for the main used topics and configuration descriptions.
+
<pre>
 +
[Match]
 +
Name=wlan0
 +
[Network]
 +
# Uncomment for DHCP
 +
#DHCP=yes
 +
Address=192.168.1.120
 +
Gateway=192.168.1.254
 +
DNS=8.8.8.8
  
=== Location Path ===
+
</pre>
  
Units are configured by ''systemd'' using configuration files that can be found in different directories. Each of them has different priority and bahaviour:
+
/etc/wpa_supplicant/wpa_supplicant-wlan0.conf
  
* <code>/lib/systemd/system</code>
+
<pre>
 +
ctrl_interface=/var/run/wpa_supplicant
 +
eapol_version=1
 +
ap_scan=1
 +
fast_reauth=1
  
This directory stores a copy of configuration files. This is the default destination for new installed configuration file.  Typically files in this directory should not be modified bye the user.
+
network={
 +
    ssid="SSID1"
 +
    psk="password1"
 +
    priority=1
 +
}
 +
network={
 +
    ssid="SSID2"
 +
    psk="password2"
 +
    priority=2
 +
}
 +
</pre>
  
* <code>/etc/systemd/system</code>
+
For automatically creating the network configuration, the following command can be used:
  
This is the directory where to store a new ''Unit'' or to modify an existing one. The files present in this directory have the highest priority.
+
wpa_passphrase <ESSID> <passphrase> >> /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
  
* <code>/run/systemd/system</code>
+
Then, the service should be enabled on the ''wlan0'' interface for let systemd to start it using the (just) created configuration file <code>wpa_supplicant-wlan0.conf</code>:
The files present in this directory have higher priority only respect the ones on <code>/lib/systemd/system</code>. Systemd creates these configuration files dinamcally at runtime; modification on this directory can be used for testing a runtime behaviour for a ''Unit'' but all modifications will be lost at next boot.
 
  
=== [Unit] section ===
+
systemctl enable wpa_supplicant@wlan0
  
This section is used for defining the metadata and relations between different ''Unit''
+
== Logging with systemd (<code>journalctl</code>) ==
  
Please find below the main properties description:
+
systemd has its own logging process called <code>journal</code> avoiding to start the ''syslog'' daemon. For the status information it is possible to use <code>journalctl</code>.
  
Description=:  
+
<code>journalctl</code> ha many command line switches, to customize its behavior and filter log data (a good reference can be found [https://www.digitalocean.com/community/tutorials/how-to-use-journalctl-to-view-and-manipulate-systemd-logs here]
  
Name and function
+
For example, to display the new log messages (similar to <code>tail -f /var/log/messages</code>) add the <code>-f</code> option
  
Documentation=:
+
With <code>-p</code> it's possible to set the log ''priority''
  
URI for the documentation
+
journalctl -p LEVEL
  
Requires=:
+
Where <code>LEVEL</code> can be the number or keyword of the following table (sorted from higher to lower priority). Specifying a priority will display messages marked with that priority or higher
  
List of ''Units'' dependencies. For succesfully executing this ''Unit'', all listed dependency should be activated without errors, otherwise this Unit return ''fail''.
+
{| class="wikitable"
 +
|-
 +
! Value !! Keyword
 +
|-
 +
| 0 || emerg
 +
|-
 +
| 1 || alert
 +
|-
 +
| 2|| crit
 +
|-
 +
| 3|| err
 +
|-
 +
| 4|| warning
 +
|-
 +
| 5|| notice
 +
|-
 +
| 6|| info
 +
|-
 +
| 7|| debug
 +
|}''<time>''
 +
User can filter by arbitrary time limits using the <code>--since</code> and <code>--until</code> options, which restrict the entries displayed to those after or before the given time, respectively. E.g.:
  
Wants=:
+
<pre>
 +
root@imx6qxelk:/home# journalctl --since "20 min ago"
 +
-- Logs begin at Wed 2019-06-26 13:22:41 UTC, end at Mon 2019-07-08 13:22:01 UTC. --
 +
Jul 08 13:11:54 imx6qxelk kernel: ERROR: v4l2 capture: slave not found!
 +
Jul 08 13:11:54 imx6qxelk kernel: ERROR: v4l2 capture: slave not found!
 +
Jul 08 13:11:54 imx6qxelk kernel[551]: [ 3157.796945] ERROR: v4l2 capture: slave not found!
 +
Jul 08 13:11:54 imx6qxelk kernel[551]: [ 3157.801690] ERROR: v4l2 capture: slave not found!
 +
Jul 08 13:11:54 imx6qxelk kernel: ERROR: v4l2 capture: slave not found!
 +
Jul 08 13:11:54 imx6qxelk kernel: ERROR: v4l2 capture: slave not found!
 +
Jul 08 13:11:54 imx6qxelk kernel[551]: [ 3157.859371] ERROR: v4l2 capture: slave not found!
 +
Jul 08 13:11:54 imx6qxelk kernel[551]: [ 3157.864406] ERROR: v4l2 capture: slave not found!
 +
</pre>
  
Similar to a ''Requires'' but weaker. If the ''Unit'' listed are not found or return fail, this ''Unit'' are in any case executed. this is the recommended method to be used.
+
For displaying the log related to a specific ''Unit'', use the <code>-u</code> option, e.g.:
  
  BindsTo=:
+
<pre>
 +
root@imx6qxelk:/home# journalctl -u systemd-networkd  
 +
-- Logs begin at Wed 2019-06-26 13:22:41 UTC, end at Mon 2019-07-08 13:25:01 UTC. --
 +
Jul 05 11:02:13 imx6qxelk systemd-networkd[572]: Enumeration completed
 +
Jul 05 11:02:13 imx6qxelk systemd-networkd[572]: eth0: IPv6 enabled for interface: Success
 +
Jul 05 11:02:15 imx6qxelk systemd-networkd[572]: eth0: Gained carrier
 +
Jul 05 11:02:16 imx6qxelk systemd-networkd[572]: eth0: Gained IPv6LL
 +
Jul 05 11:02:29 imx6qxelk systemd-networkd[572]: eth0: Configured
 +
</pre>
  
Similar to ''Requires'' but it does a Sop for the ''Unit'' when the listed ''Unit'' are terminated.
+
For displaying the log related to a specific <code>/dev</code> device, just add it to the command line:
  
Before=:
+
<pre>
 +
root@imx6qxelk:~# journalctl /dev/fb0
 +
-- Logs begin at Wed 2019-06-26 13:22:41 UTC, end at Thu 2019-07-11 09:07:01 UTC. --
 +
Jun 26 13:22:41 imx6qxelk kernel: mxc_sdc_fb fb@0: registered mxc display driver ldb
 +
Jun 26 13:22:41 imx6qxelk kernel: mxc_sdc_fb fb@0: using reserved memory region at 0x8e000000, size 2 MiB
 +
Jun 26 13:22:41 imx6qxelk kernel: mxc_sdc_fb fb@0: assigned reserved memory node splashscreen
 +
Jun 26 13:22:41 imx6qxelk kernel: mxc_sdc_fb fb@0: using memory region 0x8e000000 0x8e1fffff
 +
</pre>
  
The ''Unit'' listed will not be executed until this ''Unit'' will not change to ''started''. This is used for an order of Units executions.
+
For displaying the log related to a user ID, use <code>_UID=</code> parameter
  
After=:
+
<pre>
 +
root@imx6qxelk:~# id messagebus
 +
uid=995(messagebus) gid=993(messagebus) groups=993(messagebus)
 +
root@imx6qxelk:~# journalctl _UID=993
 +
-- Logs begin at Wed 2019-06-26 13:22:41 UTC, end at Thu 2019-07-11 09:14:01 UTC. --
 +
Jul 10 14:42:48 imx6qxelk systemd-timesyncd[423]: Network configuration changed, trying to establish connection.
 +
Jul 10 14:43:02 imx6qxelk systemd-timesyncd[423]: Network configuration changed, trying to establish connection.
 +
Jul 11 07:38:31 imx6qxelk systemd-timesyncd[423]: Synchronized to time server 216.239.35.8:123 (time3.google.com).
 +
</pre>
  
The ''Unit'' listed wile be started before this ''Unit''. This is used for an order of Units executions.
+
== Analyze the boot time==
  
Conflicts=
+
Boot time analysis is one of the most important and interesting activity for an embedded system: systemd provide an userspace command called <code>systemd-analyze</code> to help in this (hard) task
  
The ''Unit'' listed cannot be executed simultaneously to this ''Unit''.
+
The <code>systemd-analyze</code> command list how many services are running on the system and how long they took for starting at the last boot.
  
=== [Install] section ===
+
<code>systemd-analyze</code> provides a good level of boot time information for further optimizations:
  
This section is optional but is comonly used for defining a ''Unit'' behaviour when it will be executed at boot time with ''enable'' command.
+
=== time ===
  
WantedBy=:
+
The <code>time</code> parameter gives the total amount of seconds used for starting the kernel and reaching the userspace.
  
This is similar to the ''Wants='' on ''[Unit]'' section but allows to mantain the top ''Unit'' more ''clean''.
+
<pre>
 +
root@imx6qxelk:~# systemd-analyze time
 +
Startup finished in 5.109s (kernel) + 4.771s (userspace) = 9.880s
 +
</pre>
  
Wwhen the ''Unit'' will be enabled, a directory on <code>/etc/systemd/system</code> will be created with the ''Unit'' name adding <code>.wants</code> to the name. Inside this directotya symbolic link  to the ''Unit'' is created.
+
=== blame ===
 +
The <code>blame</code> parameter gives the list of started services and how long they took for starting:
  
Example:
+
<pre>
 +
root@imx6qxelk:~# systemd-analyze blame
 +
          3.608s dev-mmcblk0p2.device
 +
          547ms systemd-remount-fs.service
 +
          545ms systemd-vconsole-setup.service
 +
          544ms kmod-static-nodes.service
 +
          503ms systemd-udev-trigger.service
 +
          426ms systemd-journal-flush.service
 +
          407ms tmp.mount
 +
          371ms systemd-logind.service
 +
          327ms systemd-journald.service
 +
          317ms systemd-networkd.service
 +
          275ms systemd-timesyncd.service
 +
          257ms systemd-sysctl.service
 +
          204ms ofono.service
 +
          203ms systemd-modules-load.service
 +
          194ms sys-kernel-config.mount
 +
          188ms sys-kernel-debug.mount
 +
          177ms sshd.socket
 +
          161ms psplash-start.service
 +
          138ms systemd-random-seed.service
 +
          138ms sys-fs-fuse-connections.mount
 +
          129ms systemd-udevd.service
 +
          129ms systemd-update-utmp.service
 +
          128ms systemd-tmpfiles-setup-dev.service
 +
          124ms rc-local.service
 +
            98ms systemd-tmpfiles-setup.service
 +
            91ms psplash-quit.service
 +
            90ms systemd-resolved.service
 +
            89ms systemd-backlight@backlight:backlight.service
 +
            63ms dev-mmcblk0p1.device
 +
            41ms var-volatile.mount
 +
            33ms systemd-update-utmp-runlevel.service
 +
</pre>
  
* current ''Unit'' has <code>WantedBy=multi-user.target</code>
+
=== critical-chain ===
* a directory <code>/etc/systemd/system/multi-user.target.wants</code> will be created
+
The <code>critical-chain</code> parameter shows the startup process flow and the time consumed by each service.
* the symbolic link to the ''Unit'' will be created inside the new directoty
 
* disabling the ''Unit'' the symbolic link is deleted and the relation is then removed.
 
  
RequiredBy=:
+
Here below a picture showing an example of critical path:
  
This is similar to ''WantedBy='' but a dependency cause a ''fail'' if not satisfied. When the ''Unit'' is enabled, a directory with added ''.requires'' will be created
+
[[File:Systemd-analyze-critical-chain.png|800px]]
  
Also=:
+
== Services and targets ==
 +
systemd manages not only services but many different objects called '''Unit'''. Unit are related to the resources that systemd can manage. Unit configurations are defined into the ''Unit files''.
  
When the ''Unit'' is enabled, also the listed Units are enabled too.
+
Units categoris (identified by the file extension) are:
  
=== Specific sections ===
+
    .service
 +
    .target
 +
    .socket
 +
    .device
 +
    .mount
 +
    .automount
 +
    .swap
 +
    .path
 +
    .timer
 +
    .snapshot
 +
    .slice
 +
    .scope
  
Some ''Unit'' have specific sections based on their characteristic. The most important is the section [Service] related to the Unit <code>.service</code>
+
Major interesting Units are '''services''' and '''targets'''. They will be analyzed in the following paragraphs.
  
Please find more information at the [https://www.freedesktop.org/software/systemd/man/systemd.service.html# documentation page]
+
=== Targets ===
  
==== [Service] section ====
+
Targets are used by systemd for having a synchronization mechanism between different services at boot time or during run-time changes.
  
Used for providing configurations for the ''services''.
+
They can be used for set the system to a new state.
  
===== Type =====
+
All services linked to a ''target'' are linked to the modification to the same target. These can be seen in a similar way of SystemV ''runlevels'' with many other added functionalities.
  
''Type='' should be set to :
+
==== Target and  runlevels ====
  
simple:
+
Here below there is a list of power on/off targets and related SystemV runlevels:
  
Default configuration for a service when specified <code>ExecStarts=</code>
+
{| class="wikitable"
 +
|-
 +
! Description !! SystemV (runlevel) !! systemd (target)
 +
|-
 +
| System halt || 0 || runlevel0.target, poweroff.target
 +
|-
 +
| Single user mode || 1, s, single || runlevel1.target, rescue.target
 +
|-
 +
| Multi user || 2 || runlevel2.target, multi-user.target
 +
|-
 +
| Multi user with network || 3 || runlevel3.target, multi-user.target
 +
|-
 +
| Experimental || 4 || runlevel4.target, multi-user.target
 +
|-
 +
| Multi user with network, graphical mode || 5 || runlevel5.target, graphical.target
 +
|-
 +
| Reboot || 6 || runlevel6.target, reboot.target
 +
|}
  
forking:
+
<code>multi-user</code> target can be identified as the <code>runlevel 3</code>.
  
the process will call a <code>fork()</code> when starts causing the father to exit. This informs systemd that the process is still alive even if the father has been terminated.
+
Into the following directory:
  
  oneshot:
+
  /etc/systemd/system/''<target_name>''.target.wants
  
the process has a very short execution time and then systemd should wait for its termination before continuing with other Units. this is the default configuration if ''ExecStarts='' is not specified.
+
there is a list of services related to that target.
  
dbus:
+
For example:
  
the Unit will acquire the name on the D-Bus. systemd will continue to process the other Units
+
<pre>
 +
root@imx6qxelk:~# ls /etc/systemd/system/multi-user.target.wants/
 +
atd.service       busybox-syslog.service  gpuconfig.service  ofono.service systemd-networkd.service
 +
avahi-daemon.service  connman.service       mytest.service   psplash-quit.service systemd-resolved.service
 +
busybox-klogd.service  crond.service       ntpdate.service   remote-fs.target
 +
</pre>
  
notify:
+
==== Active targets ====
  
the service will notify when completely initialized. Systemd will wait for the notification before continuing with the following Units
+
It is possible to display all active targets with:
  
  idle:
+
  systemctl -t target
  
the service will not be executed until all active jobs are dispatched.
+
Changing a target
  
===== Other options =====
+
systemctl isolate graphical
  
ExecStarts=:  
+
The actual target is shown with:
  
Specifiy the full path and parameters for executing a service. If preceded by a "-" this inform that the command failure can be accepted.
+
systemctl get-default
  
ExecStartsPre=:
+
Changing the default target:
  
Può essere utilizzata per fornire comandi aggiuntivi che dovrebbero essere eseguiti prima del processo principale. Può essere usato multiple volte, deve specificare il percorso completo del comando e può essere usato anche qui il "-" per tollerare errori.
+
systemctl set-default multi-user
  
ExecReload=:
+
=== Unit files ===
 +
For a complete information on '''Unit''' please look to the [https://www.freedesktop.org/software/systemd/man/systemd.unit.html documentation page]
  
commands to be executed for reloading the service configuration.
+
Here below you can find an extract for the main used topics and configuration descriptions.
  
ExecStop=:
+
==== Location Path ====
  
commands required for stopping the service. If missing, the service will be killed.
+
Units are configured by ''systemd'' using configuration files that can be found in different directories. Each of them has different priority and behaviour:
  
ExecStopPost=:
+
{| class="wikitable"
 +
|-
 +
! Path !! Description
 +
|-
 +
| <code>/lib/systemd/system</code> || This directory stores a copy of configuration files: this is the default destination for new installed configuration file. Typically files in this directory should not be modified by the user.
 +
|-
 +
| <code>/etc/systemd/system</code> || This is the directory where to store a new ''Unit'' or to modify an existing one. The files present in this directory have the highest priority.
 +
|-
 +
| <code>/run/systemd/system</code> || The files present in this directory have higher priority only respect the ones on <code>/lib/systemd/system</code>.
 +
Systemd creates these configuration files dinamically at runtime; modification on this directory can be used for testing a runtime behaviour for a ''Unit'' but all modifications will be lost at next boot.
 +
|}
  
commands to be executed after the service has been stopped..
+
==== [Unit] section options ====
  
RestartSec=:
+
This section is used for defining the metadata and relations between different ''Unit''
  
time to sleep (seconds) before restarting the service.
+
Please find below the main properties description:
  
Restart=:
+
{| class="wikitable"
 +
|-
 +
! Property !! Function
 +
|-
 +
| Description=: || Name and function
 +
|-
 +
| Documentation=: || URI for the documentationvv
 +
|-
 +
| Requires=: || List of ''Units'' dependencies. For successfully executing this ''Unit'', all listed dependency should be activated without errors, otherwise this Unit return ''fail''.
 +
|-
 +
| Wants=: || Similar to a ''Requires'' but weaker. If the ''Unit'' listed are not found or return fail, this ''Unit'' are executed anyway. this is the recommended method to be used.
 +
|-
 +
| BindsTo=: || Similar to ''Requires'' but it does a Stop for the ''Unit'' when the listed ''Unit'' are terminated.
 +
|-
 +
| Before=: || The ''Unit'' listed will not be executed until this ''Unit'' will not change to ''started''. This is used for an order of Units executions.
 +
|-
 +
| After=: || The ''Unit'' listed will be started before this ''Unit''. This is used for an order of Units executions.
 +
|-
 +
| Conflicts=: || The ''Unit'' listed cannot be executed simultaneously to this ''Unit''.
 +
|}
  
restart conditions for systemd to be checked before restarting the service (if terminated). Can be set to "always","on-success", "on-failure", "on-abnormal", "on-abort", or "on-watchdog".
+
==== [Install] section options ====
  
TimeoutSec=:
+
This section is optional but is commonly used for defining a ''Unit'' behaviour when it will be executed during ''enable'' or ''disable'' commands.
  
time to sleep during ''start'' or ''stop'' before considering the process failed on start or stop. Start and stop timeout can be set with different values using <code>TimeoutStartSec=</code> nad e <code>TimeoutStopSec=</code>
+
{| class="wikitable"
 +
|-
 +
! Property !! Function
 +
|-
 +
| WantedBy=: || This is similar to the <code>Wants=</code> on ''[Unit]'' section but allows to mantain the top ''Unit'' more ''clean''.
  
 +
When the ''Unit'' will be enabled, a directory on <code>/etc/systemd/system</code> will be created with the ''Unit'' name adding <code>.wants</code> to the name. Inside this directoty a symbolic link  to the ''Unit'' is created.
  
== Network Configuration ==
+
Example:
  
One of the most systemt configuration used is the '''Network configuration'''.
+
* current ''Unit'' has <code>WantedBy=multi-user.target</code>
 +
* a directory <code>/etc/systemd/system/multi-user.target.wants</code> will be created
 +
* the symbolic link to the ''Unit'' will be created inside the new directory
 +
* disabling the ''Unit'' the symbolic link is deleted and the relation is then removed.
  
systemd uses a slightly different configuration mechanism than SystemV. The configuration file is the following one with an example of configuration:
+
|-
 +
| RequiredBy=: || This is similar to <code>WantedBy=</code> but a dependency cause a ''fail'' if not satisfied. When the ''Unit'' is enabled, a directory with added ''.requires'' will be created
 +
|-
 +
| Also=: || When the ''Unit'' is enabled, also the listed Units are enabled too.
 +
|}
  
/etc/systemd/network/eth0.network
+
==== Specific sections ====
  
<pre>
+
Some ''Unit'' have specific sections based on their characteristic. The most important is the section '''Service''' related to the Unit <code>.service</code>
[Match]
 
Name=eth0
 
  
# Prevent the interface loading if the kernel boots from nfs
+
Please find more information at the [https://www.freedesktop.org/software/systemd/man/systemd.service.html# documentation page]
KernelCommandLine=!nfsroot
 
  
[Network]
+
===== [Service] section =====
Address=192.168.0.120
 
Gateway=192.168.0.254
 
DNS=192.168.0.1
 
#DNS=8.8.8.8
 
  
</pre>
+
Used for providing configurations for the ''services''.
  
'''Note:'''
+
====== Type ======
  
The DNS is used only if the <code>systemd-resolved</code> service is enabled and the <code>/etc/resolv.conf</code> has a symbloic link to <code>/run/systemd/resolve/stub-resolv.conf</code>
+
<code>Type=</code> uses one of the (main) following values:
  
<pre>
+
{| class="wikitable"
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
+
|-
</pre>
+
! Value !! Description
 +
|-
 +
| simple || Default configuration for a service when specified <code>ExecStarts=</code>
 +
|-
 +
| forking || the process will call a <code>fork()</code> when starts causing the father to exit. This informs systemd that the process is still alive even if the father has been terminated.
 +
|-
 +
| oneshot: || the process has a very short execution time and then systemd should wait for its termination before continuing with other Units. this is the default configuration if <code>ExecStarts=</code> is not specified.
 +
|-
 +
| dbus || the Unit will acquire the name on the D-Bus. systemd will continue to process the other Units
 +
|-
 +
| notify || the service will notify when completely initialized. systemd will wait for the notification before continuing with the following Units
 +
|-
 +
| idle || the service will not be executed until all active jobs are dispatched.
 +
|}
  
=== wireless ===
+
====== Other options ======
  
==== wpa_supplicant ====
+
{| class="wikitable"
wpa_supplicant provides different services on systemd:
+
|-
 +
! Value !! Description
 +
|-
 +
| ExecStarts=: || Specifiy the full path and parameters for executing a service. If preceded by a "-" this inform that the command failure can be accepted.
 +
|-
 +
| ExecStartsPre=: || used for adding more commands to be executed before starting the main process. May be used multiple times specifying the complete path and command parameters.
 +
|-
 +
| ExecReload=: || commands to be executed for reloading the service configuration.
 +
|-
 +
| ExecStop=: || commands required for stopping the service. If missing, the service will be killed.
 +
|-
 +
| ExecStopPost=: || commands to be executed after the service has been stopped..
 +
|-
 +
| RestartSec=: || time to sleep (seconds) before restarting the service.
 +
|-
 +
| Restart=: || restart conditions for systemd to be checked before restarting the service (if terminated). Can be set to "always","on-success", "on-failure", "on-abnormal", "on-abort", or "on-watchdog".
 +
|-
 +
| TimeoutSec=: || time to sleep during ''start'' or ''stop'' before considering the process failed on start or stop. Start and stop timeout can be set with different values using <code>TimeoutStartSec=</code> and <code>TimeoutStopSec=</code>
 +
|}
  
* <code>wpa_supplicant.service</code> uses D-Bus, recommende with the ''NetworkManager''
+
== Putting it all together: create a new service ==
* <code>wpa_supplicant@interface.service</code> uses the interface name (like ''wlan0'') as parameter ansd executes the wpa_supplicant daemon on that interface. The configuration file is <code>/etc/wpa_supplicant/wpa_supplicant-interface.conf</code>
 
  
For enabling the interface at boot time it is required to start the service
+
For creating a new service the following file has to be created:
  
  systemctl enable wpa_supplicant@interface
+
  /etc/systemd/system/''<service_name>''.service
  
==== Configuration example ====
+
=== Service example ===
  
Assuming ''wlan0'' as the wireless interface name, the a configuration file example are the following one:
+
The following paragraph shows how to create a new service called <code>iperf3</code> executing the iperf3 command in server mode
  
  /etc/systemd/network/wlan0.network
+
  /etc/systemd/system/iperf3.service
  
 
<pre>
 
<pre>
[Match]
+
[Unit]
Name=wlan0
+
Description=iperf3 server mode
[Network]
+
After=network.target
# Uncomment for DHCP
+
StartLimitIntervalSec=0
#DHCP=yes
+
 
Address=192.168.1.120
+
[Service]
Gateway=192.168.1.254
+
Type=simple
DNS=8.8.8.8
+
Restart=0
 +
RestartSec=1
 +
User=root
 +
ExecStart=/usr/bin/iperf3 -s
  
 +
[Install]
 +
WantedBy=multi-user.target
 
</pre>
 
</pre>
  
/etc/wpa_supplicant/wpa_supplicant-wlan0.conf
+
=== Basic settings ===
  
<pre>
+
{| class="wikitable"
ctrl_interface=/var/run/wpa_supplicant
+
|-
eapol_version=1
+
! Parameter !! Description
ap_scan=1
+
|-
fast_reauth=1
+
| After || The executed command (''iperf3'') requires the network interface to be already active, so we use <code>After</code> for this purpose.
 +
|-
 +
| Restart || This is configured with ''0'' for disabling the service after it has been run.
 +
|-
 +
| RestartSec || time sleep before restarting the service; default value is 100ms.
 +
|-
 +
| User || configures the ''user'' or ''group'' used for executing the service.
 +
|-
 +
| ExecStart || command to be executed when the service will be started (in our case ''iperf3'').
 +
|-
 +
| WantedBy || defines which target is used related to the service started.
 +
|}
  
network={
+
=== Running a service ===
    ssid="SSID1"
 
    psk="password1"
 
    priority=1
 
}
 
network={
 
    ssid="SSID2"
 
    psk="password2"
 
    priority=2
 
}
 
</pre>
 
  
For automatically creating the netwrok configuration, the following command can be used:
+
Starting the service from userspace:
  
  wpa_passphrase <ESSID> <passphrase> >> /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
+
  systemctl start iperf3
  
Then, the sercice should be enabled on the ''wlan0'' interface for instructing systemd to start itusing the (just) created configuration file <code>wpa_supplicant-wlan0.conf</code>:
+
Starting the service at boot time:
  
  systemctl enable wpa_supplicant@wlan0
+
  systemctl enable iperf3

Revision as of 16:06, 9 November 2020

Info Box
Axel-04.png Applies to Axel Ultra
Axel-02.png Applies to AXEL ESATTA
Axel-lite 02.png Applies to Axel Lite
SBC-AXEL-02.png Applies to SBC AXEL


200px-Emblem-important.svg.png

This application note has been validated starting from the XELK 4.0.0 kit version.

History[edit | edit source]

Version Date XELK version Notes
1.0.0 Sep 2019 4.0.0

Introduction[edit | edit source]

Starting from XELK 4.0.0 the root file system generated by NXP Yocto recipes produces a root file system using systemd.

systemd is a System and Service Manager which has enough different settings and configuration from SystemV(SysV) which was used on all XELK BSPs up to XELK 3.0.0.


200px-Emblem-important.svg.png

This application note is not a complete systemd user's guide but collects some useful hints that can be used for getting familiar with systemd. There is a plenty of documentation and User's Guide available for systemd, but some simple examples - that can be found here below - may simplify the systemd approach for beginners.

Architecture[edit | edit source]

Here below, a picture (from wikipedia) showing the main systemd components:

Systemd components.png

Configuring systemd[edit | edit source]

The most used commands on a Linux embedded system are the commands used for: start a service, looking at logging, evalutate the boot time and configuring the network interface.

In the following paragraphs, there are the related commands used for these tasks.

Manage services[edit | edit source]

systemctl is the main command utility and primary tool for managing the systemd daemons/services such as start, restart, stop, enable, disable, reload & status.

It is possible to display all started services with the following userspace command:

systemctl -t service

It is possible to display all services (including disabled and stopped services) with:

systemctl -t service --all

service commands[edit | edit source]

Starting a service from userspace:

systemctl start <service_name>

Stopping a service from userspace

systemctl stop <service_name>

Starting a service at boot time:

systemctl enable <service_name>

Disabling service (already started at boot time):

systemctl disable <service_name>

mask a service[edit | edit source]

There is a third level for stopping a service other than stop and disable: it is the command mask.

It stops the service and it will not possible to start it again using start. Using systemctl it is possbile to mask/unmask a service:

root@imx6qxelk:~# systemctl mask emergency
Created symlink /etc/systemd/system/emergency.service → /dev/null.

If we will try to start it:

root@imx6qxelk:~# systemctl start emergency
Failed to start emergency.service: Unit emergency.service is masked.

In this way, the service will not be used as a dependency in the Unit

The reverse command is unmask:

root@imx6qxelk:~# systemctl unmask emergency
Removed /etc/systemd/system/emergency.service.

Migrating from SystemV to systemd[edit | edit source]

start[edit | edit source]

Considering a SystemV script executing the start() function as in the following example:

start() {
  echo "Starting My Custom Service..."
  /usr/bin/myservice -D
}

The related command is executed in the custom service /usr/bin/myservice with the same -D parameter. It is possibile to use the ExecStart=:

[Service]
ExecStart=/usr/bin/myservice -D
restart[edit | edit source]

The same SystemV script may use special commands for restarting the service like reboot() function:

reboot() {
  echo "Reloading My Custom Service..."
  /usr/bin/myservice reload
}

which is equivalent to use ExecReload=:

[Service]
ExecReload=/usr/bin/myservice reload
stop[edit | edit source]

The stop() function in the script will become ExecStop=:

SystemV:

stop() {
  echo "Stopping My Custom Service..."
  /usr/bin/myservice shutdown
}

systemd:

[Service]
ExecStop=/usr/bin/myservice shutdown

Configuring the network interfaces[edit | edit source]

One of the most systemd configuration used is the Network configuration.

Wired interface[edit | edit source]

systemd uses a slightly different configuration mechanism than SystemV. The configuration file is the following one with an example of configuration:

/etc/systemd/network/eth0.network
[Match]
Name=eth0

# Prevent the interface loading if the kernel boots from nfs
KernelCommandLine=!nfsroot

[Network]
Address=192.168.0.120
Gateway=192.168.0.254
DNS=192.168.0.1
#DNS=8.8.8.8

Note:

The DNS is used only if the systemd-resolved service is enabled and the /etc/resolv.conf has a symbolic link to /run/systemd/resolve/stub-resolv.conf

ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

Wireless interface[edit | edit source]

wpa_supplicant[edit | edit source]

wpa_supplicant provides different services on systemd:

  • wpa_supplicant.service uses D-Bus, recommended with the NetworkManager
  • wpa_supplicant@interface.service uses the interface name (like wlan0) as parameter and executes the wpa_supplicant daemon on that interface. The configuration file is /etc/wpa_supplicant/wpa_supplicant-interface.conf

For enabling the interface at boot time it is required to enable the service:

systemctl enable wpa_supplicant@interface
wlan configuration example[edit | edit source]

Assuming wlan0 as the wireless interface name, the configuration file examples are the following one:

/etc/systemd/network/wlan0.network
[Match]
Name=wlan0
[Network]
# Uncomment for DHCP
#DHCP=yes
Address=192.168.1.120
Gateway=192.168.1.254
DNS=8.8.8.8

/etc/wpa_supplicant/wpa_supplicant-wlan0.conf
ctrl_interface=/var/run/wpa_supplicant
eapol_version=1
ap_scan=1
fast_reauth=1

network={
    ssid="SSID1"
    psk="password1"
    priority=1
}
network={
    ssid="SSID2"
    psk="password2"
    priority=2
}

For automatically creating the network configuration, the following command can be used:

wpa_passphrase <ESSID> <passphrase> >> /etc/wpa_supplicant/wpa_supplicant-wlan0.conf

Then, the service should be enabled on the wlan0 interface for let systemd to start it using the (just) created configuration file wpa_supplicant-wlan0.conf:

systemctl enable wpa_supplicant@wlan0

Logging with systemd (journalctl)[edit | edit source]

systemd has its own logging process called journal avoiding to start the syslog daemon. For the status information it is possible to use journalctl.

journalctl ha many command line switches, to customize its behavior and filter log data (a good reference can be found here

For example, to display the new log messages (similar to tail -f /var/log/messages) add the -f option

With -p it's possible to set the log priority

journalctl -p LEVEL

Where LEVEL can be the number or keyword of the following table (sorted from higher to lower priority). Specifying a priority will display messages marked with that priority or higher

Value Keyword
0 emerg
1 alert
2 crit
3 err
4 warning
5 notice
6 info
7 debug

User can filter by arbitrary time limits using the --since and --until options, which restrict the entries displayed to those after or before the given time, respectively. E.g.:

root@imx6qxelk:/home# journalctl --since "20 min ago" 
-- Logs begin at Wed 2019-06-26 13:22:41 UTC, end at Mon 2019-07-08 13:22:01 UTC. --
Jul 08 13:11:54 imx6qxelk kernel: ERROR: v4l2 capture: slave not found!
Jul 08 13:11:54 imx6qxelk kernel: ERROR: v4l2 capture: slave not found!
Jul 08 13:11:54 imx6qxelk kernel[551]: [ 3157.796945] ERROR: v4l2 capture: slave not found!
Jul 08 13:11:54 imx6qxelk kernel[551]: [ 3157.801690] ERROR: v4l2 capture: slave not found!
Jul 08 13:11:54 imx6qxelk kernel: ERROR: v4l2 capture: slave not found!
Jul 08 13:11:54 imx6qxelk kernel: ERROR: v4l2 capture: slave not found!
Jul 08 13:11:54 imx6qxelk kernel[551]: [ 3157.859371] ERROR: v4l2 capture: slave not found!
Jul 08 13:11:54 imx6qxelk kernel[551]: [ 3157.864406] ERROR: v4l2 capture: slave not found!

For displaying the log related to a specific Unit, use the -u option, e.g.:

root@imx6qxelk:/home# journalctl -u systemd-networkd  
-- Logs begin at Wed 2019-06-26 13:22:41 UTC, end at Mon 2019-07-08 13:25:01 UTC. --
Jul 05 11:02:13 imx6qxelk systemd-networkd[572]: Enumeration completed
Jul 05 11:02:13 imx6qxelk systemd-networkd[572]: eth0: IPv6 enabled for interface: Success
Jul 05 11:02:15 imx6qxelk systemd-networkd[572]: eth0: Gained carrier
Jul 05 11:02:16 imx6qxelk systemd-networkd[572]: eth0: Gained IPv6LL
Jul 05 11:02:29 imx6qxelk systemd-networkd[572]: eth0: Configured

For displaying the log related to a specific /dev device, just add it to the command line:

root@imx6qxelk:~# journalctl /dev/fb0
-- Logs begin at Wed 2019-06-26 13:22:41 UTC, end at Thu 2019-07-11 09:07:01 UTC. --
Jun 26 13:22:41 imx6qxelk kernel: mxc_sdc_fb fb@0: registered mxc display driver ldb
Jun 26 13:22:41 imx6qxelk kernel: mxc_sdc_fb fb@0: using reserved memory region at 0x8e000000, size 2 MiB
Jun 26 13:22:41 imx6qxelk kernel: mxc_sdc_fb fb@0: assigned reserved memory node splashscreen
Jun 26 13:22:41 imx6qxelk kernel: mxc_sdc_fb fb@0: using memory region 0x8e000000 0x8e1fffff

For displaying the log related to a user ID, use _UID= parameter

root@imx6qxelk:~# id messagebus
uid=995(messagebus) gid=993(messagebus) groups=993(messagebus)
root@imx6qxelk:~# journalctl _UID=993
-- Logs begin at Wed 2019-06-26 13:22:41 UTC, end at Thu 2019-07-11 09:14:01 UTC. --
Jul 10 14:42:48 imx6qxelk systemd-timesyncd[423]: Network configuration changed, trying to establish connection.
Jul 10 14:43:02 imx6qxelk systemd-timesyncd[423]: Network configuration changed, trying to establish connection.
Jul 11 07:38:31 imx6qxelk systemd-timesyncd[423]: Synchronized to time server 216.239.35.8:123 (time3.google.com).

Analyze the boot time[edit | edit source]

Boot time analysis is one of the most important and interesting activity for an embedded system: systemd provide an userspace command called systemd-analyze to help in this (hard) task

The systemd-analyze command list how many services are running on the system and how long they took for starting at the last boot.

systemd-analyze provides a good level of boot time information for further optimizations:

time[edit | edit source]

The time parameter gives the total amount of seconds used for starting the kernel and reaching the userspace.

root@imx6qxelk:~# systemd-analyze time 
Startup finished in 5.109s (kernel) + 4.771s (userspace) = 9.880s

blame[edit | edit source]

The blame parameter gives the list of started services and how long they took for starting:

root@imx6qxelk:~# systemd-analyze blame 
          3.608s dev-mmcblk0p2.device
           547ms systemd-remount-fs.service
           545ms systemd-vconsole-setup.service
           544ms kmod-static-nodes.service
           503ms systemd-udev-trigger.service
           426ms systemd-journal-flush.service
           407ms tmp.mount
           371ms systemd-logind.service
           327ms systemd-journald.service
           317ms systemd-networkd.service
           275ms systemd-timesyncd.service
           257ms systemd-sysctl.service
           204ms ofono.service
           203ms systemd-modules-load.service
           194ms sys-kernel-config.mount
           188ms sys-kernel-debug.mount
           177ms sshd.socket
           161ms psplash-start.service
           138ms systemd-random-seed.service
           138ms sys-fs-fuse-connections.mount
           129ms systemd-udevd.service
           129ms systemd-update-utmp.service
           128ms systemd-tmpfiles-setup-dev.service
           124ms rc-local.service
            98ms systemd-tmpfiles-setup.service
            91ms psplash-quit.service
            90ms systemd-resolved.service
            89ms systemd-backlight@backlight:backlight.service
            63ms dev-mmcblk0p1.device
            41ms var-volatile.mount
            33ms systemd-update-utmp-runlevel.service

critical-chain[edit | edit source]

The critical-chain parameter shows the startup process flow and the time consumed by each service.

Here below a picture showing an example of critical path:

Systemd-analyze-critical-chain.png

Services and targets[edit | edit source]

systemd manages not only services but many different objects called Unit. Unit are related to the resources that systemd can manage. Unit configurations are defined into the Unit files.

Units categoris (identified by the file extension) are:

   .service
   .target
   .socket
   .device
   .mount
   .automount
   .swap
   .path
   .timer
   .snapshot
   .slice
   .scope

Major interesting Units are services and targets. They will be analyzed in the following paragraphs.

Targets[edit | edit source]

Targets are used by systemd for having a synchronization mechanism between different services at boot time or during run-time changes.

They can be used for set the system to a new state.

All services linked to a target are linked to the modification to the same target. These can be seen in a similar way of SystemV runlevels with many other added functionalities.

Target and runlevels[edit | edit source]

Here below there is a list of power on/off targets and related SystemV runlevels:

Description SystemV (runlevel) systemd (target)
System halt 0 runlevel0.target, poweroff.target
Single user mode 1, s, single runlevel1.target, rescue.target
Multi user 2 runlevel2.target, multi-user.target
Multi user with network 3 runlevel3.target, multi-user.target
Experimental 4 runlevel4.target, multi-user.target
Multi user with network, graphical mode 5 runlevel5.target, graphical.target
Reboot 6 runlevel6.target, reboot.target

multi-user target can be identified as the runlevel 3.

Into the following directory:

/etc/systemd/system/<target_name>.target.wants

there is a list of services related to that target.

For example:

root@imx6qxelk:~# ls /etc/systemd/system/multi-user.target.wants/
atd.service	       busybox-syslog.service  gpuconfig.service  ofono.service		systemd-networkd.service
avahi-daemon.service   connman.service	       mytest.service	  psplash-quit.service	systemd-resolved.service
busybox-klogd.service  crond.service	       ntpdate.service	  remote-fs.target

Active targets[edit | edit source]

It is possible to display all active targets with:

systemctl -t target

Changing a target

systemctl isolate graphical

The actual target is shown with:

systemctl get-default

Changing the default target:

systemctl set-default multi-user

Unit files[edit | edit source]

For a complete information on Unit please look to the documentation page

Here below you can find an extract for the main used topics and configuration descriptions.

Location Path[edit | edit source]

Units are configured by systemd using configuration files that can be found in different directories. Each of them has different priority and behaviour:

Path Description
/lib/systemd/system This directory stores a copy of configuration files: this is the default destination for new installed configuration file. Typically files in this directory should not be modified by the user.
/etc/systemd/system This is the directory where to store a new Unit or to modify an existing one. The files present in this directory have the highest priority.
/run/systemd/system The files present in this directory have higher priority only respect the ones on /lib/systemd/system.

Systemd creates these configuration files dinamically at runtime; modification on this directory can be used for testing a runtime behaviour for a Unit but all modifications will be lost at next boot.

[Unit] section options[edit | edit source]

This section is used for defining the metadata and relations between different Unit

Please find below the main properties description:

Property Function
Description=: Name and function
Documentation=: URI for the documentationvv
Requires=: List of Units dependencies. For successfully executing this Unit, all listed dependency should be activated without errors, otherwise this Unit return fail.
Wants=: Similar to a Requires but weaker. If the Unit listed are not found or return fail, this Unit are executed anyway. this is the recommended method to be used.
BindsTo=: Similar to Requires but it does a Stop for the Unit when the listed Unit are terminated.
Before=: The Unit listed will not be executed until this Unit will not change to started. This is used for an order of Units executions.
After=: The Unit listed will be started before this Unit. This is used for an order of Units executions.
Conflicts=: The Unit listed cannot be executed simultaneously to this Unit.

[Install] section options[edit | edit source]

This section is optional but is commonly used for defining a Unit behaviour when it will be executed during enable or disable commands.

Property Function
WantedBy=: This is similar to the Wants= on [Unit] section but allows to mantain the top Unit more clean.

When the Unit will be enabled, a directory on /etc/systemd/system will be created with the Unit name adding .wants to the name. Inside this directoty a symbolic link to the Unit is created.

Example:

  • current Unit has WantedBy=multi-user.target
  • a directory /etc/systemd/system/multi-user.target.wants will be created
  • the symbolic link to the Unit will be created inside the new directory
  • disabling the Unit the symbolic link is deleted and the relation is then removed.
RequiredBy=: This is similar to WantedBy= but a dependency cause a fail if not satisfied. When the Unit is enabled, a directory with added .requires will be created
Also=: When the Unit is enabled, also the listed Units are enabled too.

Specific sections[edit | edit source]

Some Unit have specific sections based on their characteristic. The most important is the section Service related to the Unit .service

Please find more information at the documentation page

[Service] section[edit | edit source]

Used for providing configurations for the services.

Type[edit | edit source]

Type= uses one of the (main) following values:

Value Description
simple Default configuration for a service when specified ExecStarts=
forking the process will call a fork() when starts causing the father to exit. This informs systemd that the process is still alive even if the father has been terminated.
oneshot: the process has a very short execution time and then systemd should wait for its termination before continuing with other Units. this is the default configuration if ExecStarts= is not specified.
dbus the Unit will acquire the name on the D-Bus. systemd will continue to process the other Units
notify the service will notify when completely initialized. systemd will wait for the notification before continuing with the following Units
idle the service will not be executed until all active jobs are dispatched.
Other options[edit | edit source]
Value Description
ExecStarts=: Specifiy the full path and parameters for executing a service. If preceded by a "-" this inform that the command failure can be accepted.
ExecStartsPre=: used for adding more commands to be executed before starting the main process. May be used multiple times specifying the complete path and command parameters.
ExecReload=: commands to be executed for reloading the service configuration.
ExecStop=: commands required for stopping the service. If missing, the service will be killed.
ExecStopPost=: commands to be executed after the service has been stopped..
RestartSec=: time to sleep (seconds) before restarting the service.
Restart=: restart conditions for systemd to be checked before restarting the service (if terminated). Can be set to "always","on-success", "on-failure", "on-abnormal", "on-abort", or "on-watchdog".
TimeoutSec=: time to sleep during start or stop before considering the process failed on start or stop. Start and stop timeout can be set with different values using TimeoutStartSec= and TimeoutStopSec=

Putting it all together: create a new service[edit | edit source]

For creating a new service the following file has to be created:

/etc/systemd/system/<service_name>.service

Service example[edit | edit source]

The following paragraph shows how to create a new service called iperf3 executing the iperf3 command in server mode

/etc/systemd/system/iperf3.service
[Unit]
Description=iperf3 server mode
After=network.target
StartLimitIntervalSec=0

[Service]
Type=simple
Restart=0
RestartSec=1
User=root
ExecStart=/usr/bin/iperf3 -s

[Install]
WantedBy=multi-user.target

Basic settings[edit | edit source]

Parameter Description
After The executed command (iperf3) requires the network interface to be already active, so we use After for this purpose.
Restart This is configured with 0 for disabling the service after it has been run.
RestartSec time sleep before restarting the service; default value is 100ms.
User configures the user or group used for executing the service.
ExecStart command to be executed when the service will be started (in our case iperf3).
WantedBy defines which target is used related to the service started.

Running a service[edit | edit source]

Starting the service from userspace:

systemctl start iperf3

Starting the service at boot time:

systemctl enable iperf3