日期 :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 串行 + 并行混合调度,任何一条长链路上有服务失败或超时,整条链路都会跟着卡住。排查顺序:
systemd-analyze blame--- 看哪些服务耗时最长systemd-analyze critical-chain graphical.target--- 看启动关键路径,找出卡在哪个环节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_specific。99-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