Systemd自启动服务应用案例


systemd 是一种用于 Linux 操作系统的初始化系统和服务管理器,负责启动和管理系统中的各种服务和进程,由 Lennart Poettering 主导开发并在 LGPL 2.1 及其后续版本许可证下开源发布。systemd 已经广泛被多数主流 Linux 发行版采用,如 Ubuntu、Fedora、Debian。展厅上的i.MX6/8/9系列采用Linux定制版,即Yocto系统,它也采用了systemd管理器。

systemctl命令是systemd系统和服务管理器的命令行工具,通过控制和监视系统的服务和单位文件,提供了对系统进程的强大管理功能。

在开发板上做调试时,有时我们会想把一些命令或脚本文件设置为开机自启动。尤其是在多次开机后运行同一命令观察其结果,设置为开机自启动能提高调试效率。我们可以利用systemd设置命令或脚本文件的开机自启动。

本文档涉及案例包括:

•        利用Systemd设置程序开机自启动

1.     预定开发板在动手实践本应用案例前先预定开发板:(以i.MX8MP为例,i.MX93等同样适用)

2.     如前面所述,systemctl命令是systemd系统和服务管理器的命令行工具。当 Linux 系统启动时,内核会加载并执行第一个用户空间程序,即 systemd。它作为 PID 1 运行,是所有其他进程的父进程。Systemd会读取配置文件,通常配置文件位于/etc/systemd/system下和/lib/systemd/system下,后缀为.service, 按照依赖顺序并行或顺序地启动服务。

systemctl命令的基本语法为:

systemctl [OPTIONS...] COMMAND [UNIT]

其中,OPTIONS是可选参数,用于指定systemctl的行为;COMMAND是必需参数,用于执行特定的systemd命令,如启动、停止或重新启动服务;UNIT是可选参数,用于指定要操作的服务或单元。

例如:

启动服务:

systemctl start 服务名称.service

停止服务:

systemctl stop 服务名称.service

重启服务:

systemctl restart 服务名称.service

查看服务状态:

systemctl satus 服务名称.service

设置服务开机自启动:

systemctl enable服务名称.service

取消服务开机自启动:

systemctl disable服务名称.service

查看所有已启用的服务:

systemctl list-unit-files --state=enabled

重新加载服务配置文件:

当修改了服务的配置文件后,需要执行此命令来重新加载配置文件。

systemctl daemon-reload

1.     systemd 设计的单元(Units)是用于描述系统资源和服务的配置文件,它们代表了systemd可以管理的各种不同类型的对象。systemd支持的主要单元类型有:

(1)    服务单元 (.service):这是最常用的单元类型,用于定义系统服务,如守护进程(daemon)及其相关进程。服务单元控制着服务的启动、停止、重载等操作。

(2)    套接字单元 (.socket):用于管理系统中的本地IPC(进程间通信)或网络套接字,支持基于套接字激活服务,即当套接字上有连接请求时自动启动相应服务。

(3)    目标单元 (.target):作为一组单元的集合,用于定义系统状态或运行级别,如多用户目标(multi-user.target)或图形界面目标(graphical.target)。切换目标实际上就是启动或停止与该目标相关联的一组服务。

(4)    设备单元 (.device):代表系统中的硬件设备,可以用于基于设备的激活,即当设备接入或移除时执行特定操作。

除此之外,还有挂载单元 (.mount),路径单元 (.path),计时器单元 (.timer),交换单元 (.swap),自动挂载点单元 (.automount)等。

服务单元 (.service)是最常用的单元类型。以/lib/systemd/system下的psplash-start.service为例,该服务单元会让屏幕在Weston启动之前显示一张open-embedded 图片,

vi /lib/systemd/system/psplash-start.service

[Unit]

Description=Start Psplash Boot Screen

Wants=systemd-vconsole-setup.service

After=systemd-vconsole-setup.service systemd-udev-trigger.service systemd-udevd.service

DefaultDependencies=no


[Service]

ExecStartPre=/bin/sh -c "if [ -e /sys/class/graphics/fbcon/cursor_blink ]; then echo 0 > /sys/class/graphics/fbcon/cursor_blink; fi"

ExecStart=/bin/sh -c "s=$(/usr/sbin/fbset -i -fb /dev/fb0 | grep epdc); if [ -z "$s" ]; then i=0; else i=1; fi; if [ -e /dev/fb$i ]; then /usr/bin/psplash -n

[Install]

WantedBy=sysinit.target

.service文件分为三个部分:

(1)    [Unit] 部分,描述了单元的元数据和依赖关系。

1)       Description:对当前服务的描述。

2)       After 和 Before:定义服务的启动顺序,表示当前服务应该在哪些服务之后或之前启动。这两个字段只涉及启动顺序,不涉及依赖关系。

3)       Wants:表示当前服务与另一个服务之间存在弱依赖关系。如果另一个服务启动失败或停止运行,不影响当前服务继续执行。

4)       Requires:表示当前服务与另一个服务之间存在强依赖关系。如果另一个服务启动失败或异常退出,当前服务也必须退出。

5)       Conflicts:定义与当前服务冲突的服务。如果冲突的服务已经启动,那么当前服务就不能启动。

(2)    [Service]部分:定义了服务的具体行为。

1)       ExecStart:定义服务启动时要执行的命令。可以是单个命令、脚本文件、或者多个命令组成的脚本。

2)       ExecStop:定义服务停止时要执行的命令。

3)       ExecStartPre 和 ExecStopPost:定义服务启动前和停止后要执行的命令。

4)       WorkingDirectory:指定服务的工作目录。

5)       User 和 Group:指定服务运行的用户和组。

6)       Restart 和 RestartSec:定义服务的重启策略,如是否自动重启、重启间隔等。

(3)    [Install]部分:定义了如何将服务安装到系统中。

1)       WantedBy 和 RequiredBy:定义哪些服务或目标需要或要求当前服务。

2)       Alias:为服务定义别名。

2.     以8MPLUSLPD4-PEVK-3开发板为例,CPU频率默认的策略是ondemand的(平时低速运行,当系统负载提高时按需自动提高频率),我们想设置开机自启动让CPU频率策略为powersave, 即以最低的频率运行。

先查看默认的CPU频率:

cat  /sys/kernel/debug/clk/clk_summary|grep arm

                   

能看到大部分时候CPU频率是1.8GHz(最高),偶尔也运行在1.6GHz。如果手动运行以下命令,CPU频率策略为powersave, 即以最低的频率运行:

cpufreq-set -g powersave

 

可以看到CPU的频率已经变为1.2GHz,为最低频率。

我们现在通过在systemd中新添加一个my service服务,设置CPU频率策略为powersave命令为开机自启动。

首先在/home/root下,创建一个名为cpufreq.sh的脚本文件,并将脚本权限设置为为最高777:

#!/bin/bash

cpufreq-set -g powersave

cpufreq-info

在/etc/systemd/system路径下,创建一个名为myservice.service的文件,内容如下:

[Unit]

Description=My service

After=weston.service

[Service]

ExecStart=/home/root/cpufreq.sh

User=root

[Install]

WantedBy=multi-user.target

ExecStart表示该服务启动时要执行脚本/home/root/cpufreq.sh。

依次运行以下命令:

systemctl daemon-reload

systemctl enable myservice.service

systemctl start myservice.service

 

 

之后点击PowerReset-EVK重启开发板,在临近文件系统login时,可以看到My service在Weston service启动后 自启动。查看CPU频率,看到CPU频率已经被设置为最低1.2GHz,证明通过systemd设置程序自启动已经生效。

 

需要注意的是,当运行

systemctl status myservice

时,会看到myservice的状态是inactive (dead)的,表示该服务已经停止。

 

这是因为ExecStart 调用的cpufreq.sh 里的命令只是一句命令,不是服务程序也没有设置循环,在开机运行完后就结束了。如果我们修改cpufreq.sh为:

#!/bin/bash

while true;do

cpufreq-set -g powersave

cpufreq-info

done

并依次运行以下命令:

systemctl daemon-reload

systemctl enable myservice.service

systemctl restart myservice.service

后,再运行

systemctl status myservice

去查看,会看到myservice的状态由inactive (dead)变为active。开发板重启,也依旧看看到此状态。

 

若想取消myservice的自启动,则运行

systemctl disable myservice.service

然后重启,可以看到启动log中“[  OK  ] Started My service.”的log消失,查看其状态是disabled和inactive的。