强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

systemd 教程 / 启动分析与优化

启动分析与优化

systemd 提供了丰富的工具来分析和优化系统启动时间。通过理解启动流程和关键路径,可以显著减少系统从开机到可用的等待时间。


1. systemd-analyze 命令

1.1 基本启动时间分析

# 查看启动各阶段耗时
systemd-analyze

# 输出示例:
# Startup finished in 1.234s (firmware) + 5.678s (loader) + 2.345s (kernel) + 12.567s (initrd) + 8.901s (userspace) = 30.725s
# graphical.target reached after 8.890s in userspace

1.2 systemd-analyze blame

blame 列出每个服务的启动时间,按耗时从长到短排序:

# 查看所有服务启动时间
systemd-analyze blame

# 输出示例:
#     15.234s NetworkManager-wait-online.service
#      8.567s plymouth-quit-wait.service
#      5.123s firewalld.service
#      3.456s cups.service
#      2.789s avahi-daemon.service
#      1.234s systemd-udev-settle.service
#        890ms initrd-parse-etc.service
#        567ms lvm2-monitor.service
# 按服务类型过滤
systemd-analyze blame --type=service

# 只看用户空间服务
systemd-analyze blame --user

# JSON 格式输出
systemd-analyze blame --json=pretty

1.3 systemd-analyze critical-chain

critical-chain 显示关键路径——决定启动总时间的服务链:

# 查看默认目标的关键路径
systemd-analyze critical-chain

# 输出示例:
# The time after the unit is active or started is printed after the "@" character.
# The time the unit takes to start is printed after the "+" character.
#
# graphical.target @8.890s
# └─multi-user.target @8.889s
#   └─cups.service @5.433s +3.456s
#     └─network.target @5.432s
#       └─NetworkManager.service @2.891s +2.540s
#         └─basic.target @2.890s
#           └─sockets.target @2.889s
#             └─dbus.socket @2.889s
# 指定目标查看
systemd-analyze critical-chain multi-user.target

# 查看指定服务的关键路径
systemd-analyze critical-chain nginx.service

1.4 systemd-analyze plot

生成 SVG 启动时序图:

# 生成 SVG 图
systemd-analyze plot > boot.svg

# 在浏览器中查看
xdg-open boot.svg  # 桌面环境
# 或
python3 -m http.server 8080 --directory /tmp  # 服务器

💡 提示:SVG 图是分析启动并行度的最佳工具,可以直观看到服务之间的依赖关系和等待时间。

1.5 systemd-analyze dump

输出完整的 systemd 内部状态:

# 输出到终端
systemd-analyze dump

# 重定向到文件(输出很长)
systemd-analyze dump > /tmp/systemd-dump.txt

# 过滤特定服务
systemd-analyze dump | grep -A 20 "nginx.service"

2. 启动时间分析

2.1 启动阶段详解

阶段说明典型耗时
firmwareUEFI/BIOS 初始化1-10s
loader引导加载程序(GRUB)1-5s
kernel内核加载和初始化1-5s
initrd初始内存盘2-15s
userspace用户空间服务5-30s

2.2 内核启动时间分析

# 查看内核启动时间
systemd-analyze time

# 查看内核日志中的时间戳
dmesg | less

# 查看内核初始化耗时
dmesg | grep -i "initcall" | sort -k3 -n -r | head -20

2.3 initrd 启动时间分析

# 查看 initrd 阶段的服务
systemd-analyze blame --firmware-setup

# 分析 initrd 内容
lsinitrd /boot/initramfs-$(uname -r).img | less

# 重建 initrd(优化后)
sudo dracut --force --hostonly

3. 关键路径分析

3.1 理解依赖关系

# 查看服务依赖树
systemd-analyze dot nginx.service

# 生成依赖图
systemd-analyze dot --to-pattern='*.target' | dot -Tsvg > deps.svg

# 查看反向依赖
systemctl list-dependencies --reverse nginx.service

3.2 依赖优化策略

策略方法适用场景
延迟启动Type=oneshot + RemainAfterExit=yes非关键服务
弱依赖Wants= 替代 Requires=非必需依赖
并行化减少 After= 约束无依赖关系的服务
Socket 激活使用 socket 协议有客户端的服务

4. 服务并行启动优化

4.1 并行化配置

# /etc/systemd/system.conf
[Manager]
DefaultDependencies=yes
DefaultTasksMax=4096

4.2 减少不必要的 After 依赖

# 优化前:串行启动
[Unit]
Description=My Service
After=network.target mysql.service redis.service

# 优化后:只在真正需要时添加 After
[Unit]
Description=My Service
After=network.target
Wants=mysql.service redis.service

4.3 Socket 激活

使用 socket 激活可以解耦服务启动顺序:

# myapp.socket
[Unit]
Description=My App Socket

[Socket]
ListenStream=8080

[Install]
WantedBy=sockets.target

# myapp.service
[Unit]
Description=My App
Requires=myapp.socket

[Service]
ExecStart=/usr/bin/myapp --socket=fd

5. 启动超时处理

5.1 超时配置

# /etc/systemd/system.conf
[Manager]
# 默认启动超时(秒)
DefaultTimeoutStartSec=90s

# 默认停止超时
DefaultTimeoutStopSec=90s

# 设备超时
DefaultDeviceTimeoutSec=90s

5.2 服务级超时

[Service]
# 设置较长超时
TimeoutStartSec=300

# 禁用超时(不推荐)
TimeoutStartSec=infinity

5.3 超时后行为

[Service]
# 超时后发送 SIGTERM
TimeoutStopSec=30

# 超时后强制 kill
KillMode=mixed
KillSignal=SIGTERM
FinalKillSignal=SIGKILL

⚠️ 注意:将超时设置过短会导致服务启动失败,设置过长会影响启动速度。建议根据服务实际需求设置。


6. initramfs 优化

6.1 分析 initramfs 大小

# 查看 initramfs 内容
lsinitrd /boot/initramfs-$(uname -r).img | wc -l

# 查看大小
ls -lh /boot/initramfs-$(uname -r).img

# 查看占用空间最多的文件
lsinitrd /boot/initramfs-$(uname -r).img | sort -k5 -n -r | head -20

6.2 优化 initramfs

# 使用 hostonly 模式(仅包含当前硬件所需模块)
sudo dracut --force --hostonly

# 排除不需要的模块
sudo dracut --force --hostonly --omit "network iscsi"

# 压缩算法优化
sudo dracut --force --hostonly --compress="xz -9 --check=crc32"

6.3 Dracut 配置

# /etc/dracut.conf.d/optimize.conf
# 仅包含当前硬件驱动
hostonly="yes"

# 排除的模块
omit_dracutmodules+=" network iscsi fcoe "

# 压缩算法
compress="xz"

7. 内核参数优化

7.1 systemd 相关内核参数

参数说明示例
systemd.unit=指定启动目标systemd.unit=multi-user.target
systemd.log_level=日志级别systemd.log_level=debug
systemd.confirm_spawn确认进程创建systemd.confirm_spawn=1
systemd.show_status显示启动状态systemd.show_status=1
systemd.default_timeout_start_sec默认超时systemd.default_timeout_start_sec=30

7.2 设置内核参数

# 临时设置(重启后失效)
sudo grubby --update-kernel=ALL --args="systemd.unit=multi-user.target"

# 永久设置
sudo grubby --update-kernel=ALL --args="systemd.default_timeout_start_sec=30"

# 查看当前参数
cat /proc/cmdline

7.3 跳过不必要的初始化

# 禁用 plymouth(启动画面)
sudo grubby --update-kernel=ALL --args="rd.plymouth=0 plymouth.enable=0"

# 禁用 SELinux(测试环境)
sudo grubby --update-kernel=ALL --args="enforcing=0"

8. 禁用不需要的服务

8.1 分析启用的服务

# 列出所有启用的服务
systemctl list-unit-files --state=enabled

# 查看哪些服务会拖慢启动
systemd-analyze blame | head -20

8.2 常见可禁用的服务

服务说明适用场景
NetworkManager-wait-online.service等待网络就绪服务器/容器
cups.service打印服务无打印机的服务器
ModemManager.service调制解调器管理无调制解调器
accounts-daemon.service用户账户服务服务器
avahi-daemon.servicemDNS/DNS-SD不需要 mDNS 的环境
firewalld.service防火墙使用 iptables 的服务器
postfix.service邮件服务不需要本地邮件

8.3 批量禁用

# 禁用单个服务
sudo systemctl disable cups.service
sudo systemctl mask cups.service  # 彻底禁止

# 批量禁用(服务器环境)
for service in cups avahi-daemon accounts-daemon ModemManager; do
    sudo systemctl disable ${service}.service
    sudo systemctl mask ${service}.service
done

⚠️ 注意maskdisable 更强,被 mask 的服务无法被手动或依赖启动。谨慎使用。


9. 实际案例

9.1 服务器启动优化

优化前:启动耗时 45 秒

# 1. 分析启动时间
systemd-analyze
# Startup finished in 2.5s (firmware) + 3.2s (loader) + 1.8s (kernel) + 8.5s (initrd) + 28.9s (userspace) = 44.9s

# 2. 分析耗时服务
systemd-analyze blame | head -10
#     15.234s NetworkManager-wait-online.service
#      5.678s firewalld.service
#      3.456s cups.service
#      2.345s avahi-daemon.service
#      ...

# 3. 优化
sudo systemctl disable NetworkManager-wait-online.service
sudo systemctl disable cups.service
sudo systemctl disable avahi-daemon.service
sudo systemctl mask cups.service
sudo systemctl mask avahi-daemon.service

# 4. 优化 initramfs
sudo dracut --force --hostonly

# 5. 优化超时
sudo grubby --update-kernel=ALL --args="systemd.default_timeout_start_sec=15"

优化后:启动耗时 18 秒

systemd-analyze
# Startup finished in 2.5s (firmware) + 3.2s (loader) + 1.8s (kernel) + 6.5s (initrd) + 4.2s (userspace) = 18.2s

9.2 容器快速启动

# /etc/systemd/system.conf.d/container.conf
[Manager]
DefaultTimeoutStartSec=10s
DefaultTimeoutStopSec=10s
DefaultDeviceTimeoutSec=5s
# 最小化 systemd 单元
sudo systemctl mask systemd-logind.service
sudo systemctl mask systemd-resolved.service
sudo systemctl mask systemd-networkd.service

# 使用 networkd 替代 NetworkManager
sudo systemctl enable systemd-networkd.service

10. 启动性能基准测试

10.1 自动化测试脚本

#!/bin/bash
# boot-benchmark.sh

RUNS=5
TOTAL=0

echo "Running boot benchmark ${RUNS} times..."

for i in $(seq 1 ${RUNS}); do
    echo "Run ${i}/${RUNS}..."
    sudo reboot
    sleep 60  # 等待系统重启
    BOOT_TIME=$(systemd-analyze | grep "startup" | grep -oP '[0-9]+\.[0-9]+s' | tail -1)
    echo "Boot time: ${BOOT_TIME}"
    TOTAL=$(echo "${TOTAL} + ${BOOT_TIME}" | bc)
done

AVERAGE=$(echo "${TOTAL} / ${RUNS}" | bc)
echo "Average boot time: ${AVERAGE}s"

10.2 持续监控

# 记录每次启动时间到日志
echo "$(date): $(systemd-analyze | grep 'startup')" >> /var/log/boot-times.log

# 生成报告
systemd-analyze blame > /var/log/boot-blame-$(date +%Y%m%d).log
systemd-analyze critical-chain > /var/log/boot-chain-$(date +%Y%m%d).log

⚠️ 注意事项

  1. 不要盲目禁用服务:某些服务禁用可能导致系统功能异常
  2. 测试环境先验证:优化措施应在测试环境验证后再应用到生产
  3. 备份配置:优化前备份 /etc/systemd/system.conf 和 GRUB 配置
  4. 监控关键服务:优化后监控关键服务是否正常启动
  5. 固件时间:firmware 和 loader 阶段通常无法通过软件优化

💡 提示

  • systemd-analyze plot 的 SVG 图是分析启动并行度的最佳可视化工具
  • NetworkManager-wait-online.service 是常见的启动瓶颈,服务器通常可以安全禁用
  • 使用 systemd-analyze verify 检查 unit 文件的正确性
  • 固态硬盘(SSD)对启动时间的提升最为显著
  • 容器环境可以跳过大部分硬件检测,启动速度更快

扩展阅读