记一次 Arch Linux 启动时进入 emergency mode 但无法使用键盘的问题排查经历 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Arch Linux
Mantext1989
V2EX    Arch

记一次 Arch Linux 启动时进入 emergency mode 但无法使用键盘的问题排查经历

  •  1
     
  •   Mantext1989 1 月 17 日 789 次点击
    这是一个创建于 50 天前的主题,其中的信息可能已经有所发展或是发生改变。

    周五晚上准备启动 Arch 学习一会就睡觉时,突然进了 emergency mode ,报的错是:

    [FAILED] Failed to mount /efi/ See 'systemctl status efi.mount' for details [DEPEND] Dependency failed for Local File Systems 

    Shell 的最下方写着:

    You are in emergency mode. After logging in, type "journalctl -xb" to view system logs, "systemctl reboot" to reboot, or "exit" to continue bootup. Enter root password for system maintenance (Or press Control-D to continue): _ 

    好吧,正准备输密码查日志找原因呢,突然发现键盘无论怎么按都没反应,甚至背光都没亮。我就纳闷了,就这么巧,系统崩了键盘也坏了?

    遂从一旁掏出另一把键盘插上,发现依旧没有反应。这下伤脑筋了,没法看日志怎么排错?只能靠回想上次关机前做了什么事了。

    嗯,上次启动电脑我用的是 Windows ,关机的时候好像 Windows 更新了,难道是 Windows 更新导致 efi 分区的 UUID 产生了临时性的变化?先重启进 Windows 让它更新完再说。

    重新进入 Windows ,果然弹出了正在更新的提示,顿时在心里把巨硬骂了个狗血淋头。更新完毕,心想着可算搞好了,再次重启进入 Arch 。

    哦豁,还是完全一模一样的报错,看来是错怪 Windows 了,默默地向巨硬全体开发者道歉。

    好了,那这下该怎么办?上网一顿搜,发现既然提示是Dependency failed for Local File Systems,那有没有可能是 fstab 被什么东西暗中修改了?先看看再说。

    遂启动 Windows ,掏出 U 盘装上 Arch 的安装镜像,进 live ,挂载、chroot 到 Arch 。blkid,记下 UUID ,再查看 fstab ,发现这也没变化呀。

    此时已是十二点过半,头开始发晕了。不管了,先解决键盘用不了的问题,在 emergency mode 看看日志吧,也许这样能快点找到原因呢。

    照着“arch linux emergency mode keyboard not working”的关键字,又是上网一顿搜,发现还真有人遇到过相同的问题,原因是 initramfs 中没有包含 USB 键盘的模块,导致 emergency mode 就没有键盘驱动。

    如何解决?在 /etc/mkinitcpio.conf中的MODULES=()的括号中添加以下字样:

    xhci_pci xhci_hcd usbhid hid_generic 

    然后执行

    mkinitcpio -P 

    来重新生成 initramfs 。

    再一次进入 live ,修改、输命令,虽然时间已过午夜 1 点,但心想着这下能用键盘了,疲倦中还是带着点喜悦的。

    再次重启进 Arch ,结果傻眼了,键盘还是用不了。

    我有点手足无措了,这咋办?再仔细回想一下,上次用 Arch 的时候发生了什么?好像执行了一次 pacman -Syu,可能更新了内核?因为我电脑上同时装了 Windows 和 Arch Linux ,用 Windows 又要开着 Secure Boot ,所以之前在 Arch 上也折腾过 Secure Boot 。当时用的是 shim + UKI 的方案,每次内核或者微码更新都需要重新生成并签名 UKI ,所以我每次执行完 pacman -Syu,都会手动执行一次生成 UKI 并签名的步骤。难道是上次我忘了做这一步?先试试再说。

    进 live 、执行脚本、重启。再次进入 Arch ,问题依旧。

    时间已经来到了凌晨两点,我开始有点烦躁。算了,先躺床上睡觉,明天起床再搞吧。

    躺在床上,脑子里却一直放映着终端的画面,翻来覆去都睡不着。妈的,到底怎么回事?

    心情如此烦躁,最好还是找个人倾诉一下。可是都这个点了,谁还醒着啊。不对,就算是白天我也没朋友可聊这个呀。

    由于无人可聊,我只好打开了 ChatGPT ,一边在心里感叹自己的悲凉,一边默默地把自己的遭遇一股脑地输入进对话框。呼,说出来确实感觉好多了。

    也许是我情绪上头想要发泄一通,我事无巨细地向 ChatGPT 描述了这件事的一切经过。ChatGPT 的回复给了我一个新的突破点:

    你“修复的系统”和“真正被启动的启动环境”,是不是不是同一个东西?换句话说: 你现在启动的,是不是根本不是你刚刚修好的那套 initramfs ?

    ChatGPT ,我的超人。

    这下又有事可做了。立马弹射下床、开机进 live 、 chroot一气呵成,先看看现在系统里的内核版本吧:

    ls /usr/lib/modules 

    显示是6.18.5-arch1-1

    再来看看正在启动的 UKI 里的内核:

    uname -r 

    显示是6.18.2-arch2-1

    顿时感觉自己像个傻子,折腾到大半夜没有一步是在点子上的,哈哈。

    不管怎么说,可算是找到原因了。

    由于 UKI 里打包的内核版本不对,导致每次开机时,initramfs 都尝试去加载 /usr/lib/modules/6.18.2-arch2-1/,但系统里只有/usr/lib/modules/6.18.5-arch1-1/,自然什么都加载不到。

    所以无论再怎么构建 initramfs ,系统都用不上,这也就解释了为什么即使在 mkinitcpio.conf 中添加了模块依旧无法使用键盘,同样也可以解释为什么进不了系统。

    在重建 initramfs 、用重建的 initramfs 生成 UKI 并签名之后,再次重启,终于顺利进入系统。此时已是凌晨三点,可算能睡觉了。

    不过,既然每次内核/微码更新都有可能会踩这个坑,那预防还是要做好的。

    第二天起床,我给 pacman 添加了钩子,让它每次升级完内核/微码都执行一遍上述的过程。具体操作如下:

    1. /etc/pacman.d/hooks下新建文件95-uki-secureboot.hook
    [Trigger] Type = Package Operation = Install Operation = Upgrade Target = linux Target = linux-lts Target = intel-ucode Target = amd-ucode Target = systemd [Action] Description = Rebuild and sign UKI for Secure Boot When = PostTransaction Exec = /usr/local/sbin/build_uki.sh NeedsTargets 
    1. /usr/local/sbin下新建脚本build_uki.sh
    #!/bin/bash set -euo pipefail # 更新后的内核版本号 expected_kernel="$(basename "$(ls -d /usr/lib/modules/* | sort -V | tail -n1)")" # 重建 initramfs mkinitcpio -P # 将更新后的内核和微码整合 cat /boot/intel-ucode.img /boot/initramfs-linux.img > /tmp/combined_initrd.img # 一些变量 osrel_offs=$(objdump -h "/usr/lib/systemd/boot/efi/linuxx64.efi.stub" | awk 'NF==7 {size=strtonum("0x"$3); offset=strtonum("0x"$4)} END {print size + offset}') cmdline_offs=$((osrel_offs + $(stat -Lc%s "/usr/lib/os-release"))) splash_offs=$((cmdline_offs + $(stat -Lc%s "/etc/kernel/cmdline"))) linux_offs=$((splash_offs + $(stat -Lc%s "/usr/share/systemd/bootctl/splash-arch.bmp"))) initrd_offs=$((linux_offs + $(stat -Lc%s "/boot/vmlinuz-linux"))) # 重新包装内核并生成 UKI objcopy \ --add-section .osrel="/usr/lib/os-release" --change-section-vma .osrel=$(printf 0x%x $osrel_offs) \ --add-section .cmdline="/etc/kernel/cmdline" \ --change-section-vma .cmdline=$(printf 0x%x $cmdline_offs) \ --add-section .splash="/usr/share/systemd/bootctl/splash-arch.bmp" \ --change-section-vma .splash=$(printf 0x%x $splash_offs) \ --add-section .linux="/boot/vmlinuz-linux" \ --change-section-vma .linux=$(printf 0x%x $linux_offs) \ --add-section .initrd="/tmp/combined_initrd.img" \ --change-section-vma .initrd=$(printf 0x%x $initrd_offs) \ "/usr/lib/systemd/boot/efi/linuxx64.efi.stub" "linux.efi" # 重新签名 UKI sbsign --key /root/MOK.key --cert /root/MOK.crt --output /efi/EFI/shim/grubx64.efi linux.efi # 校验 UKI 内核版本,以防未使用更新后的内核启动导致进入 emergency mode echo "Starting to verify kernel version from UKI" objcopy --dump-section .linux=/tmp/uki-vmlinuz "/efi/EFI/shim/grubx64.efi" actual_kernel="$( strings /tmp/uki-vmlinuz | grep -m1 -oE '[0-9]+\.[0-9]+\.[0-9]+-[^ ]+' )" if [[ -z "$actual_kernel" ]]; then echo "ERROR: Failed to extract kernel version from UKI" exit 1 fi if [[ "$actual_kernel" != "$expected_kernel" ]]; then echo "ERROR: UKI kernel mismatch" echo "Expected: $expected_kernel" echo "Actual: $actual_kernel" exit 1 fi echo "UKI kernel version verified: $actual_kernel" 

    在这里把这次经历 po 出来,希望能给遇到类似情况的人做个参考。

    感谢 在 Arch Linux 中配置安全启动( Secure Boot) 一文的作者,以及在各个论坛上参与讨论、分享经验的人们。

    第 1 条附言    1 月 19 日

    Edit:

    又折腾出问题来了,这次是

    Malformed security header Failed to read header: Invalid Parameter Failed to load image: Invalid Prarameter start_image() returned Invalid Parameter, falling back to default loader 

    看来手搓 UKI 的稳定性还是有待提高,也就不折腾这个,干脆用 ukify 得了。

    以下是使用 ukify 的 build_uki.sh

    #!/bin/bash # 更新后的内核版本号 expected_kernel="$(basename "$(ls -d /usr/lib/modules/* | sort -V | tail -n1)")" # 重建 initramfs mkinitcpio -P # 重新包装内核并生成 UKI # 使用 ukify ukify build \ --linux /boot/vmlinuz-linux \ --initrd /boot/intel-ucode.img \ --initrd /boot/initramfs-linux.img \ --cmdline @/etc/kernel/cmdline \ --output /tmp/linux.efi # 重新签名 UKI sbsign --key /root/MOK.key --cert /root/MOK.crt --output /efi/EFI/Boot/grubx64.efi /tmp/linux.efi # 校验 UKI 内核版本,以防未使用更新后的内核启动导致进入 emergency mode echo "Starting to verify kernel version from UKI" objcopy --dump-section .linux=/tmp/uki-vmlinuz "/efi/EFI/Boot/grubx64.efi" actual_kernel="$( strings /tmp/uki-vmlinuz | grep -m1 -oE '[0-9]+\.[0-9]+\.[0-9]+-[^ ]+' )" if [[ -z "$actual_kernel" ]]; then echo "ERROR: Failed to extract kernel version from UKI" exit 1 fi if [[ "$actual_kernel" != "$expected_kenel" ]]; then echo "ERROR: UKI kernel mismatch" echo "Expected: $expected_kernel" echo "Actual: $actual_kernel" exit 1 fi echo "UKI kernel version verified: $actual_kernel" 
    1 条回复    2026-01-17 19:43:10 +08:00
    momocraft
        1
    momocraft  
       1 月 17 日
    还好我不用 secure boot
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5677 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 08:12 PVG 16:12 LAX 01:12 JFK 04:12
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86