Arch Linux + GNOME在常规Pacman升级滾挂后的解决方案
问题描述
最近刚休假结束,开始上班的时候脑子还不太清醒,加上GNOME 45的习惯性crash,用了快两年、从来没出过大问题的Arch今天撂挑子了,由于是公司电脑必须硬着头皮解决,不过好在经过一下午的折腾顺利救活了。
具体情况是这样的:
- Pacman更新时间并没有隔太久,距离上一次
-Syyu
也就半个月,不过本次更新涉及到内核等多个重要的包 - 我是在办公途中准备重启一下电脑,看一下VSCode的ssh remote插件为啥抽风无法连接算法服务器,所以想着关机之前更新一波Pacman。当时电脑运行并不卡顿,进程不多,我就顺手
pacman -Syyu
了。 - 在进行到内核编译与initram-fs builds时,GUI突然崩了,直接导致了GNOME注销重启图形界面(GDM3我谢谢你啊),但是我不确定之前的
pacman -Syyu
跑完了没,毕竟桌面是桌面,arch是arch,系统本身没有重启。 - 我当时很放心地等了三五分钟,而且没有进行其他
pacman
操作来二次验证(毕竟平时var/lib/pacman/db.lck
还会给你把把关),就把电脑关机吃午饭去了。结果回来一开机,initram-linux.img丢了,一个黑屏直接无限循环了,这肯定就是内核更新出问题了,bootloader检测不到对应的引导文件。
# 内核更新失败,initramfs丢失的合影留念
EFI stub: ERROR: Failed to open file: initramfs-linux.img
EFI stub: ERROR: Failed to load initrd: 0×800000000000000e
EFI stub: ERROR: efi_main() failed!
Failed to execute Arch Linux (linux) (vmlinuz-linux): Not Found
但是作为Arch用户,遇到这样的问题首先要稳住心态不能慌。BBS玩家社区肯定有不少解决方案,慢慢自己搜索,加上和同事们的讨论,一步一步来还是很好差不多可以解决的。
思路分析
其实解决方法上来看还是那几个经典步骤:
- Live iso boot (从U盘启动一个临时的安装系统)
- Mount (把硬盘和对应分区挂在在临时系统下,这一部分相对麻烦,因为有些人会涉及到硬盘加密,LVM组,不同的bootloader的挂载点不同等问题,我下面会说)
- 进入chroot
- 具体问题具体分析,比如
sudo mkinicpio -P
或者sudo pacman -S linux
- 手动更新bootloader (有的情况不一定需要)
成功案例
这里先贴几个网上找到的救滾挂我觉得不错的帖子,进入chroot之前的情况没有我的这么复杂:
- 最经典的:Arch Linux系统修复指南
- Grub用户:archlinux通过arch-chroot分区修复引导2023
- 分区不复杂用户:使用 Chroot 恢复损坏的 Linux 安装
- 大致思路:用 Arch Live 修 Arch 的某些姿势
此处再加上一些其他外网的一些资源:
- Arch官方chroot文档
- 超级推荐:EndeavourOS官方arch-chroot文档
- 油管视频:How to Chroot into Arch Linux with Live USB | Fix & Install Packages 搭配着 Fix Arch Linux Boot with arch-chroot 一起看,大致思路是差不多的
动手解决
在动手之前,你需要确定几个东西,不能盲目按照之前提到过的大致思路开始:
- 你的linux系统是怎么分区,怎么挂载的?只有一个
/
?还是root
,home
,boot
分得很清楚? - 你的bootloader是什么?grub还是systemd-boot,还是别的?不同的bootloader在
/mnt/root
下的挂载点不同,一定要看清楚 - 你用的是原Arch,还是魔改Manjaro,还是类原生的EndeavourOS?
确定了以上这些问题之后,就可以按照我下面的步骤开始了 😃
Live USB Boot
利用U盘进入临时系统这部分就不多赘述了,大致推荐一下做系统盘的软件:
- Rufus + 使用教程: Rufus 创建 Linux 安装启动U盘
- 个人强烈推荐:Ventoy + 使用教程 Ventoy制作Linux、Windows系统多合一启动U盘教程 + 官方使用文档
自己在BIOS中设置一下UEFI顺序,进入live iso系统,和初次装机时候步骤一样,等到root@archiso ~ #
就可以了
到了这里我有个建议,很多人可能要开始折腾WIFI联网了,我觉得直接找个连着WIFI的手机,用USB线连接电脑,在手机上打开数据Ethernet(就是让手机提供网线),让电脑直接通过手机数据线联网,能剩下很多麻烦的步骤。
挂载分区
如果你的硬盘挂载的方式很简单,就是/
和/boot
,那么直接按照前面几个教程里的直接mount
。此处注意一下,由于是live iso,我不需要加sudo
,如果你需要权限的话自己分情况判断。
fdisk -l #查看分区情况,找到你的root和其他重要的分区
mount /dev/XXX /mnt #挂载root分区,注意XXX 调整为你的linux具体分区
先挂root
,如果你的/boot
不在/root
下,手动继续挂下。这里注意一下你的bootloader,看下EndeavourOS官方arch-chroot文档里建议的boot
挂载点:
mount /dev/XXX /mnt/boot/ #区分下bootloader,systemd-boot挂在/mnt/boot 下就好
mount /dev/XXX /mnt/boot/EFI #grub应该是要挂载 /mnt/boot/EFI 下,不建议挂在 /mnt/efi下,啥用没有
我个人的情况比较复杂,所以这篇帖子有特殊的警示意义:
- 首先硬盘分成了五个区,分别挂在LVM组下的
/
,/home
,/docker
, 还有非LVM的普通分区/swap
和EPS服务/boot
- LVM组里的三个volumes被LUKS加密了
- 所以我的思路是:解密硬盘 -> 激活LVM分区 -> 把需要的LVM volume挂在
/mnt
下 -> 进入arch-chroot /mnt
开始挂载(记得把我的的xxx都修改成你对应的硬件和挂载点名字):fdisk -l #查看加密分区 cryptsetup open /dev/XXXXX/ YYYYY #把XXXXX改成你对应的分区名字,YYYYY改成解密的分区名字,比如root lvscan #解密后能自动扫描到LVM group了 vgchange -ay /dev/your_lv_group_name #把your_lv_group_name改成你看到的名字,例如 /dev/vg7000 lsblk #再次查看一下分区情况
mount /dev/vgxxx/root /mnt mount /dev/vgxxx/home /mnt/home #其实没必要,我不过就随手试一下 mount /dev/nvmexxx /mnt/boot #因为我的bootloader是systemd-boot, 如果你的是grub需要自己试一下是不是/mnt/boot/efi
如果显示没有某个mount point
导致无法正常挂载,请检查一波:
- 你是否将
root
或者是包含root
的分区挂载到了/mnt
- 你的bootloader是否要求特定的挂载点,例如grub貌似要求挂载
/mnt/boot/EFI
, systemd-boot要求挂载/mnt/boot
(我尝试挂载/mnt/efi
不过没啥用) - 万不得已,手动
mkdir /mnt/xxx
来一波,基本上把root和boot都挂载上了之后,就可以准备下一步了
进入chroot
当所有挂载点没问题,就可以进入chroot来修复受损的系统文件了:
arch-chroot /mnt
当然,到了这一步我这篇文章就无法继续参考了,因为每个人滾挂的原因各不相同,具体是什么还是看一下pacman log:
tail -n 150 /var/log/pacman.log | less
这里我可以给出一下我的一些通用的个人见解:
- 如果是像我用pacman更新内核时突然炸了,那么首要做的肯定是重装一下linux内核
pacman -S linux
或者linux-lts
,linux-zen
- 如果是装完内核了,但是initramfs不知道出什么问题了,可以尝试一波
mkinicpio -P
如果是其他原因导致引导丢了,可以看一下下一步手动更新bootloader (重装也是一个道理,不过只有grub可以,systemd-boot好像不行)。
手动更新bootloader
救完系统后,最好手动更新一下系统的启动引导,争取一次性点亮。
由于我的工作电脑是用systemd-boot,所以更新eps的代码很简单:
bootctl update #更新启动引导
exit #退出chroot
shutdown now #退出chroot,关机,拔U盘,再开机
这里我也顺便贴一下别的地方找到的grub的更新代码(虽然大家应该相当熟悉了):
#记得该代码在chroot里执行
grub-mkconfig -o /boot/grub/grub.cfg
然后就可以退出临时系统了,拔掉U盘,如果可以正常开机说明系统就救活了。
当然一次性点不亮很正常,我自己由于也是第一次摸索着旧系统,Linux操作水平只能说是一般般不是特别精通,比如网上大多数的救滚是用grub为bootloader的,我把/dev/我的boot分区
挂在了/mnt/boot/EFI
,开机后引导分区彻底没了,后来又挂在/mnt/efi
试了好久也没成,最后挂在/mnt/boot/
然后重复上面更新内核、更新引导,就成功点亮了。
所以总结起来就是,一定不要太慌,要注意细节再进行下一步操作。
有什么问题可以在评论区留言,我不定期会抽空上线查看。
该教程未经本人允许请勿转载到其他平台,多谢 😃