开机启动优化记录

日期 :2025-09-04

系统 :Debian 13 (trixie) / kernel 6.12.95+deb13-amd64 / KDE Plasma 6 / X11

机型 :Lenovo XiaoXinAir 14

CPU :AMD Ryzen 5 5500U(6核12线程)

结果 :启动时间从 1 分 4 秒 降至 26.16 秒


排查思路

Linux 开机启动是 systemd 串行 + 并行混合调度,任何一条长链路上有服务失败或超时,整条链路都会跟着卡住。排查顺序:

  1. systemd-analyze blame --- 看哪些服务耗时最长
  2. systemd-analyze critical-chain graphical.target --- 看启动关键路径,找出卡在哪个环节
  3. journalctl -b -p err --- 看本次启动的所有错误和警告

最终数据对比

整体启动时间

阶段 修复前 修复后 变化
firmware(BIOS/UEFI) --- 5.9s ---
loader(GRUB) --- 8.8s ---
kernel 37.8s 7.3s -30.5s
userspace(systemd) 6 分 13 秒 4.12 秒 -6 分 9 秒
合计 7 分 4 秒 26.16 秒 -6 分 38 秒

关键路径(graphical.target 依赖链)

修复前:

复制代码
graphical.target @6min 8.330s
  └─ power-profiles-daemon.service @6min 8.224s
      └─ multi-user.target @6min 8.221s
          └─ lxc.service @3.870s +30.195s   ← 等了 30 秒超时
              └─ remote-fs.target
                  └─ mnt-shared.mount @24.991s  ← NFS 挂载等网络就绪
                      └─ nfs-client.target
                          └─ ...(一直等到 NFS 网络通)

修复后:

复制代码
graphical.target @4.121s
  └─ power-profiles-daemon.service @4.038s
      └─ multi-user.target @4.036s
          └─ containerd.service @3.624s +410ms
              └─ network.target @3.618s
                  └─ NetworkManager.service @2.844s +773ms
                      └─ dbus.service @2.757s +80ms
                          └─ sysinit.target @2.607s
                              └─ apparmor.service @2.548s +58ms
                                  └─ local-fs.target @2.538s
                                      └─ home-a1-.cache-mozilla.mount @2.487s +50ms
                                          └─ local-fs-pre.target @640ms

lxc.service 这条长链被砍掉后,整个关键路径从 6 分钟直接降到 4 秒。


一、zram swap 反复失败(导致 30s 启动超时)

现象

复制代码
Failed to activate swap dev-zram0.swap - /dev/zram0
Failed to activate swap dev-zram0.swap - /dev/zram0
Failed to activate swap dev-zram0.swap - /dev/zram0

启动日志里出现 3 次同样报错,每次尝试间隔约 10 秒,累计 30 秒。

原因

我们之前创建了一个 zramswap 服务来管理 zram 压缩内存作为 swap。这个服务在启动时会动态创建 /dev/zram0 设备并执行 swapon。但同时,/etc/fstab 里也写了一行:

复制代码
/dev/zram0 none swap sw 0 0

systemd 的 fstab-generator 会在启动早期扫描 /etc/fstab,为每一行生成对应的 unit(比如 dev-zram0.swap)。这个生成的 unit 比 zramswap.service 更早启动(因为它是"设备挂载"类单元,优先级高于普通 service),它尝试在 /dev/zram0 还不存在的时候就激活 swap ------ 必然失败。zramswap.service 稍后成功创建设备并完成 swapon,所以 swap 最终能用,但前面 3 次失败重试白白浪费了近 30 秒。

修复

为什么只改 fstab、不改 zramswap.service?

因为 zramswap.service 的机制是正确的:它自己负责创建设备、配置算法(zstd)、设置大小(内存的 50% = 7.5GB)、设置 priority(100)。fstab 的那一行是多余的冲突源,删掉即可,不需要动 service 文件。

bash 复制代码
# 从 fstab 删除 zram 行
sudo sed -i '/zram/d' /etc/fstab

# 清除 systemd 缓存的旧 generator 单元
sudo systemctl daemon-reload

# 确保 zramswap 开机自启(如果之前没开的话)
sudo systemctl enable zramswap.service

验证:

bash 复制代码
sudo swapon --show
# NAME       TYPE      SIZE USED PRIO
# /dev/zram0 partition 7.5G   0B 100

二、i2c-1 SMBus Timeout 报错

现象

复制代码
i2c i2c-1: SMBus Timeout!
i2c i2c-1: Failed reset at end of transaction (01)
i2c i2c-1: Failed! (01)

这些报错出现在内核启动早期(约开机后 1.6 秒),伴随 i2c-1 设备出现。

原因

i2c_piix4 是 Linux 内核的 SMBus 驱动,专为 Intel PIIX4 芯片组设计,常见于虚拟机(VMware、VirtualBox)中模拟的南桥芯片。我们的机器是物理机 AMD Ryzen 5 5500U,主板上有 Synopsys DesignWare I2C 控制器(i2c-0 ~ i2c-8),但没有任何设备挂在 i2c-1 这条总线上。

模块加载后,内核会 probe i2c-1 总线上的所有地址,尝试与可能存在的外设通信。因为没有任何设备响应,每次 probe 都会超时(SMBus Timeout),于是产生这些报错。

检查确认:

bash 复制代码
cat /sys/bus/i2c/devices/i2c-1/name
# SMBus PIIX4 adapter port 0 at 0b00

lsmod | grep i2c_piix4
# i2c_piix4 28672 0   ← 引用计数为 0,没人用它

修复

通过 modprobe 黑名单阻止该模块加载:

bash 复制代码
echo "blacklist i2c_piix4" | sudo tee /etc/modprobe.d/blacklist-i2c-piix4.conf
sudo update-initramfs -u  # 更新 initramfs,确保黑名单在早期启动也生效

重启后 i2c-1 不再出现,SMBus timeout 日志消失。i2c-0 ~ i2c-8 的 Synopsys 控制器不受影响,因为它们由不同的驱动(dw_i2c)管理。


三、AMD GPU reset_method 写入失败

现象

复制代码
pci 0000:04:00.0: Unsupported reset method 'device_specific'
(udev-worker): 0000:04:00.0: /etc/udev/rules.d/99-vendor-reset.rules:1 Failed to write ATTR...reset_method="device_specific", ignoring: Invalid argument
amdgpu 0000:04:00.0: Unsupported reset method 'device_specific'

原因

PCIe 设备的 reset_method 决定了内核如何对该设备进行硬件重置(比如在驱动加载失败时重新初始化)。可选值取决于硬件支持:

  • bus --- 对整个 PCI 总线复位(最通用,几乎所有设备支持)
  • slot --- 对插槽复位(需要热插拔槽位)
  • func --- 对单一功能复位
  • device_specific --- 使用设备自己的方法(需要固件/驱动提供支持)

我们的 AMD GPU(Radeon Graphics,设备 ID 0x164c)只支持 bus,不支持 device_specific99-vendor-reset.rules 这个规则可能是之前某个调试或优化工具写的,把不兼容的方法写进去了。每次 GPU 枚举时 udev 都会尝试写入,失败后报错。

修复

bash 复制代码
# 验证哪些方法实际可用
sudo cat /sys/bus/pci/devices/0000:04:00.0/reset_method
# 输出: bus   ← 确认只有 bus 有效

# 修改规则
sudo tee /etc/udev/rules.d/99-vendor-reset.rules > /dev/null << 'EOF'
# AMD GPU (0x164c) reset method --- 使用 bus reset
ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x1002", ATTR{device}=="0x164c", ATTR{reset_method}="bus"
EOF

sudo udevadm control --reload-rules

四、LXC 网络桥接失败(拖慢启动 30 秒)

现象

复制代码
Failed to start lxc-net.service - LXC network bridge setup

systemd-analyze blame 显示 lxc.service 耗时 30.195s,是启动中最长的单项。

原因

lxc.service 的 Unit 定义里有 After=remote-fs.target,意思是"等远程文件系统都挂载好再启动"。而 remote-fs.target 要等所有的 NFS 挂载点都就绪。

我们的 /mnt/shared 是通过 NFS 从 192.168.31.82 挂载的网络目录。开机时网络(NetworkManager)还没完全建立连接,NFS 服务器也还没响应,mnt-shared.mount 就一直挂着等。lxc.service 被动等待,直到超时才继续。

检查依赖链:

bash 复制代码
systemctl show lxc.service --property=After,Requires
# After=network.target remote-fs.target ...
# Wants=lxc-net.service

本机实际上没有运行任何 LXC 容器(/var/lib/lxc/ 是空的),LXC 相关服务都是多余的负担。

修复

bash 复制代码
sudo systemctl disable --now lxc.service lxc-net.service lxc-monitord.service lxcfs.service

禁用后,lxc.service 不再挂起整个启动链,NFS 挂载变成了独立事件,不再阻塞 graphical.target。


五、k3s-agent 启动失败

现象

复制代码
Failed to start k3s-agent.service - Lightweight Kubernetes

原因

k3s-agent 是一个轻量级 Kubernetes 节点代理,它需要连接到主控制平面(server)才能正常工作。本机配置的是 agent 模式,但主集群服务器已经停用,agent 启动后连不上主节点,systemd 认为启动失败。

后续观察发现它其实没有真正"失败退出"------进程还在运行(PID 1779),只是在不断地重连重试,浪费了启动时间。

修复

bash 复制代码
sudo systemctl disable --now k3s-agent.service

等主集群恢复后再启用即可:sudo systemctl enable --now k3s-agent.service


六、NFS blkmapd 管道文件错误

现象

复制代码
blkmapd[1309]: open pipe file /run/rpc_pipefs/nfs/blocklayout failed: No such file or directory

原因

nfs-blkmap 是 pNFS(Parallel NFS)的 block layout mapping daemon。pNFS 是一种分布式文件系统协议,允许客户端直接从存储服务器读写数据块,绕过元数据服务器。这个 daemon 需要 /run/rpc_pipefs/nfs/blocklayout 这个管道文件,但它只在启用 pNFS 的场景下才有意义。

普通 NFSv4 挂载(我们用的就是 vers=4.2)不依赖 pNFS,这个服务完全无用。而且它的依赖 rpcbind 需要在启动早期就准备好,增加了不必要的初始化开销。

修复

bash 复制代码
sudo systemctl disable --now nfs-blkmap.service

七、libvirt 无用存储池

现象

复制代码
libvirtd: 无法打开目录 '/media/a1/Ventoy': 没有那个文件或目录
libvirtd: 自动启动化存储池 'Ventoy' 失败

原因

libvirt 有一个"自动发现存储池"的功能:当它检测到某个目录时,可能会自动创建一个 type='dir' 的存储池指向它。

Ventoy 是一个用来制作多系统启动 U盘的工具。之前我们插过 Ventoy U盘,系统自动将其挂载到 /media/a1/Ventoy,libvirt 扫描到了这个路径就创建了一个存储池。拔下 U盘后,路径不存在了,但 libvirt 的配置还留着,每次启动都尝试打开它 → 报错。

另外还发现了三个同样无用的空池:

  • a1 :指向 /home/a1(整个家目录被当成了存储池!列出所有文件和隐藏文件)
  • tmp :指向 /tmp
  • virtio-win :指向 /usr/share/virtio-win(存放 virtio 驱动 ISO,用于 Windows 虚拟机,本机没有 Windows VM)

这些池都没有绑定任何实际用途。

修复

bash 复制代码
for p in Ventoy a1 tmp virtio-win; do
  sudo virsh pool-destroy $p 2>/dev/null
  sudo virsh pool-undefine $p 2>/dev/null
done

pool-destroy 停用池(如果还在运行),pool-undefine 删除持久配置。注意:这只是删除 libvirt 的配置,不会删除任何实际数据。


八、initramfs resume UUID 警告

现象

复制代码
W: initramfs-tools configuration sets RESUME=UUID=a8a96227-3dab-4118-8b25-36ee13a20aa7
W: but no matching swap device is available

原因

Linux 的"休眠唤醒"(hibernate/suspend-to-disk)功能需要把内存内容写入 swap 分区,唤醒时再从同一个 swap 分区读回。这个配置记录在 /etc/initramfs-tools/conf.d/resume,内容是一个 UUID,指向某个 swap 设备。

之前我们手动在 /etc/fstab 里加了 /dev/zram0 none swap sw 0 0,initramfs-tools 检测到这个 swap 条目后自动生成了 resume UUID 配置。后来我们把 fstab 那行删掉了(改用 zramswap.service 动态管理 zram),但 resume 配置文件还留着,指向一个不存在的 UUID → 警告。

zram swap 是纯内存的压缩分区,不支持休眠(resume),所以这个配置本来就没有意义。

修复

bash 复制代码
sudo rm /etc/initramfs-tools/conf.d/resume
sudo update-initramfs -u

九、Samba 服务

现象

复制代码
664ms nmbd.service
181ms smbd.service
136ms winbind.service

原因

Samba 是 Linux 上的 SMB/CIFS 文件共享服务,用于和 Windows 机器共享文件。我们本机没有配置任何共享(/etc/samba/smb.conf 里的 [shared] 指向 /home/a1 但没实际使用),这些服务只是开机自启白等。

修复

bash 复制代码
sudo systemctl disable --now nmbd smbd winbind

ydotool 改为按需启动

ydotool 是鼠标键盘自动化工具(连点器依赖它)。原配置开机自启但 X session 未就绪时首次启动失败,5 秒后 systemd 自动重试成功。改为禁用开机自启,点连点器图标时脚本自动拉起 ydotoold:

bash 复制代码
# 禁用开机自启
systemctl --user disable --now ydotool.service
# 连点器脚本已更新:启动前先起 ydotoold
# /home/a1/.local/bin/clicker-launcher.sh

十、工具与产出

xiaoai-battery 电源管理工具

路径/home/a1/bin/xiaoai-battery

快捷方式~/桌面/XiaoXinAir-电源管理.desktop

控制原理

接口 路径 可调值 作用
platform_profile /sys/firmware/acpi/platform_profile low-power / balanced / performance ACPI 整体功耗策略,控制 CPU/TDP/风扇曲线
EPP /sys/devices/system/cpu/cpuN/cpufreq/energy_performance_preference power / default / performance 每核 CPU 调度倾向(AMD-pstate-EPP 驱动)
GPU DPM /sys/class/drm/card0/device/power_dpm_force_performance_level auto / low / middle / high AMDGPU 显卡性能级别

三个模式的具体含义:

模式 profile EPP GPU 适用场景
🚀 野兽 performance performance high 游戏、编译、渲染
⚖️ 均衡 balanced default auto 日常使用
🔋 安静 low-power power auto 办公、追剧、续航优先

Conservation Mode :写入 /sys/bus/platform/devices/VPC2004:00/conservation_mode。值为 1 时限制充电上限约 80%,减少电池循环次数,延长寿命。适合长期插电使用的场景。


十一、残留的无害报错

报错 深度原因 是否需要处理
ydotool.service 首次启动失败 已禁用开机自启,改为点连点器图标时按需启动 ydotoold 不需要
obexd evolution-source-registry 找不到 obexd(蓝牙文件传输)启动时尝试连接 Evolution 通讯录服务做同步,本机只装了基础库没装完整 evolution。尝试修复多次后放弃(需装额外包) 保留现状,无害
Bluetooth Opcode 0x2013 failed: -38 MediaTek MT7921 蓝牙芯片不支持 HCI_Vendor_Specific command 0x2013(读温度),驱动 probe 时发了一条芯片不认识的命令。已关闭 USB autosuspend/etc/modprobe.d/btusb.conf)减少此类噪音;蓝牙功能本身正常,Powered: yes 已关闭 autosuspend,报错不影响功能

十二、排查命令速查

bash 复制代码
# 查看本次启动的完整错误日志
sudo journalctl -b -p err --no-pager

# 查看启动耗时,哪些服务最慢
sudo systemd-analyze blame

# 看启动关键路径(找出卡住的那条链)
sudo systemd-analyze critical-chain graphical.target

# 看某个服务的具体耗时和依赖
sudo systemd-analyze critical-chain <service-name>

# 查看某个服务的详细日志
sudo journalctl -b -u <service-name> --no-pager -o verbose

# 查看当前 swap 状态
sudo swapon --show

# 查看当前性能模式
cat /sys/firmware/acpi/platform_profile
cat /sys/devices/system/cpu/cpu0/cpufreq/energy_performance_preference
cat /sys/class/drm/card0/device/power_dpm_force_performance_level
相关推荐
Titan20242 小时前
网络基础:传输层协议知识梳理
linux·服务器·网络
一叶龙洲2 小时前
Ubuntu从图标到卸载应用
linux·windows·ubuntu
爱吃提升2 小时前
VMware虚拟机迁移系统磁盘完整教程(VMware Workstation17)
linux·运维·服务器
2401_868534782 小时前
网规备考_5.4 防火墙及访问控制技术
linux·网络协议
wuminyu2 小时前
Linux内核线程调度与虚拟线程调度机制系统级深度剖析
java·linux·c语言·jvm·c++
诸葛李2 小时前
linux 配置
linux·运维·服务器
程序员老赵2 小时前
Docker 部署 Rocky Linux:轻松搭建 RHEL 兼容企业级基础镜像平台
linux·后端·docker
rest10244 小时前
对ebpf的理解(3)
linux
AR-26710-4 小时前
Linux Day1——环境搭建与基础指令
linux