一次Arch滚挂记录

-
-
2024-05-15

0x01 序

晚上一次正常的更新系统途中kernel panic导致系统爆炸的分析与修复。

0x02 背景&症状

                   -`                    sa@archlinux 
                  .o+`                   ------------ 
                 `ooo/                   OS: Arch Linux x86_64 
                `+oooo:                  Host: ROG Strix G531GU 1.0 
               `+oooooo:                 Kernel: 6.8.1-arch1-1-lily 
               -+oooooo+:                Uptime: 14 hours 
             `/:-:++oooo+:               Packages: 1990 (pacman) 
            `/++++/+++++++:              Shell: zsh 5.9 
           `/++++++++++++++:             Resolution: 1920x1080 
          `/+++ooooooooooooo/`           DE: Plasma 6.0.4 
         ./ooosssso++osssssso+`          WM: KWin 
        .oossssso-````/ossssss+`         Theme: Breeze Light [Plasma], Breeze [GTK2/3] 
       -osssssso.      :ssssssso.        Icons: [Plasma], breeze [GTK2/3] 
      :osssssss/        osssso+++.       Terminal: konsole 
     /ossssssss/        +ssssooo/-       CPU: Intel i7-9750H (12) @ 4.500GHz 
   `/ossssso+/:-        -:/+osssso+-     GPU: NVIDIA GeForce GTX 1660 Ti Mobile 
  `+sso+:-`                 `.-/+oso:    GPU: Intel CoffeeLake-H GT2 [UHD Graphics 630] 
 `++:.                           `-/+/   Memory: 3686MiB / 15834MiB 
 .`                                 `/

滚系统时候图形卡死,CapsLock键闪烁,切不了TTY,典型的Kernel Panic,尝试SysRQ恢复没反应(好像开了?)。只能长按电源键重启,此时还没有意识到问题的严重性。

重启后黑屏,依旧无法进入TTY,猜测是更新了驱动有问题或者更新时候更到Xorg或者KDE桌面挂掉了,无法操作只能强制重启。

0x03 恢复控制权

尝试进入恢复模式,重新掌控电脑,我使用的System-Boot引导,启动按e编辑启动项。更改启动目标,行末加上内核参数systemd.unit=multi-user.target (相当于sysV的level 3)进入多用户模式。这时候多用户模式目标(Multi-user.target)会连接到Systemd的默认Target,在这个状态下系统不会启动图形系统(也就是Xorg SDDM KDE plasma都不会启动)最容易排查是那个部分炸掉了。

如果multi-user.target依旧进不去那就比较危险,可能是驱动不兼容炸的,只能进到更低的运行级别rescue.target(单用户模式相当于SysV的level 1)或者emergency.target 急救模式;如果能进去,就能得到足够的错误信息判断是图形系统炸了还是依赖的什么东西炸了。

很庆幸我进去了。

0x04 诊断与修复

还没登陆,启动过程就给我了几个红色信息

5月 14 21:25:08 archlinux systemd[1]: Listening on D-Bus System Message Bus Socket.
5月 14 21:25:08 archlinux systemd[1]: Listening on GnuPG network certificate management daemon for /etc/pacman.d/gnupg.
5月 14 21:25:08 archlinux systemd[1]: Starting Docker Socket for the API...
5月 14 21:25:08 archlinux systemd[1]: Listening on GnuPG cryptographic agent and passphrase cache (access for web browsers) for /etc/pacman.d/gnupg.
5月 14 21:25:08 archlinux systemd[1]: Listening on GnuPG cryptographic agent and passphrase cache (restricted) for /etc/pacman.d/gnupg.
5月 14 21:25:08 archlinux systemd[1]: Listening on GnuPG cryptographic agent (ssh-agent emulation) for /etc/pacman.d/gnupg.
5月 14 21:25:08 archlinux systemd[1]: Listening on GnuPG cryptographic agent and passphrase cache for /etc/pacman.d/gnupg.
5月 14 21:25:08 archlinux systemd[1]: Listening on GnuPG public key management service for /etc/pacman.d/gnupg.
5月 14 21:25:08 archlinux systemd[1]: Listening on libvirt legacy monolithic daemon socket.
5月 14 21:25:08 archlinux systemd[1]: Listening on libvirt legacy monolithic daemon admin socket.
5月 14 21:25:08 archlinux systemd[1]: Listening on libvirt legacy monolithic daemon read-only socket.
5月 14 21:25:08 archlinux systemd[1]: Listening on libvirt locking daemon socket.
5月 14 21:25:08 archlinux systemd[1]: Listening on libvirt logging daemon socket.
5月 14 21:25:08 archlinux systemd[1]: Starting D-Bus System Message Bus...
5月 14 21:25:08 archlinux systemd[1]: TPM2 PCR Barrier (Initialization) was skipped because of an unmet condition check (ConditionSecurity=measured-uki).
5月 14 21:25:08 archlinux systemd[1]: Listening on Docker Socket for the API.
5月 14 21:25:08 archlinux systemd[1]: Reached target Socket Units.
5月 14 21:25:08 archlinux dbus-broker-launch[654]: Invalid XML in /usr/share/dbus-1/system.d/org.kde.kf6auth.conf +1: no element found
5月 14 21:25:08 archlinux dbus-broker-launch[654]: ERROR run @ ../dbus-broker-36/src/launch/main.c +152: Return code 1
5月 14 21:25:08 archlinux dbus-broker-launch[654]:       main @ ../dbus-broker-36/src/launch/main.c +178
5月 14 21:25:08 archlinux dbus-broker-launch[654]: Exiting due to fatal error: -131
5月 14 21:25:08 archlinux systemd[1]: dbus-broker.service: Main process exited, code=exited, status=1/FAILURE
5月 14 21:25:08 archlinux systemd[1]: dbus-broker.service: Failed with result 'exit-code'.
5月 14 21:25:08 archlinux systemd[1]: Failed to start D-Bus System Message Bus.

看上去好像DBus炸了,可能因为更新了一半导致的。我尝试重新更新系统,但是NetworkManager没有启动,没有网络。

我尝试启动nm得到

 archlinux systemd[1]: Dependency failed for Network Manager. 
 archlinux systemd[1]: NetworkManager.service: Job  NetworkManager.service/start failed with result 'dependency'.


因为依赖不满足,启动失败。好像启动nm依赖DBus,但DBus已经炸了,回去查看DBus的错误

 archlinux dbus-broker-launch[654]: Invalid XML in /usr/share/dbus-1/system.d/org.kde.kf6auth.conf +1: no element found 
 archlinux dbus-broker-launch[654]: ERROR run @ ../dbus-broker-36/src/launch/main.c +152: Return code 1 
 archlinux dbus-broker-launch[654]:       main @ ../dbus-broker-36/src/launch/main.c +178 
 archlinux dbus-broker-launch[654]: Exiting due to fatal error: -131 
 archlinux systemd[1]: dbus-broker.service: Main process exited, code=exited, status=1/FAILURE 
 archlinux systemd[1]: dbus-broker.service: Failed with result 'exit-code'. 
 archlinux systemd[1]: Failed to start D-Bus System Message Bus.



由于dbus-broker主进程退出导致的DBus启动失败。

再往上看由于无效的XML语法在/usr/share/dbus-1/system.d/org.kde.kf6auth.conf文件,没找到该有的元素

我cd进去/usr/share/dbus-1/system.d/查看只有org.kde.kf5auth.conf,没有6。

打开org.kde.kf5auth.conf看看:

<!DOCTYPE busconfig PUBLIC
 "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<!-- Allow anyone to call into the service - we'll reject callers using Polkit -->
  <policy context="default">
    <allow send_interface="org.kde.kf5auth"/>
    <allow receive_sender="org.kde.kf5auth"/>
    <allow receive_interface="org.kde.kf5auth"/>
  </policy>
</busconfig>

看上去不是复杂的文件,像是dbus和Plasma接口的配置文件,那么既然更新了Plasma 6,配置也应该是6,接口名一般也不会有太大的变化。

于是我cp org.kde.kf5auth.conf org.kde.kf6auth.conf,把里面的5都改成6。重启DBus!

得到:

archlinux systemd[1]: Starting D-Bus System Message Bus... 
 archlinux dbus-broker-launch[1224]: Invalid XML in /usr/share/dbus-1/system.d/org.kde.ktexteditor6.katetextbuffer.conf +1: no element found 
 archlinux dbus-broker-launch[1224]: ERROR run @ ../dbus-broker-36/src/launch/main.c +152: Return code 1 
 archlinux dbus-broker-launch[1224]:       main @ ../dbus-broker-36/src/launch/main.c +178 
 archlinux dbus-broker-launch[1224]: Exiting due to fatal error: -131 
 archlinux systemd[1]: dbus-broker.service: Main process exited, code=exited, status=1/FAILURE 
 archlinux systemd[1]: dbus-broker.service: Failed with result 'exit-code'. 
 archlinux systemd[1]: Failed to start D-Bus System Message Bus.



又变成org.kde.ktexteditor6.katetextbuffer.conf了,如法炮制,重启!

这次进到TTY没有红色了,看一眼D-Bus,启动了,没有什么大问题。

尝试启动SDDM进入桌面

得到:

 archlinux systemd[1]: Started Simple Desktop Display Manager. 
 archlinux sddm[867]: Initializing... 
 archlinux sddm[867]: Starting... 
 archlinux sddm[867]: Logind interface found 
 archlinux sddm[867]: Adding new display... 
 archlinux sddm[867]: Loaded empty theme configuration 
 archlinux sddm[867]: Xauthority path: "/run/sddm/xauth_hvJEhW" 
 archlinux sddm[867]: Using VT 2 
 archlinux sddm[867]: Display server starting... 
 archlinux sddm[867]: Writing cookie to "/run/sddm/xauth_hvJEhW" 
 archlinux sddm[867]: Running: /usr/bin/X -nolisten tcp -background none -seat seat0 vt2 -auth /run/sddm/xauth_hvJEhW -noreset -displayfd 16 
 archlinux sddm[867]: Failed to read display number from pipe 
 archlinux sddm[867]: Display server stopping... 
 archlinux sddm[867]: Attempt 1 starting the Display server on vt 2 failed 
 archlinux sddm[867]: Display server starting... 
 archlinux sddm[867]: Writing cookie to "/run/sddm/xauth_hvJEhW" 
 archlinux sddm[867]: Running: /usr/bin/X -nolisten tcp -background none -seat seat0 vt2 -auth /run/sddm/xauth_hvJEhW -noreset -displayfd 16 
 archlinux sddm[867]: Failed to read display number from pipe 
 archlinux sddm[867]: Display server stopping... 
 archlinux sddm[867]: Attempt 2 starting the Display server on vt 2 failed 
 archlinux sddm[867]: Display server starting... 
 archlinux sddm[867]: Writing cookie to "/run/sddm/xauth_hvJEhW" 
 archlinux sddm[867]: Running: /usr/bin/X -nolisten tcp -background none -seat seat0 vt2 -auth /run/sddm/xauth_hvJEhW -noreset -displayfd 16 
 archlinux sddm[867]: Failed to read display number from pipe 
 archlinux sddm[867]: Display server stopping... 
 archlinux sddm[867]: Attempt 3 starting the Display server on vt 2 failed 
 archlinux sddm[867]: Could not start Display server on vt 2 
 archlinux sddm[867]: Signal received: SIGTERM



X11还是炸的sddm拉不起来,错误的意思大概是X11因为不能从管道中读取显示器编号而启动失败。

我删除了/etc/X11/*.conf/etc/X11/conf.d/*.conf但还是无效(这在遇到x11不能启动的情况经常有效,删除conf文件记得备份)。

查看日志发现Optimus-Manager也炸了,这块和硬件相关、电源策略相关我就不了解了,先禁用optimus-manager

我这里有个旧病就是独显(Nvida)会被当作i2c设备,一启动图形就死机,解决方法是禁用i2c_nvidia_gpu模块

而且不能用BBswitch,通过BBswitch关闭显卡电源会因为电源状态错误死机,解决方法就是不用BBswitch

有时间单开一篇写写

刚才更新的时候有很多kde的包在更新,我怀疑是不完全更新导致的,于是我使用pacman -Qkk 检查软件包状态

结果查到大量如下内容

...
ldconfig: File /usr/lib/libKF6UnitConversion.so is empty, not checked. 
ldconfig: File /usr/lib/libKF6PeopleWidgets.so is empty, not checked. 
ldconfig: File /usr/lib/libQuickChartsControls.so is empty, not checked. 
error: error while reading file /var/lib/pacman/local/gupnp-dlna-0.10.5+4+gc947eed-2/mtree: Unrecognized archive format
error: error while reading file /var/lib/pacman/local/gvfs-1.46.1-1/mtree: Unrecognized archive format
...

ldconfig: File  /path/to/file is empty, not checked 意思是pacman的文件追踪器与文件系统中实际的文件不对应,当追踪器与实际不符时pacman不会覆盖与数据库不一致的文件,如果是空就会跳过检查。所以强制更新这些软件包不奏效因为不一致的文件已经跳过检查了。对此的解决方法是pacman -Qkk 检查有问题的包使用pacman --overwrite参数强制覆盖不匹配的文件

error: error while reading file /path/to/mtree: Unrecognized archive format意味着pacman的数据库已经损坏,不能反应这些包的文件结构,这时pacman -Qnq 也不会显示损坏的软件包。这通常是文件系统出现大规模的严重错误、磁盘损坏等导致的。

先修复数据库使用pacman --dbonly参数

pacman --dbonly -S <all packages with broken mtrees>

可以使用

LC_ALL=C pacman -Qkk 2>/dev/null | sed '/no mtree/!d; s/:.*//g' |pacman --dbonly -S -

来检查所有软件包然后修复数据库。

由于错误的软件包太多了(Qkk检查出900多个有问题的包)我决定重新安装所有软件包

sudo pacman -Syu --overwrite ‘*’ $(pacman -Qnq)

重新安装1989个包(我都不知道居然有这么多,一直以为就900多个)

经过漫长的等待之后终于滚完了。然后重新启动!

插电!开机!直接进入sddm。成功啦!

0x05 跋

Panic时候用不了SysRq,检查一下是不是开着

archlinux# cat /proc/sys/kernel/sysrq 
16

16是只允许sync同步磁盘(这是arch 的默认值吗?我记得我开的是1)

开起来!


小知识:

什么是SysRq

神奇的 SysRq 键是 Linux 内核可以理解的组合键,它允许用户执行各种低级命令,无论系统状态如何。它通常用于从冻结中恢复,或在不损坏文件系统的情况下重新启动计算机。

怎么开启SysRq?

如果只是临时更改 SysRq 的值,只需要将新的值写入到 /proc/sys/kernel/sysrq 中去

echo "1" |sudo tee /proc/sys/kernel/sysrq

或者通过 sysctl 来进行设置sysctl -w kernel.sysrq=1

如果需要每次启动时都自动修改SysRq的值,则需要修改配置文件

echo "kernel.sysrq = 1"|sudo tee -a /etc/sysctl.conf

怎么用SysRq?

SysRq 键在 QWERT 键盘上与 PrtSc 同键,通过按下 ALT+SysRq+<command key> 可以直接向linux kernel发送预设的系统操作指令。

R-E-I-S-U-B:安全重启系统

这套组合键大致相当于reboot命令:

  • ALT+SysRq+R:unRaw – 把键盘设置为 XLATE 模式,使按键可以穿透 x server 捕捉传递给内核
  • ALT+SysRq+E:tErminate – 向除 init 外进程发送 SIGTERM 信号,让其自行结束. 这一步推荐等待30秒让进程有足够的时间进行收尾的工作。
  • ALT+SysRq+I:kIll - 向除 init 以外所有进程发送 SIGKILL 信号,强制结束进程. 这一步推荐等待10秒,保证所有进程都退出了
  • ALT+SysRq+S:Sync – 同步缓冲区数据到硬盘,避免数据丢失. 这一步在能看到输出的情况下等到"Emergency Sync complete" 后再做后续动作,否则推荐等待10秒
  • ALT+SysRq+U:Unmount – 将所有已经挂载的文件系统 重新挂载为只读. 该操作通常也有一定延时,请等到"Emergency Remount complete" 出现过后再进行后续操作,否则推荐等待10秒
  • ALT+SysRq+B:reBoot - 立即重启计算机

恢复系统挂起

若仅仅是因为资源消耗过量引起系统挂起就重启系统显然是不好的,我们可以尝试通过回收一些资源的方式来回复系统挂起。

SysRq中用来结束进程的command-key包括 E-I-K-F,其中:

  • ALT+SysRq+E 和 I 太凶残,它会杀掉除了 init 外的所有进程,属于杀敌一千自损八百的操作。因此在一般情况下不会轻易使用
  • ALT+SysRq+F 则是利用 OOM-Kiler选择一个进程来结束,对于由于内存不足引起的挂起比较有效,但有时候OOMKiller也可能会误判杀掉一些长期运行的后台程序。
  • ALT+SysRq+K 杀掉与当前控制台有关的进程组,比较推荐用这种方法回复系统

此外,若系统挂起是由于实时任务消耗太多CPU引起的,则可以通过 N 来降低实时任务运行的优先级来缓解挂起症状。

SysRq数字与功能对应关系:

0完全禁用sysrq 
1允许所有的sysrq功能 
2允许控制终端日志级别 
4允许控制键盘输入类型(SAK,unraw) 
8允许调试进程dump 
16允许执行sync命令 
32允许重新挂载文件系统为只读 
64允许发送信号给进程(term,kill,oom-kill) 
128允许重启/关机 
256允许调整实时任务的优先级 
SysRq数字与功能对应关系

 

 

 

 

 

“您的支持是我持续分享的动力”

微信收款码
微信
支付宝收款码
支付宝

目录