拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

yocto: 13-systemd Service

yocto: 13-systemd Service

第3课:自己写 systemd Service —— 掌握开机服务

摘要:本教程详细介绍了如何在 Raspberry Pi 上创建自定义 systemd 服务,实现开机自动运行程序。内容包括:systemd 基本概念、service 文件结构解析、Yocto 集成方法、recipe 编写要点,以及完整的构建、部署和验证流程。通过 hello.service 示例,展示了从编写服务文件到系统集成的完整实践过程。

自己写一个 service,让 Raspberry Pi 开机自动运行自己的程序。
学习完成后,你就会理解:

  • 什么是 systemd

  • 什么是 service

  • service 文件长什么样

  • Yocto 如何安装 service

  • Yocto 如何自动 enable service

最终效果:

Pi 开机 ↓ systemd ↓ 启动 hello.service ↓ 执行 /usr/bin/hello

这就是现代 Linux 的标准启动方式。
所以要做两件事:

1.增加systemd serice 服务2.增加hello-systemd 服务

一、什么是 systemd
以前 Linux 使用init
后来使用SysV init
现在几乎所有 Linux 都使用systemd
可以理解成:systemd 所有程序几乎都是它启动。
例如

- network -ssh- dbus - bluetooth - nginx -docker- 自己的程序

全部都是 systemd 管理。


二、什么是 service
例如:
SSH 服务: sshd.service
网络: NetworkManager.service
时间同步: systemd-timesyncd.service

我们也可以写:hello.service

开机执行:/usr/bin/hello


三、service 文件在哪里
一般放:/lib/systemd/system/
或者: /usr/lib/systemd/system/

Yocto 使用变量:${systemd_system_unitdir}

例如:${systemd_system_unitdir}/hello.service


四、service 文件格式
建立 hello.service
内容:

[Unit]Description=Hello Demo ServiceAfter=network.target[Service]Type=simpleExecStart=/usr/bin/helloRestart=always[Install]WantedBy=multi-user.target

这是最经典的 service。


五、逐行解释
[Unit]

Description=Hello Demo Service # 描述这个服务。


After=

After=network.target # 网络启动完成以后, 再启动 hello 不是依赖,只是启动顺序。


[Service]

真正运行程序。


Type=simple
最常见。

simple意思:ExecStart 启动以后, 程序一直运行


ExecStart
真正执行:

ExecStart=/usr/bin/hello # systemd 会执行/usr/bin/hello


Restart
Restart=always

程序退出:重新启动, 非常适合 daemon。


[Install]
WantedBy=multi-user.target
意思:进入正常多用户模式时启动。

可以理解成:开机以后自动启动


六、把 service 放进 recipe
目录:

hello-systemd/ ├── hello-systemd.bb ├── hello └── hello.service

hello.service
[Unit]
Description=Hello Demo Service
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/hello
Restart=always

[Install]

WantedBy=multi-user.target


hello(脚本)

#!/bin/shwhiletruedoecho"Hello Systemd"sleep5done

七、Recipe – hello-systemd.bb

SUMMARY="Hello systemd demo"LICENSE="MIT"LIC_FILES_CHKSUM="file://LICENSE;md5=f4fa7fd56aac72279ad21a112915ca87"inherit systemd SRC_URI="\ file://hello \ file://hello.service \ file://LICENSE"S="${WORKDIR}"do_install(){install-d${D}${bindir}install-m0755${WORKDIR}/hello${D}${bindir}/helloinstall-d${D}${systemd_system_unitdir}install-m0644${WORKDIR}/hello.service\${D}${systemd_system_unitdir}/hello.service}SYSTEMD_SERVICE:${PN}="hello.service"SYSTEMD_AUTO_ENABLE="enable"FILES:${PN}+="\${bindir}/hello \${systemd_system_unitdir}/hello.service \ "

八、重点解释 Recipe
inherit systemd

告诉 BitBake:我要安装 systemd service。 它会引入处理 systemd 服务所需的类和打包逻辑。


SYSTEMD_SERVICE:${PN}
告诉 Yocto:这个 package 的 service 是hello.service

如果一个包有多个服务,也可以写:SYSTEMD_SERVICE:${PN} = “hello.service
monitor.service”


SYSTEMD_AUTO_ENABLE = “enable”
构建镜像时:systemctl enable hello.service
会自动完成(实际上是在 rootfs 中创建相应的符号链接),因此系统首次启动时服务就是启用状态。
如果改成:SYSTEMD_AUTO_ENABLE = “disable”

则安装了 service 文件,但不会自动启用。


九、添加systemd usrmerge 特性(推荐)
在 local.conf 中同时添加 usrmerge:vi ~/yocto/build-rpi2/conf/local.conf
bash
修改为:

bitbake# ============================================# 切换到 systemd 作为 init 管理器# ============================================DISTRO_FEATURES:append=" systemd usrmerge"VIRTUAL-RUNTIME_init_manager="systemd"VIRTUAL-RUNTIME_initscripts="systemd-compat-units"DISTRO_FEATURES_BACKFILL_CONSIDERED="sysvinit"VIRTUAL-RUNTIME_syslog="systemd-journald"bitbake core-image-minimal-ccleansstate# seemd clean tmp, so need long time to rebuildbitbake core-image-minimal

十,构建并加入镜像
编译:bitbake hello-systemd
加入镜像:IMAGE_INSTALL:append = " hello-systemd"
位置1:core-image-minimal.bbappend(最佳实践 ✅)
IMAGE_INSTALL:append = " network-config hello-script mypackage mypackage-config hello-systemd"
位置2:local.conf(快速测试)
位置3:自定义 Image Recipe(最灵活)

重新生成镜像:

bitbake core-image-minimal

写入 SD 卡并启动 Raspberry Pi。


十一、验证服务
查看是否已启用:systemctl is-enabled hello.service
期望输出:enabled
查看状态:systemctl status hello.service
可能看到:

● hello.service Loaded: loaded Active: active(running)

查看日志:

journalctl-uhello.service

如果脚本每 5 秒输出一次 Hello Systemd,日志中就会看到相应内容。

May2918:48:29 raspberrypi2 systemd[1]: Started Hello Demo Service. May2918:48:29 raspberrypi2 hello[219]: Hello Systemd ├── hello-systemd │ ├── files │ │ ├── hello │ │ ├── hello.service │ │ └── LICENSE │ └── hello-systemd.bb

十二、常见问题


本课实验(推荐)
为了真正掌握 systemd,建议按下面顺序完成三个小实验:
1.基础服务:编写 hello.service,每 5 秒打印一条日志,确认开机自动启动。

2.故障恢复:将脚本改为运行 10 秒后退出,观察 Restart=always 是否自动拉起服务。

3.启动顺序:修改 After=(如 network.target),结合 systemctl list-dependencies 和日志观察服务启动顺序。

完成这三步后,你不仅会知道如何在 Yocto 中安装和启用一个 systemd 服务,还会理解 Linux 开机服务管理的基本工作方式。这也是后续开发网络服务、守护进程(daemon)和后台应用的基础。

返回列表