帮你快速理解、总结文档立即下载
文档中心>TencentOS Server>操作指南>系统配置>系统服务管理(systemd)

系统服务管理(systemd)

最近更新时间:2026-08-24 18:27:31
我的收藏
本文介绍 systemd 的常用工具、服务类型、unit 配置及服务启动顺序,帮助您理解和使用 systemd 进行系统服务管理。

systemd 常用工具

systemctl

systemctl 是最常用的 systemd 管理工具,主要命令如下:
命令
说明
status
查看 unit 状态
cat
查看 unit 配置
start/restart/stop
控制 unit 当前状态
set-property
设置 unit 配置,例如 CPUAccountingCPUShares
daemon-reload
重新加载 manager 配置
list-units
列出系统中的 unit 及其状态
list-dependencies
以树状图展示各个 unit 之间的依赖关系
enable/disable
设置/取消 unit 开机启动,等价于创建/删除 unit file 到 /etc/systemd/ 下的软链接
mask/unmask
disable 类似,但 mask 后的 service 无法启动(即使被其他 unit require),等价于创建 unit file 到 /dev/null 的链接

journalctl

journalctl 用于查询 systemd 日志,常用参数如下:
参数
说明
-u
按 unit 查询
-b
只显示本次启动日志
-k
显示内核相关日志
例如,查看 dbus 服务相关日志:
journalctl -u dbus.service
journalctl -b 命令只能查看本次启动的日志。如果需要查询之前的启动日志,需将 journald 日志切换到磁盘存储(请参见日志管理相关文档),然后通过以下方式查询:
使用 --list-boots 参数列出系统中所有启动记录:
journalctl --list-boots
返回结果如下,其中 IDX 列为启动序号,负数表示历史启动记录,0 表示当前启动:
IDX BOOT ID FIRST ENTRY LAST ENTRY
-9 9d27b37bc8014865b0c20c957429dc31 Wed 2023-01-18 15:44:22 HKT Fri 2023-02-24 10:27:36 HKT
-8 aa28b72e95074434a4a81b623c400e7e Tue 2023-02-28 16:35:24 HKT Tue 2023-02-28 16:45:08 HKT
-7 12a71bb5bd9d4dec993d0e03e0cbe636 Mon 2023-03-06 10:46:43 HKT Mon 2023-03-06 11:07:43 HKT
...
指定 IDX 序号即可查看对应启动的日志,例如查看序号为 -8 的启动日志:
journalctl -b -8

systemd-analyze

systemd-analyze 是系统启动时间分析工具,主要子命令如下:
子命令
说明
blame
分析系统中各服务的启动时间
plot
图形化显示系统中服务的启动顺序,可通过网页或图形编辑器打开
dump
查看每个服务的状态、cgroup mask 等,比 systemctl status 更详细

blame

blame 命令分析系统中本次启动各服务的启动时间,默认按时间从长到短列出各服务的启动顺序:
systemd-analyze blame
返回结果如下,按启动耗时从长到短排列:
8.814s kdump.service
2.442s NetworkManager-wait-online.service
944ms dev-vda1.device
568ms sshd-keygen@rsa.service
295ms initrd-switch-root.service
214ms var-lib-nfs-rpc_pipefs.mount
206ms dnf-makecache.service
194ms dracut-initqueue.service
143ms user@0.service
135ms ipmi.service
118ms initrd-parse-etc.service
103ms chronyd.service
99ms NetworkManager.service
99ms systemd-logind.service
92ms avahi-daemon.service
88ms auditd.service
71ms lvm2-monitor.service
...
通过 blame 可以方便地排查系统启动时间。找到耗时服务后,结合该服务自身的日志或其他排查手段分析耗时原因。例如,上述输出中 kdump 服务启动时间最长,通过 strace 工具可以看到它最耗时的过程是加载 kdump 内核。

systemd-cgls

systemd-cgls 用于查看系统中的 cgroup 层级。相比直接在 cgroup 目录下查看,systemd-cgls 会把每个 cgroup 中的进程都列出来,并且各个层级的关系更加清晰:
systemd-cgls
返回结果如下,以树状结构展示各 cgroup 及其包含的进程:
├─user.slice
│ └─user-0.slice
│ → user.invocation_id: 183a492473c94efe8e3c4b1e1745f0b0
│ → trusted.invocation_id: 183a492473c94efe8e3c4b1e1745f0b0
│ ├─33878 sshd: root [priv]
│ ├─33892 sshd: root@pts/0
│ ├─33893 -bash
│ ├─35517 systemd-cgls
│ └─35518 less
│ └─user@0.service
│ └─init.scope
│ ├─33882 /usr/lib/systemd/systemd --user
│ └─33885 (sd-pam)
├─init.scope
│ └─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 31
└─system.slice
├─rngd.service
│ └─685 /usr/sbin/rngd -f -x pkcs11 -x nist
├─irqbalance.service
│ └─683 /usr/sbin/irqbalance --foreground

systemd-nspawn

systemd-nspawn 的使用方式与 chroot 类似,但进入的目录需要是一个 OS tree 形式。如果目录是正确的 OS tree 形式,先查看目录内容确认:
ls rootfs/
返回结果如下,即目录中包含完整的 OS 文件系统结构:
bin boot data dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
确认无误后,通过 systemd-nspawn 创建轻量级容器:
说明:
如果目录不符合 OS tree 要求,执行以下命令将返回类似 Directory /root/rootfs doesn't look like it has an OS tree (/usr/ directory is missing). Refusing. 报错。
systemd-nspawn -D ./rootfs
成功进入容器后,返回结果如下:
Spawning container rootfs on /root/rootfs.
Press ^] three times within 1s to kill container.
如果需要模拟真实环境,还可增加 -b 选项在容器中启动 systemd。

systemd 服务

服务开机启动

systemd 在启动时,会根据 /usr/lib/systemd/system-preset/ 以及 /usr/lib/systemd/user-preset/ 下的 preset 文件决定哪些服务开机启动。当前系统主要默认配置了以下几个配置文件:
文件名
作用
90-default.preset
控制默认启动的系统服务
99-default-disable.preset
默认禁用所有服务
85-display-manager.preset
控制桌面相关的服务是否需要自启动
preset 文件按照文件名决定执行顺序,前面的数字越小,优先级越高,越后执行。因此,在 99-default-disable.preset 中即便 disable 所有服务,仍可以在 90-default.preset85-display-manager.preset 中开启所需的服务。

systemd unit 种类

service

service 是最常接触的 unit,控制系统中的进程运行(包括 daemon 进程),例如 dbus.servicedocker.service 等。通常通过 ExecStart= 指定程序运行的动作,ExecReload= 指定 systemctl reload 的动作,ExecStop= 指定停止 unit 的动作。
使用 systemctl cat 查看 dbus.service 的 unit file 配置:
systemctl cat dbus.service
返回结果如下,可以看到该 service 的完整配置,包括 [Unit][Service][Install] 三个配置段:
# /usr/lib/systemd/system/dbus-broker.service
[Unit]
Description=D-Bus System Message Bus
Documentation=man:dbus-broker-launch(1)
DefaultDependencies=false
After=dbus.socket
Before=basic.target shutdown.target
Requires=dbus.socket
Conflicts=shutdown.target
[Service]
Type=notify
Sockets=dbus.socket
OOMScoreAdjust=-900
LimitNOFILE=16384
ProtectSystem=full
PrivateTmp=true
PrivateDevices=true
ExecStart=/usr/bin/dbus-broker-launch --scope system --audit
ExecReload=/usr/bin/busctl call org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus ReloadConfig
[Install]
Alias=dbus.service
通过 systemctl status 可以查看 service 的状态信息,并打印该服务相关的 journal 日志。以 sshd 服务为例:
systemctl status sshd
返回结果如下,包含服务加载状态、运行状态、主进程 PID、内存占用等信息:
● sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2023-04-21 11:52:56 CST; 2 weeks 4 days ago
Docs: man:sshd(8)
man:sshd_config(5)
Main PID: 1208 (sshd)
Tasks: 1 (limit: 9183)
Memory: 8.7M
CPU: 199ms
CGroup: /system.slice/sshd.service
└─1208 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"
状态输出中各字段的含义如下:
服务名前面的圆点("●"):用不同的颜色和形状表示服务当前状态。
圆点颜色形状
表示的状态
"○"
inactive 或 maintenance
"●"(绿色)
active
"●"(白色)
deactivating
"×"
failed 或 error
"↻"
reloading
Loaded 行:显示该服务是否被加载进内存。loaded 表示已加载,error 表示加载失败,not-found 表示未找到 unit file,bad-setting 表示 unit file 配置错误,masked 表示服务被 mask。后面的路径为加载的 unit file 路径,再后面为当前该服务是否设置开机启动(enabled),vendor preset 表示发行版厂商是否将该服务预设为开机启动。
Active 行:显示该服务的运行状态。括号前为当前状态,括号内为子状态。
当前状态取值如下:
状态
说明
active
unit 正在运行
inactive
unit 已经停止运行
activating
unit 正在启动中
deactivating
unit 正在停止中
failed
unit 启动失败
子状态取值如下:
子状态
说明
running
unit 正在运行
exited
unit 已经停止运行
waiting
unit 正在等待某些条件的发生,例如网络连接、文件系统挂载等
start-pre
unit 正在启动前的准备工作
start-post
unit 启动后的工作
stop-pre
unit 停止前的准备工作
stop-post
unit 停止后的工作
后面的时间为该服务最后一次启动的时间。

timer

timer 是定时器,在固定的时间触发激活其他 unit(默认是同名的 service)。通常通过 [Timer] 字段中的 OnActiveSec=/OnCalendar= 等配置项控制触发时间,详细说明可执行 man systemd.timer查看。
例如,sysstat-collect 中配置的 *:00/10 表示整点开始,每 10 分钟触发一次。使用 systemctl cat 查看其 timer 配置:
systemctl cat sysstat-collect.timer
返回结果如下,可以看到 [Timer] 段中通过 OnCalendar=*:00/10 配置触发周期:
# /usr/lib/systemd/system/sysstat-collect.timer
# Activates activity collector every 10 minutes
[Unit]
Description=Run system activity accounting tool every 10 minutes
[Timer]
OnCalendar=*:00/10
[Install]
WantedBy=sysstat.service
通过 systemctl status 可以看到 timer 相比 service 多了 TriggerTriggers 字段。Trigger 指下次触发的时间及剩余时间,Triggers 显示该计时器所激活的服务。查看 sysstat-collect.timer 的状态:
systemctl status sysstat-collect.timer
返回结果如下,该示例中,timer 触发的服务是 sysstat-collect.service,8 分钟后再次触发。
● sysstat-collect.timer - Run system activity accounting tool every 10 minutes
Loaded: loaded (/usr/lib/systemd/system/sysstat-collect.timer; enabled; vendor preset: disabled)
Active: active (waiting) since Thu 2023-05-11 20:04:47 CST; 1 week 0 days ago
Until: Thu 2023-05-11 20:04:47 CST; 1 week 0 days ago
Trigger: Thu 2023-05-18 20:40:00 CST; 8min left
Triggers: ● sysstat-collect.service

mount

mount 用于控制系统中的挂载点,通常通过 [Mount] 字段中的 Where=/What=/Type= 控制挂载的位置、设备和类型。正常情况下只需配置 /etc/fstabsystemd-fstab-generator 会自动将 fstab 中的挂载点生成对应的 mount unit。
使用 systemctl cat 查看已生成的 mnt.mount 配置:
systemctl cat mnt.mount
返回结果如下,该 mount unit 由 systemd-fstab-generator 自动生成,配置内容与 /etc/fstab 中的挂载项对应:
# /run/systemd/generator/mnt.mount
# Automatically generated by systemd-fstab-generator
[Unit]
Documentation=man:fstab(5) man:systemd-fstab-generator(8)
SourcePath=/etc/fstab
Before=local-fs.target
Requires=systemd-fsck@dev-vdb1.service
After=systemd-fsck@dev-vdb1.service
After=blockdev@dev-vdb1.target
[Mount]
What=/dev/vdb1
Where=/mnt
Type=ext4
Options=noatime,acl,user_xattr
例如,在 /etc/fstab 中配置如下挂载项:
cat /etc/fstab
返回结果如下,其中配置了 /dev/vdc1 挂载到 /data/ 目录:
/dev/vdc1 /data/ ext4 noatime,acl,user_xattr 1 1
重启后(systemd-fstab-generator 会在启动时执行),系统中会生成对应的 mount 服务,服务配置与 fstab 中配置相对应。首先使用 systemctl list-units 确认 mount 服务已生成:
systemctl list-units -a | grep data
返回结果如下,可以看到 data.mount 已加载并处于 active 状态:
data.mount loaded active mounted /data
然后执行以下命令查看其配置内容:
systemctl cat data.mount
返回结果如下,配置中的 WhatWhereTypeOptions/etc/fstab 中的配置一致:
# /run/systemd/generator/data.mount
# Automatically generated by systemd-fstab-generator
[Unit]
Documentation=man:fstab(5) man:systemd-fstab-generator(8)
SourcePath=/etc/fstab
Before=local-fs.target
Requires=systemd-fsck@dev-vdc1.service
After=systemd-fsck@dev-vdc1.service
After=blockdev@dev-vdc1.target
[Mount]
What=/dev/vdc1
Where=/data
Type=ext4
Options=noatime,acl,user_xattr

automount

automountmount 类似,区别是 automount 仅在用户访问对应目录时才挂载,而非像 mount 一样从启动后一直挂载。可以通过 autofs 使用 automount 能力。以下示例介绍如何使用 automount 服务。
1. 安装 autofs 服务
dnf install -y autofs
2. /etc/auto.master 文件中配置 automount 服务
vim /etc/auto.master
在文件末尾添加以下内容:
/mnt/ /etc/auto.devices --timeout=10
其中,/mnt/ 是挂载点所在的路径(不是设备挂载点),/etc/auto.devices 是设备挂载配置文件的路径,--timeout=10 表示设备挂载超时时间为 10 秒。
3. /etc/auto.devices 文件中配置需要挂载的设备
vim /etc/auto.devices
在文件中添加需要挂载的设备信息:
mymnt -fstype=auto :/dev/vdb
其中,mymnt 是挂载的目录,-fstype=auto 表示自动检测设备文件系统类型,:/dev/vdb 是设备的路径。
4. 重启 autofs 服务
systemctl restart autofs
5. 验证 automount 功能
当需要访问 mymnt 设备时,访问 /mnt/ 目录下的 mymnt 目录,automount 服务会自动将 /dev/vdb 设备挂载到该目录下。
注意:进入 /mnt 目录时,看不到 mymnt 目录,也无法通过 Tab 补全,但可以直接访问它。
cd /mnt/mymnt
访问 /mnt/mymnt 目录后,automount 服务会自动将 /dev/vdb 设备挂载到该目录下。使用 lsblk 命令查看挂载状态:
lsblk
返回结果如下,可以看到 /dev/vdb 已挂载到 /mnt/mymnt
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sr0 11:0 1 18.8M 0 rom
zram0 251:0 0 8G 0 disk [SWAP]
vda 252:0 0 100G 0 disk
└─vda1 252:1 0 100G 0 part /
vdb 252:16 0 200G 0 disk /mnt/mymnt
vdc 252:32 0 300G 0 disk
└─vdc1 252:33 0 300G 0 part /data
如果一段时间内没有访问该目录,automount 服务会自动卸载设备,以释放系统资源。

target

target unit 与其他 unit 不同,它本身不执行任何操作,仅代表一个群组的 unit。target 通过 Requires=/After= 等 unit 依赖配置来控制每个群组 unit 的依赖关系和启动顺序,通过 systemctl list-dependencies 可以查看。以 multi-user.target 为例:
systemctl list-dependencies multi-user.target
返回结果如下,以树状结构展示该 target 依赖的所有 unit:
multi-user.target
● ├─acpid.service
● ├─arpwatch.service
● ├─atd.service
● ├─auditd.service
● ├─avahi-daemon.service
● ├─chrony-wait.service
● ├─chronyd.service
● ├─crond.service
● ├─gssproxy.service
系统启动时通过一个一个的 target 服务,按顺序拉起各个子系统所依赖的具体服务。例如,启动时系统只需拉起 default.target(本系统中为 multi-user.targetgraphical.target),其他各个 target 只需在它们的 unit file 中指定:
[Install]
WantedBy=multi-user.target
即可实现在 multi-user.target 启动前启动。

path

path unit 与 timer unit 类似,主要作用是当监控的路径改变时,触发同名的 service。通过 [Path] 字段中的 DirectoryNotEmpty=/PathChanged= 等配置项控制监控的路径及对应模式。
使用 systemctl cat 查看系统自带的 systemd-ask-password-console.path 配置:
systemctl cat systemd-ask-password-console.path
返回结果如下,可以看到 [Path] 段中通过 DirectoryNotEmpty= 监控 /run/systemd/ask-password 目录:
# /usr/lib/systemd/system/systemd-ask-password-console.path
[Unit]
Description=Dispatch Password Requests to Console Directory Watch
Documentation=man:systemd-ask-password-console.path(8)
DefaultDependencies=no
Conflicts=shutdown.target emergency.service
After=plymouth-start.service
Before=paths.target shutdown.target cryptsetup.target
ConditionPathExists=!/run/plymouth/pid
[Path]
DirectoryNotEmpty=/run/systemd/ask-password
MakeDirectory=yes
以下示例介绍 path 服务的使用方法。
1. 创建 .path 单元文件
/etc/systemd/system 目录下创建 my-path-monitor.path 文件,定义要监视的路径和触发条件:
[Unit]
Description=Monitor changes in /data/testpath directory
[Path]
PathModified=/data/testpath
Unit=my-triggered-service.service
[Install]
WantedBy=multi-user.target
.path 单元文件将监视 /data/testpath 目录的更改。当该目录发生更改时,将触发名为 my-triggered-service.service 的服务。
2. 创建关联的 service 单元文件
/etc/systemd/system 目录下创建 my-triggered-service.service 文件,定义服务的行为:
[Unit]
Description=Service triggered by path changes
[Service]
Type=oneshot
ExecStart=/usr/bin/echo "123"
该服务将在 .path 单元触发时执行 echo 123
3. 重新加载 systemd 配置
systemctl daemon-reload
4. 启动 .path 单元
systemctl start my-path-monitor.path
5. 触发路径变更
rm -r /data/testpath
6. 验证服务是否被触发
查看 my-triggered-service.service 日志,该服务已被 path 服务触发:
systemctl status my-triggered-service.service
返回结果如下,可以看到服务已被触发执行,状态为 inactive (dead) 表示已执行完毕:
○ my-triggered-service.service - Service triggered by path changes
Loaded: loaded (/etc/systemd/system/my-triggered-service.service; static)
Active: inactive (dead) since Mon 2023-05-29 03:09:15 UTC; 9s ago
TriggeredBy: ● my-path-monitor.path
Process: 1227670 ExecStart=/usr/bin/echo 123 (code=exited, status=0/SUCCESS)
Main PID: 1227670 (code=exited, status=0/SUCCESS)
CPU: 1ms
May 29 03:09:15 localhost.localdomain systemd[1]: Starting my-triggered-service.service - Service triggered by path changes...
May 29 03:09:15 localhost.localdomain echo[1227670]: 123
May 29 03:09:15 localhost.localdomain systemd[1]: my-triggered-service.service: Deactivated successfully.
May 29 03:09:15 localhost.localdomain systemd[1]: Finished my-triggered-service.service - Service triggered by path changes.

socket

socket unit 与 timer/path 一样,配合 service unit 使用。通过 socket unit 指定 systemd 监听的 socket,当 socket 有写入时 systemd 唤醒该 unit 对应的 service unit。
使用 systemctl cat 查看 acpid 服务及其 socket 的配置:
systemctl cat acpid acpid.socket
返回结果如下,可以看到 service 通过 Requires=acpid.socket 依赖对应的 socket unit,socket unit 通过 ListenStream=/run/acpid.socket 指定监听地址:
# /usr/lib/systemd/system/acpid.service
[Unit]
Description=ACPI Event Daemon
Documentation=man:acpid(8)
Requires=acpid.socket
[Service]
StandardInput=socket
EnvironmentFile=/etc/sysconfig/acpid
ExecStart=/usr/sbin/acpid -f $OPTIONS
[Install]
Also=acpid.socket
WantedBy=multi-user.target

# /usr/lib/systemd/system/acpid.socket
[Unit]
Description=ACPID Listen Socket
Documentation=man:acpid(8)
[Socket]
ListenStream=/run/acpid.socket
[Install]
WantedBy=sockets.target
以下示例介绍 socket 服务的使用方法。
1. 安装 nc 工具
dnf install nc -y
2. 创建 service 单元文件
/etc/systemd/system 目录下创建 socket_server.service 文件:
[Unit]
Description=Socket Server
[Service]
ExecStart=nc -l 12345
User=nobody
Group=nobody
3. 创建 socket 单元文件
/etc/systemd/system 目录下创建 socket_server.socket 文件:
[Unit]
Description=Socket Server Socket
[Socket]
ListenStream=12345
Accept=yes
[Install]
WantedBy=sockets.target
.socket 单元文件将在 12345 端口上创建一个 TCP 套接字,并在接收到连接请求时激活 socket_server.service
4. 重新加载 systemd 配置
systemctl daemon-reload
5. 启动 .socket 单元
systemctl start socket_server.socket
套接字已创建并开始监听连接。当有客户端连接到端口 12345 时,socket_server.service 将被激活并执行 nc -l 12345
6. 验证连接
使用 telnetnc(netcat)连接到端口 12345:
telnet localhost 12345

swap

swap unit 管理 swap 分区挂载,与 mount 类似,通常也是通过 /etc/fstab 配置,由 systemd-fstab-generator 自动生成。
1. 创建一个 swap 文件
fallocate -l 1G /swapfile
2. 将文件设置为 swap
mkswap /swapfile
3. /etc/fstab 文件中添加 swap 配置
/etc/fstab 文件末尾添加一行,指定 swap 分区或文件的路径、挂载点(使用 none)、文件系统类型(使用 swap)以及挂载选项(使用 sw),最后添加两个数字 0 0,表示不需要进行文件系统检查:
/swapfile none swap sw 0 0
重启后,swap 分区或文件会自动启用,系统已自动创建对应的 swap 服务。使用 systemctl list-units 查看 swap 服务状态:
systemctl list-units -a | grep swap
返回结果如下,可以看到 swapfile.swap 已加载并处于 active 状态:
swapfile.swap loaded active active /swapfile
可以使用 free -hswapon --show 命令查看 swap 的状态:
free -h
返回结果如下,可以看到 Swap 总量为 1.0Gi,当前未使用:
total used free shared buff/cache available
Mem: 7.5Gi 195Mi 7.1Gi 9Mi 210Mi 7.1Gi
Swap: 1.0Gi 0B 1.0Gi

device

device unit 是由 systemd-udevd 根据 /sys//dev/ 下的设备创建的 unit,主要作用是控制设备和设备之间以及设备和其他 unit 之间的依赖关系。
使用 systemctl list-dependencies 查看 mnt.mount 的依赖关系,可以看到其中包含 dev-vdb1.device
systemctl list-dependencies mnt.mount
返回结果如下,mnt.mount 依赖对应的块设备 unit dev-vdb1.device
mnt.mount
● ├─-.mount
● ├─dev-vdb1.device
● ├─system.slice
○ └─systemd-fsck@dev-vdb1.service

slice

slice 类似 target,也是一组 unit 的代表,但 slice 用于在 cgroup 中进行资源控制。系统默认将 unit 分为 user.slice(用户会话)、system.slice(系统进程)、machine.slice(容器和虚拟机进程)。
使用 tree 命令查看系统中的 cgroup 层级结构:
tree -d /sys/fs/cgroup/
返回结果如下,可以看到各个 service 分别归属于 system.sliceuser.slice
/sys/fs/cgroup/
├── dev-hugepages.mount
├── dev-mqueue.mount
├── init.scope
├── proc-fs-nfsd.mount
├── proc-sys-fs-binfmt_misc.mount
├── sys-fs-fuse-connections.mount
├── sys-kernel-config.mount
├── sys-kernel-debug.mount
├── sys-kernel-tracing.mount
├── system.slice
│ ├── NetworkManager.service
│ ├── acpid.service
│ ├── arpwatch.service
│ ├── atd.service
│ ├── auditd.service
│ ├── avahi-daemon.service
│ ├── chronyd.service
│ ├── systemd-logind.service
│ ├── systemd-udevd.service
│ │ └── udev
│ ├── systemd-userdbd.service
│ ├── tmp.mount
│ └── var-lib-nfs-rpc_pipefs.mount
└── user.slice
└─user-0.slice
├── session-1702.scope
├── session-22304.scope

scope

scopeslice/target 类似,不同的是 scope unit 仅可通过 systemd dbus 接口创建,且 scope unit 中的进程不会自行创建子进程。

unit 配置

systemd 支持的 unit 配置参数数量庞大,大部分问题都与配置有关。这里以 CPU 资源控制相关配置为例,CPU 的资源控制配置主要由以下几种方式决定。

default 配置

systemd 有一个 unit 配置表 ConfigTableItem,表中的配置项都会有默认初始值。如果后续没有手动配置,这些属性会使用代码中的初始值,例如 CPUAccounting 默认为 false。可以在 src/core/main.c 文件中查看:
static int parse_config_file(void) {
const ConfigTableItem items[] = {
{ "Manager", "LogLevel", config_parse_level2, 0, NULL },
{ "Manager", "LogTarget", config_parse_target, 0, NULL },
.....

manager 配置文件

manager 配置文件位于以下路径:
/etc/systemd/system.conf
/etc/systemd/user.conf
/etc/systemd/system.conf.d/
/etc/systemd/user.conf.d/

unit file

unit 自己的配置文件一般在 /usr/lib/systemd/system/ 下。可以通过 systemctl cat a.service 查看具体内容。通过 systemctl set-property 命令手动设置属性时,最终会在 /etc/systemd/ 下生成对应 unit 的额外配置文件。
rsyslog.service 为例,使用 systemctl set-property 设置 CPU 配额为 50%:
systemctl set-property rsyslog.service CPUQuota=50%
然后使用 systemctl show 查看该属性的配置路径:
systemctl show rsyslog.service | grep CPUQuota
返回结果如下,可以看到 DropInPaths 指向了自动生成的配置文件路径:
DropInPaths=/etc/systemd/system.control/rsyslog.service.d/50-CPUQuota.conf
可以看到最终生成 /etc/systemd/system.control/rsyslog.service.d/50-CPUQuota.conf 额外配置文件。查看该文件内容:
cat /etc/systemd/system.control/rsyslog.service.d/50-CPUQuota.conf
返回结果如下,文件中记录了通过 set-property 设置的 CPUQuota=50% 配置:
# This is a drop-in unit file extension, created via "systemctl set-property"
# or an equivalent operation. Do not edit.
[Service]
CPUQuota=50%

服务启动顺序

systemd 服务的启动顺序通过配置相互依赖关系实现。unit 与 unit 之间的依赖关系分为多种情况,包括自动生成的依赖和显式配置的依赖。

自动生成依赖

自动生成的依赖分为两种:隐式依赖和默认依赖。
隐式依赖:通过 unit TypeUnit 的配置决定。例如 dbus.serviceType=dbus,会隐式依赖 dbus.socket(等价于 Requires= 以及 After=dbus.socket)。
默认依赖:与隐式依赖类似,但可以通过 DefaultDependencies= 选项控制开关。例如 A.target 里配置了 Wants= 或者 Requires=B,A 会默认被配置一个 After=B。所有 target 都会默认配置 Conflicts=shutdown.targetBefore=shutdown.target,以保证关机前所有 target 已退出。Triggers/TriggeredBy 会默认配置在 socket/path/mount 等对应的 service 中。

显式配置依赖

显式配置的依赖关系主要有 6 种(两两配对,逻辑相同但行为相反):
依赖关系
说明
Wants/WantedBy
弱依赖。A Wants= B,A 启动时会尝试拉起 B,如果 B 启动失败,A 继续启动。也可以通过在 unit file 外创建 .wants 目录实现同样效果
Requires/RequiredBy
强依赖。A Requires= B,A 启动时会尝试拉起 B,如果 B 启动失败,A 不会启动。也可以通过创建 .requires/ 目录实现同样效果
BindsTo/BoundBy
更强依赖。与 Requires 不同的是,A BindsTo= B,如果 A 关闭了,B 也会关闭,而 Requires 时 B 不受影响
Before/After
启动顺序。A Before= B,A 启动后 B 才能启动。关闭流程相反:A Before= B 时,如果 A 和 B 都需要关闭,B 先关闭,A 才会关闭
PartOf/ConsistsOf
Requires 相似,但 PartOf 只影响关闭和重启动作。A PartOf= B,B 被关闭或重启时,A 也会被关闭或重启
Conflicts/ConflictedBy
A Conflicts= B,启动 A 就会关闭 B
例如,查看 rsyslog 服务是由谁拉起的,通过 list-dependencies 命令的 --reverse 参数查看反向依赖:
systemctl list-dependencies rsyslog --reverse
返回结果如下,可以看到 rsyslog.servicemulti-user.target 拉起,而 multi-user.target 又被 graphical.target 拉起:
rsyslog.service
● └─multi-user.target
○ └─graphical.target
之所以有如此依赖关系,是因为 rsyslog 服务的 unit file 中有如下配置。使用 systemctl cat 查看其配置:
systemctl cat rsyslog.service
返回结果如下,可以看到 [Install] 段中通过 WantedBy=multi-user.target 指定了依赖关系:
# /usr/lib/systemd/system/rsyslog.service
[Unit]
...
[Install]
WantedBy=multi-user.target
...