Changes

Jump to: navigation, search

XELK-AN-008: How to use systemd on an Embedded system

1,194 bytes added, 13:19, 24 September 2019
no edit summary
Major insteresting Units are '''services''' and '''targets'''. They will be analyzed in the following paragraphs.
== Services 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. In the following paragraphs, there are the related commands used for these tasks.  === Manage services ===
<code>systemctl</code> is the main command utility and primary tool fo managing the systemd daemons/services such as ''start, restart, stop, enable, disable, reload & status''.
systemctl -t service --all
==== service commands ====
Starting a service from userspace:
systemctl disable ''<service_name>''
==== mask a service ====
There is a third level for stopping a service other than ''stop'' and ''disable'': it is the command <code>mask</code>.
Removed /etc/systemd/system/emergency.service.
</pre>
 
=== Configuring the network interfaces===
 
One of the most systemd configuration used is the '''Network configuration'''.
 
==== wired interface ====
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
 
<pre>
[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
 
</pre>
 
'''Note:'''
 
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>
 
==== wireless interface ====
 
===== wpa_supplicant =====
wpa_supplicant provides different services on systemd:
 
* <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>
 
For enabling the interface at boot time it is required to ''enable'' the service
 
systemctl enable wpa_supplicant@interface
 
===== wlan configuration example =====
 
Assuming ''wlan0'' as the wireless interface name, the configuration file examples are the following one:
 
/etc/systemd/network/wlan0.network
 
<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
 
</pre>
 
/etc/wpa_supplicant/wpa_supplicant-wlan0.conf
 
<pre>
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
}
</pre>
 
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 <code>wpa_supplicant-wlan0.conf</code>:
 
systemctl enable wpa_supplicant@wlan0
 
=== Logging with systemd ===
 
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>.
 
journalctl -f
 
for displaying the new log messages (similar to <code>tail -f /var/log/messages</code>)
 
journalctl -p
 
with '''-p''' parameter is it possible to set the log ''severity'' :
 
{| class="wikitable"
|-
! Value !! Severity !! Keyword
|-
| 0 || Emergency || emerg
|-
| 1 || Alert || alert
|-
| 2|| Critical || crit
|-
| 3|| Error || err
|-
| 4|| Warning || warning
|-
| 5|| Notice || notice
|-
| 6|| Information || info
|-
| 7|| Debug || debug
|}
 
journalctl --since ''<time>''
 
with different keywords like:
 
<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>
 
journalctl -u ''<unit_name>''
 
for displaying the log related to a specific ''Unit'':
 
<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>
 
journalctl /dev/''<node_name>''
 
for displaying the log related to a specific <code>/dev</code> device:
 
<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>
 
journalctl _UID=''<uid>''
 
for displaying the log related to a user_id:
 
<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>
 
=== Analyze the boot time===
 
Boot time analysis is one of the most important and interesting activity for an emebedded system. systemd provide an userspace command called <code>systemd-analyze</code>.
 
The systemd-analyze command list how many services are running on the system and how long they took for starting at the last boot.
 
<code>systemd-analyze</code> provides a good level of boot time information for further optimizations:
 
==== time ====
 
The <code>time</code> parameter gives the total amount of seconds used for starting the kernel and reaching the userspace.
 
<pre>
root@imx6qxelk:~# systemd-analyze time
Startup finished in 5.109s (kernel) + 4.771s (userspace) = 9.880s
</pre>
 
==== blame ====
The <code>blame</code> parameter gives the list of started services and how long they took for starting:
 
<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>
 
==== critical-chain ====
Here below a picture showing an example of critical path where the most time consuming task are displayed in red:
 
[[File:Systemd-analyze-critical-chain.png|800px]]
 
== Targets ==
ExecStop=/usr/bin/myservice shutdown
</pre>
 
== systemd-analyze ==
<code>systemd-analyze</code> provides a good level of boot time information for further optimizations:
 
=== time ===
<pre>
root@imx6qxelk:~# systemd-analyze time
Startup finished in 5.109s (kernel) + 4.771s (userspace) = 9.880s
</pre>
 
=== blame ===
<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>
 
=== critical-chain ===
[[File:Systemd-analyze-critical-chain.png|800px]]
 
== Logging with systemd ==
 
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>.
 
journalctl -f
 
for displaying the new log messages (similar to <code>tail -f /var/log/messages</code>)
 
journalctl -p
 
with '''-p''' parameter is it possible to set the log ''severity'' :
 
{| class="wikitable"
|-
! Value !! Severity !! Keyword
|-
| 0 || Emergency || emerg
|-
| 1 || Alert || alert
|-
| 2|| Critical || crit
|-
| 3|| Error || err
|-
| 4|| Warning || warning
|-
| 5|| Notice || notice
|-
| 6|| Information || info
|-
| 7|| Debug || debug
|}
 
journalctl --since ''<time>''
 
with different keywords like:
 
<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>
 
 
journalctl -u ''<unit_name>''
 
for displaying the log related to a specific ''Unit'':
 
<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>
 
journalctl /dev/''<node_name>''
 
for displaying the log related to a specific <code>/dev</code> device:
 
<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>
 
journalctl _UID=''<uid>''
 
for displaying the log related to a user_id:
 
<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>
 
== How to configure network ==
 
One of the most systemd configuration used is the '''Network configuration'''.
 
=== wired interface ===
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
 
<pre>
[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
 
</pre>
 
'''Note:'''
 
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>
 
=== wireless interface ===
 
==== wpa_supplicant ====
wpa_supplicant provides different services on systemd:
 
* <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>
 
For enabling the interface at boot time it is required to ''enable'' the service
 
systemctl enable wpa_supplicant@interface
 
==== Configuration example ====
 
Assuming ''wlan0'' as the wireless interface name, the configuration file examples are the following one:
 
/etc/systemd/network/wlan0.network
 
<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
 
</pre>
 
/etc/wpa_supplicant/wpa_supplicant-wlan0.conf
 
<pre>
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
}
</pre>
 
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 <code>wpa_supplicant-wlan0.conf</code>:
 
systemctl enable wpa_supplicant@wlan0
8,154
edits

Navigation menu