记一次Linux GRUB修复

Posted by noHentai on Saturday, October 1, 2022

本文简单记录一次突发的Linux GRUB损坏,并从零学习修复。

起因

前几天上PT站的时候,突然发现挂着刷流量的盒子下线了。测试一番发现盒子上运行的服务均已下线,SSH也登不进去。

从服务商的网页后台重启机器同样没用,发工单询问客服被告知“GRUB损坏”,同时帮我把机器重启进入救援模式,剩下的要我自己动手修复。

什么是GRUB?

作为一名不折不扣的小白,自然先从“是什么”入手。

GRUB是Linux上默认自带的系统启动引导管理器,在开机的时候将Linux内核加载入内存以进行后续的系统启动流程,如果安装了多系统的话也是靠它来选择启动。

总而言之,它十分灵活、兼容性高,也因此它比较复杂,需要经过多个阶段来执行(通常可以在/boot/grub文件夹下一窥一二),并可能分别存储在硬盘的不同位置。稍有不慎就极有可能损坏GRUB,造成系统无法启动。

修复过程

GRUB的修复有两种常见的方法:一种是从救援模式手动启动系统,随后在系统中重新安装GRUB;另一种是在救援模式下挂载原系统各必要分区,随后直接chroot到原系统环境重新安装GRUB。

我盒子的系统是Debian 10,救援模式环境是服务商提供的GRML Linux Rescue Image。本次使用的是第二种方法。

首先进入救援模式,输入以下命令:

fsarchiver probe simple

这个命令会列出当前所有硬盘上的文件系统,这里以一个无RAID双硬盘为例:

root@debian /root % fsarchiver probe simple
[=====DEVICE=====] [==FILESYS==] [=====LABEL=====] [====SIZE====] [MAJ] [MIN]
[/dev/sda1       ] [ext3       ] [boot           ] [   256.00 MB] [  8] [  1]
[/dev/sda2       ] [reiserfs   ] [debian         ] [    16.00 GB] [  8] [  2]
[/dev/sda3       ] [ntfs       ] [winxp32        ] [    16.00 GB] [  8] [  3]
[/dev/sda4       ] [ext3       ] [data           ] [   898.56 GB] [  8] [  4]
[/dev/sdb1       ] [ext3       ] [boot           ] [   976.55 MB] [  8] [ 17]
[/dev/sdb2       ] [reiserfs   ] [gentoo         ] [    16.00 GB] [  8] [ 18]
[/dev/sdb3       ] [LVM2_member] [<unknown>      ] [   866.56 GB] [  8] [ 19]

可以从标签(Label)上很清楚的看到,Debian系统及其boot分区被安装在/dev/sda硬盘上。

那么接下来就很简单,只要挂载+重装GRUB即可。但由于我的盒子为了刷流量使用了软RAID 0(上面的Label里会各种显示unknown),不能直接挂载,所以这里需要多做一步。

mdadm -Asf && vgchange -ay   #忘了后面的vgchange -ay是否必要了,自行尝试

这一步是为了启动RAID来正常挂载。此时再使用上述fsarchiver命令,应该可以看到启用RAID后出现的/dev/md*分区,包括系统分区及boot分区。

接下来就是在救援模式下挂载原系统各分区了,这里假设/dev/md0是RAID启动后的系统分区:

root@sysresccd /root % mkdir /mnt/linux
root@sysresccd /root % mount /dev/md0 /mnt/linux
root@sysresccd /root % mount -o bind /proc /mnt/linux/proc
root@sysresccd /root % mount -o bind /dev /mnt/linux/dev
root@sysresccd /root % mount -o bind /sys /mnt/linux/sys
root@sysresccd /root % chroot /mnt/linux /bin/bash

使用chroot后就进入了和正常系统一样的shell环境下了。

这里注意,通常boot分区都与系统分区不同,所以到此为止实际上是没有挂载上boot分区的,可以利用ls命令查看/boot文件夹是否为空。

如果为空,那么同样需要挂载,这里假设/dev/md1是boot分区。

[root@sysresccd /]# ls -l /boot/
total 0
[root@sysresccd /]# mount /dev/md1 /boot/
[root@sysresccd /]# ls -l /boot/
-rw-r--r--. 1 root root   97567 2009-05-27 22:25 config-2.6.29.4-167.fc11.i586
drwxr-xr-x. 2 root root    1024 2009-11-14 18:57 grub
-rw-------. 1 root root 2944107 2009-06-14 11:08 initrd-2.6.29.4-167.fc11.i586.img
-rw-r--r--. 1 root root 1257178 2009-05-27 22:25 System.map-2.6.29.4-167.fc11.i586
-rwxr-xr-x. 1 root root 3035056 2009-05-27 22:25 vmlinuz-2.6.29.4-167.fc11.i586

可以看到/boot文件夹下有包括GRUB文件夹在内的一些文件,即成功挂载。

一切就绪,接下来一键重装GRUB即可。

dpkg-reconfigure grub-pc

注意:GRUB一般安装到与系统同硬盘,例如/dev/sda。如果你使用了RAID,那么就应该选中所有RAID包含的硬盘(/dev/sda、/dev/sdb、……),不要选择虚拟出来的/dev/md0等

GRUB重装完毕,退出chroot,卸载各分区,重启即可。

[root@sysresccd /]# exit
exit
root@sysresccd /root % umount /mnt/linux/{dev,proc,sys}
root@sysresccd /root % umount /mnt/linux/boot
root@sysresccd /root % umount /mnt/linux/

reboot

以上记录一次从零开始学习的GRUB修复,小白第一次,错误疏漏在所难免。但大体思路没问题,大家多加搜索应该就能顺利解决类似问题。