Changes

Jump to: navigation, search

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

994 bytes added, 16:06, 9 November 2020
no edit summary
{{AppliesToAxelEsatta}}
{{AppliesToAxelLite}}
{{AppliesToAXEL Lite AN}}
{{AppliesToSMARX AN}}
{{AppliesToSBCX}}
{{AppliesToSBC Axel AN}}
{{InfoBoxBottom}}
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]].
{{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 example examples - that can be found here below - may simplify the systemd approach for beginners. == Brief description ==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 insteresting Units are '''services''' and '''targets'''. They will be analyzed in the following paragraphs.}}
== Architecture ==
== 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.
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 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:
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 =====
 
The <code>stop()</code> function in the script will become <code>ExecStop=</code>:
 
SystemV:
 
<pre>
stop() {
echo "Stopping My Custom Service..."
/usr/bin/myservice shutdown
}
</pre>
 
systemd:
 
<pre>
[Service]
ExecStop=/usr/bin/myservice shutdown
</pre>
One of the most systemd configuration used is the '''Network configuration'''.
==== wired Wired interface ====
systemd uses a slightly different configuration mechanism than SystemV. The configuration file is the following one with an example of configuration:
</pre>
==== wireless Wireless interface ====
===== wpa_supplicant =====
* <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
systemctl enable wpa_supplicant@wlan0
=== Logging with systemd =(<code>journalctl</code>) ==
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>.
<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] For example, to display the new log messages (similar to <code>tail -f /var/log/messages</code>) add the <code>-f</code> option
for displaying the new log messages (similar to With <code>tail -f /var/log/messagesp</code>)it's possible to set the log ''priority''
journalctl -pLEVEL
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 '''-p''' parameter is it possible to set the log ''severity'' :that priority or higher
{| 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 likeUser 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.:
<pre>
</pre>
journalctl -u ''<unit_name>'' for For displaying the log related to a specific ''Unit'', use the <code>-u</code> option, e.g.:
<pre>
</pre>
journalctl /dev/''<node_name>'' for For displaying the log related to a specific <code>/dev</code> device, just add it to the command line:
<pre>
</pre>
journalctl _UID=''<uid>'' for For displaying the log related to a user_id:user ID, use <code>_UID=</code> parameter
<pre>
</pre>
=== Analyze the boot time===
Boot time analysis is one of the most important and interesting activity for an emebedded embedded system. : systemd provide an userspace command called <code>systemd-analyze</code>.to help in this (hard) task
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.
<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>
==== blame ====
The <code>blame</code> parameter gives the list of started services and how long they took for starting:
</pre>
==== critical-chain ====The <code>critical-chain</code> parameter shows the startup process flow and the time consumed by each service. 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]]
== 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''.
 
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 ===
Targets are used by systemd for having a synchronization mechanism between different services at boot time or during runtime 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 ====
Here below there is a list of power on/off targets and related SystemV runlevels:
<code>multi-user</code> target can be identified as the <code>runlevel 3</code>.
On Into the following directory:
/etc/systemd/system/''<target_name>''.target.wants
directory there is a list of services related to that target.
For example:
</pre>
==== Active targets ====
It is possible to display all active targets with:
systemctl set-default multi-user
=== Unit files ===
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.
==== Location Path ====
Units are configured by ''systemd'' using configuration files that can be found in different directories. Each of them has different priority and behaviour:
{| 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.|}
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 <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. ==== [Unit] section options ====
This section is used for defining the metadata and relations between different ''Unit''
|}
==== [Install] section options ====
This section is optional but is commonly used for defining a ''Unit'' behaviour when it will be executed during ''enable'' or ''disable'' commands.
|}
==== Specific sections ====
Some ''Unit'' have specific sections based on their characteristic. The most important is the section '''Service''' related to the Unit <code>.service</code>
Please find more information at the [https://www.freedesktop.org/software/systemd/man/systemd.service.html# documentation page]
===== [Service] section =====
Used for providing configurations for the ''services''.
====== Type ======
<code>Type=</code> uses one of the (main) following values:
! 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.
|}
====== Other options ======
{| class="wikitable"
|}
=== Creating Putting it all together: create a new service ===
For creating a new service the following file has to be created:
/etc/systemd/system/''<service_name>''.service
==== Service example ====
The following paragraph shows how to create a new service called '''myservice''' <code>iperf3</code> executing a the iperf3 command (in our case ''iperf3''):server mode
/etc/systemd/system/myserviceiperf3.service
<pre>
[Unit]
Description=My Serviceiperf3 server mode
After=network.target
StartLimitIntervalSec=0
</pre>
===== Basic settings =====
After {| class="wikitable"|-! Parameter !! Description|-| 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. |}
===== running Running a service =====
Starting the service from userspace:
systemctl start myserviceiperf3
Starting the service at boot time:
systemctl enable myservice === 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 ==== The <code>stop()</code> function in the script will become <code>ExecStop=</code>: SystemV: <pre>stop() { echo "Stopping My Custom Service..." /usr/bin/myservice shutdown}</pre> systemd: <pre>[Service]ExecStop=/usr/bin/myservice shutdown</pre>iperf3
8,154
edits

Navigation menu