Linux:认识Systemd服务(一)
一、什么是Systemd?
(1)systemd是一个系统和服务管理器,systemd是Linux系统中一套基本的构建模块,提供了一系列工具的集合,用于管理后台服务、状态查询、日志归档、设备管理、电源管理和定时任务等许多职责。
(2)systemd作为PID为1的进程,是系统中所有其他进程的父进程。(通过ls -l 可以看到/sbin/init是一个指向/lib/systemd/systemd的软链接)

(3)systemctl是一个命令行工具,用于与systemd进行交互。通过systemctl,用户可以启动、停止、重启、查看状态以及管理系统中的服务单元
(4)systemd作为后台服务运行,而systemctl则提供了用户与systemd交互的接口。用户通过systemctl发送指令,systemd执行相应的操作。systemctl的命令实际上是向systemd发送请求,告诉systemd要做什么。
二、单元文件
1、单元文件类型
systemd通过单元文件(Unit files)来描述和管理不同的系统资源和服务。Systemd 支持的 12 种 Unit 文件类型。其中最常用到的就是Service单元文件。
# 查看所有Unit类型
$ systemctl -t help# 常见Unit类型
Type 作用 示例
service 服务单元 nginx.service
socket 套接字单元 sshd.socket
target 目标单元 multi-user.target
mount 挂载单元 home.mount
device 设备单元 dev-sda.device
timer 定时器单元 backup.timer
path 文件路径监控单元 updatedb.path
2、单元依赖关系和顺序
systemd 有两种类型的依赖关系:要求依赖关系和顺序依赖关系。要求依赖关系指定在激活某个单元时必须启动或停止其他哪些单元。顺序依赖关系指定必须遵循的单元启动顺序。
单元依赖关系
单元文件具有依赖关系特性。某个单元可能需要在一个或多个其他单元运行之后才能运行。这些依赖关系是在单元文件中使用指令 Wants 和 Requires 设置的。
Wants
例如,如果单元 A 设置了 Wants=unit B,则当单元 A 运行时,单元 B 也会运行。但单元 B 能否成功启动不会影响单元 A 的成功运行。
Requires
如果单元 A 设置了 Requires=unit B,则这两个单元都会运行;但如果单元 B 未成功运行,则会停用单元 A。单元 A 的进程是否成功运行并不重要。
单元顺序
如果没有正确的指令,systemd 可以同时运行一组单元。以正确的顺序启动服务对于 Linux 系统的正常运行非常重要。可以使用单元文件指令 Before 和 After 来排列顺序。
Before
例如,如果单元 A 设置了 Before=unit B,当这两个单元同时运行时,会先完全执行单元 A,然后再执行单元 B。
After
如果单元 A 设置了 After=unit B,当这两个单元同时运行时,会先完全执行单元 B,然后再执行单元 A。
三、systemd目标
systemd 使用单元和目标。systemd 单元定义系统上的服务或操作,由名称、类型和配置文件组成。systemd 目标由多个单元组合而成,定义必须启动哪些服务才能达到目标。例如,在服务器上,这是网络正在运行并且多个用户可以登录的状态。这些文件由后缀 .target 标识。
与单元文件类似,可以通过依赖关系嵌套不同的目标。例如,multi-user.target 需要通过目标(及其他单元)来设置登录和用户会话服务。
常见 systemd 目标:
default.target
默认会引导。default.target 文件是指向实际目标文件(例如桌面工作站的 graphical.target)的符号链接。对于服务器,它通常是 graphical.target。poweroff.target
关闭系统并关闭电源。rescue.target
拉取基础系统并启动救援外壳会话的目标单元。multi-user.target
设置非图形(控制台)多用户系统。graphical.target
使用包含网络服务的图形多用户系统。reboot.target
关闭再重引导系统。
四、日志记录
日志文件和日记对于系统管理非常重要。它们提供有关系统的深入信息,对于查错和审计非常重要。日志文件包含内核、应用程序和登录到系统的用户所生成的事件和消息。您可以使用 journalctl 命令来查询日记。此命令可用于查看 systemd 收集的日志。systemd-journald 服务处理 systemd 的日志收集。systemd-journald 以二进制格式保存事件和消息。
# 查看完整的系统日志
qing222@qing222-virtual-machine:~/Desktop$ journalctl
Journal file /var/log/journal/3865d7ce7eb84a1d8b0b0a0dfd3dee72/system@0006118e94da3dc5-fc2783304b4edadc.journal~ is truncated, ignoring file.
2月 01 18:42:34 qing222-virtual-machine systemd-journald[337]: Time spent on flushing to /var/log/journal/3865d7ce7eb84a1d8b0b0a0dfd3dee72 is 179.370ms for 1836 entries.
2月 01 18:42:34 qing222-virtual-machine systemd-journald[337]: System Journal (/var/log/journal/3865d7ce7eb84a1d8b0b0a0dfd3dee72) is 200.0M, max 4.0G, 3.8G free.
2月 01 18:42:34 qing222-virtual-machine systemd[1]: Finished Apply Kernel Variables.
2月 01 18:42:34 qing222-virtual-machine systemd[1]: Finished Coldplug All udev Devices.
2月 01 18:42:34 qing222-virtual-machine systemd[1]: Started Rule-based Manager for Device Events and Files.
2月 01 18:42:34 qing222-virtual-machine systemd[1]: Starting Show Plymouth Boot Screen...
2月 01 18:42:34 qing222-virtual-machine systemd[1]: Received SIGRTMIN+20 from PID 418 (plymouthd).
2月 01 18:42:34 qing222-virtual-machine systemd[1]: Started Show Plymouth Boot Screen.
2月 01 18:42:34 qing222-virtual-machine systemd[1]: Condition check resulted in Dispatch Password Requests to Console Directory Watch being skipped.
2月 01 18:42:34 qing222-virtual-machine systemd[1]: Started Forward Password Requests to Plymouth Directory Watch.
2月 01 18:42:34 qing222-virtual-machine systemd[1]: Reached target Local Encrypted Volumes.
2月 01 18:42:34 qing222-virtual-machine systemd[1]: Finished Flush Journal to Persistent Storage.
2月 01 18:42:35 qing222-virtual-machine systemd-udevd[413]: Using default interface naming scheme 'v249'.
2月 01 18:42:35 qing222-virtual-machine kernel: vmw_vmci 0000:00:07.7: Using capabilities 0x1c
2月 01 18:42:35 qing222-virtual-machine mtp-probe[520]: checking bus 2, device 2: "/sys/devices/pci0000:00/0000:00:11.0/0000:02:00.0/usb2/2-1"
2月 01 18:42:35 qing222-virtual-machine mtp-probe[520]: bus: 2, device: 2 was not an MTP device
2月 01 18:42:35 qing222-virtual-machine kernel: Guest personality initialized and is active
2月 01 18:42:35 qing222-virtual-machine kernel: VMCI host device registered (name=vmci, major=10, minor=122)
# 只看错误信息
qing222@qing222-virtual-machine:~/Desktop$ journalctl -p err
Journal file /var/log/journal/3865d7ce7eb84a1d8b0b0a0dfd3dee72/system@0006118e94da3dc5-fc2783304b4edadc.journal~ is truncated, ignoring file.
2月 01 18:42:40 qing222-virtual-machine pulseaudio[1119]: ALSA 提醒我们在该设备中写入新数据,但实际上没有什么可以写入的!
2月 01 18:42:40 qing222-virtual-machine pulseaudio[1119]: 这很可能是 ALSA 驱动程序 'snd_ens1371' 中的一个 bug。请向 ALSA 开发人员报告这个问题。
2月 01 18:42:40 qing222-virtual-machine pulseaudio[1119]: 我们因 POLLOUT 被设置而唤醒 -- 但结果是 snd_pcm_avail() 返回 0 或者另一个小于最小可用值的数值。
2月 01 18:42:41 qing222-virtual-machine systemd[1105]: Failed to start Application launched by gnome-session-binary.
2月 01 18:42:44 qing222-virtual-machine pulseaudio[1119]: ALSA 提醒我们从该设备中读取新数据,但实际上没有什么可以读取的!
2月 01 18:42:44 qing222-virtual-machine pulseaudio[1119]: 这很可能是 ALSA 驱动程序 'snd_ens1371' 中的一个 bug。请向 ALSA 开发人员报告这个问题。
2月 01 18:42:44 qing222-virtual-machine pulseaudio[1119]: 我们因 POLLOUT 被设置而唤醒 -- 但结果是 snd_pcm_avail() 返回 0 或者另一个小于最小可用值的数值。
2月 01 18:42:48 qing222-virtual-machine systemd[1105]: Failed to start Application launched by gnome-session-binary.
2月 01 18:43:05 qing222-virtual-machine pulseaudio[1119]: GetManagedObjects() failed: org.freedesktop.DBus.Error.NoReply: Did not receive a reply. Possible causes include: the remote application did not>
2月 01 18:47:38 qing222-virtual-machine pulseaudio[2228]: Failed to create secure directory (/nonexistent/.config/pulse): 没有那个文件或目录
2月 01 18:47:38 qing222-virtual-machine systemd[2217]: Failed to start Sound Service.
2月 01 18:47:39 qing222-virtual-machine systemd[2217]: Failed to start Tracker file system data miner.
五、systemd命令
systemctl 命令用于检查及控制 和服务管理器的状态
1、查看systemd信息
systemctl list-units
#列出 systemd 单元。可以使用可选参数:--state=running 用于显示已启用的单元,--type=service 用于显示已退出和已启用的单元。systemctl list-unit-files
#列出 systemd 单元和状态,例如 static、generated、disabled、alias、masked 和 enabled。systemctl list-dependencies
#列出依赖关系树。systemctl list-dependencies UNIT_FILE
#列出单元文件的依赖关系。(实用)
*2、管理systemd服务
systemctl daemon-reload
#重新加载systemd配置。在修改单元文件后,需要重新加载systemd配置。(实用)systemctl status SERVICE
#检查特定服务的状态。systemctl show SERVICE
#显示服务信息。systemctl start SERVICE
#启动服务。systemctl stop SERVICE
#停止正在运行的特定服务。systemctl restart SERVICE
#重启动服务。对配置文件进行更改后,必须再次重启动相关服务。(实用)systemctl enable SERVICE
#在开机时自动启动该服务。(实用)systemctl disable SERVICE
#取消开机时自动启动该服务
3、systemd查错
3.1、使用 systemd-analyze verify SERVICE 检查 systemd 单元文件的语法。
在启动或启用 systemd 服务之前,请检查单元文件的语法,确保没有任何错误。例如:
sudo systemd-analyze verify /etc/systemd/system/my-custom-service.service
该命令会分析单元文件,并报告任何语法错误、缺失的文件或其他问题。在启用和启动服务之前,您必须解决报告的所有问题
*3.2、使用 journalctl -u SERVICE 命令检查服务的日志。
如果您在使用某个 systemd 服务时遇到任何问题,请检查该服务的日志。例如:
sudo journalctl -u my-custom-service.service
3.3、使用 systemd-analyze plot 命令来可视化系统开机过程
如果某项服务导致引导过程出现问题,您可以使用 systemd-analyze plot command 来可视化引导过程并识别问题。例如:
sudo systemd-analyze plot > boot-plot.svg
该命令会创建一个名为 boot-plot.svg 的 SVG 文件,其中包含引导过程和潜在问题的图形表示。这包括每项服务的启动和停止时间。您可以在 SVG 兼容的图像查看器或 Web 浏览器中打开此文件,以分析在引导过程中导致问题的服务。
3.4、对失败的服务进行查错
要确定哪些服务失败并检查日志输出,请运行以下命令:
sudo systemctl --state=failed
3.5、检查服务的运行时状态
要确定服务的当前运行时状态,请运行以下命令:
sudo systemctl status SERVICE
4、其他命令
4.1、检查服务的运行时状态
要确定服务的当前运行时状态,请运行以下命令:
sudo systemctl status SERVICE
4.2、在 systemd 单元文件中使用绝对路径
在 systemd 单元文件中使用可执行文件和所需文件(例如配置文件或脚本)的绝对路径。systemd 不依赖使用用户的环境变量(例如 $PATH)来查找文件。
[Service]
ExecStart=/home/qing222/code/test_delete/build-untitled-unknown-Debug/untitled
4.3、使用 RestartSec 指令
如果您想定义一段延迟时间(以秒为单位),发生故障后,需要经过这段时间才重启动服务,那么,请在 [SERVICE] 部分使用 RestartSec 指令。此指令对于需要在经过指定时间后才释放资源,或防止出现快速重启循环(这可能导致系统负载过高)的服务非常有用。
[Service]
ExecStart=PATH_TO_EXECUTABLE
Restart=on-failure
RestartSec=5
六、systemd 启动流程
1、BIOS/UEFI 初始化 → 引导加载程序 → 内核加载
2、内核初始化完成后,启动 PID 1 进程(systemd)
3、systemd 读取目标单元配置,按依赖关系启动各个服务
启动流程:sysinit.target → basic.target → network.target → multi-user.target → graphical.target
systemd 采用"目标(target)"的概念代替了传统的运行级别。不同 target 表示系统的不同状态或启动阶段。以下是主要的 target 单元及其详细说明:
sysinit.target
●启动时机:系统最早的启动阶段之一
●主要任务:
挂载 /sys, /proc 等虚拟文件系统
设置主机名
初始化随机数生成器
加载内核模块
设置 SELinux
启动 udev
●适合场景:需要在系统初始化最早阶段执行的任务,通常用于硬件初始化相关操作
●需注意:此时许多系统资源尚未就绪,如文件系统可能处于只读状态
basic.target
●启动时机:sysinit.target 之后
●主要任务:
完成基本文件系统挂载
初始化日志服务
设置系统时钟
激活 LVM 卷和软件 RAID
挂载所有非系统存储设备
●适合场景:需要完整文件系统访问但不需要网络的任务
●示例用途:
清理临时文件
检查磁盘健康状态
初始化本地数据库
network.target
●启动时机:basic.target 之后
●主要任务:
初始化网络接口
分配 IP 地址
设置路由表
●适合场景:需要网络连接的服务和任务
●需注意:此 target 仅表示网络栈已初始化,不保证网络连接已经可用
network-online.target
●启动时机:network.target 之后
●主要任务:确保网络实际可用
●适合场景:严格依赖网络连接的服务,如网络文件系统挂载、远程数据库连接等
multi-user.target
●启动时机:network.target 之后
●主要任务:
启动系统关键服务
启动用户登录服务(如 SSH)
大多数常规服务都在这个阶段启动
●适合场景:大多数普通服务和守护进程
●对应传统:相当于传统 SysV init 中的运行级别 3
graphical.target
●启动时机:multi-user.target 之后
●主要任务:
启动图形环境
启动显示管理器
提供图形登录界面
●适合场景:依赖图形环境的服务或应用
●对应传统:相当于传统 SysV init 中的运行级别 5
选择合适的启动阶段的建议
●如果任务需要完整的文件系统但不需要网络:basic.target
●如果任务需要网络栈但不一定需要网络连接:network.target
●如果任务严格依赖网络连接成功:network-online.target
●大多数服务通常应该使用:multi-user.target
●需要图形环境的应用:graphical.target
资料参考:
官方文档:https://systemd.io/
systemd 服务配置完全指南:从入门到精通
systemd 基础知识简介(这里面的内容比较实用)
使用 systemd 设置开机和关机任务
