今天 brtfs 崩溃了。。。。原因是 APT 锁住了,我强制重启,然后文件系统就崩了(进入 initramfs 模式)。于是尝试修复文件系统。
分以下几个部份说明:
一、开机出现 grub rescue 指令模式
二、开机出现grub指令模式
三、可见到grub menu,但无法开机
四、开机进入initramfs模式
五、处理grub的异常状况
第5是前面四种错误处理完后,进入系统该接著处理的事情。不然下次开机仍会发生一样的问题。
解决方法一般是3步:
启动盘开机,chroot 到硬盘系统,执行 update-grub.
一、开机出现 grub rescue 指令模式
假如看到grub rescue,表示mbr (master boot record)的资料,完全对应不上磁盘的状况,所以无法辨别系统的所有分区,更不用说连grub menu都无法读入。所以,处理的方法就是帮他找到grub的设置。
grub rescue>ls
(hd0), (hd0,msdos3), (hd0,msdos2), (hd0,msdos1)
ls可以列出所有的硬碟与分区,(hd0)是第一个硬碟,(hd0,msdos1)是第一颗硬碟的第一个分区。以此类推。输入指令时,可以简写成(hd0,1)表示。若是GPT分割,出现的会是(hd0,gpt0)的格式。
接下来我们必须了解各分区,到底是什麼分区?所以我们可以用ls列出文件列表判断,格式如下:
grub recue> ls (hd0,1)/
grub recue> ls (hd0,2)/
grub recue> ls (hd0,3)/
确定各个分区那个是 / ,哪个是/boot,哪个是swap后,就可以开始继续处理。现在假设 / 是(hd0,3),/boot 是(hd0,2)。
额外说明一下,(hd0,2)/grub下的i386-pc或者x86_64-efi目录,是放置grub模组所在:前者出现在以mbr开机的系统,后者出现在efi开机的系统 。你可以尝试 ls 看看,会发现列出一堆.mod档,这是开机所需要的文件,稍候我们也会需要其中一个模组。
接下来是正式设置,其实只有四行指令:
grub rescue> set root=(hd0,3)
grub rescue> set prefix=(hd0,2)/grub
grub rescue> insmod normal
grub rescue> normal
第一行指令:设置根目录所在的分区
第二行指令:设置grub目录。这样他才知道哪里去找模组。此行设置错误,第三行指令执行时,就无法载入模组。假如你的 /boot 没有额外分割,那这行就要写成 set prefix=(hd0,3)/boot/grub
第三行指令:载入normal模组
第四行指令:执行normal模组
normal模组作用是什麼?他会把一些指令,文件系统模组,及其他需要的模组自动呼叫进来。
假如你的grub.cfg没有问题,应该就可以看见grub菜单了。提醒一点,这模式下,指令只要打错,只能开机重来,无法重打一次覆盖之前的命令。
进入系统后,记得 处理grub的异常状况
附注:我利用fdisk的expert mode重新变更分区的顺序,产生这样的问题。
二、开机出现grub指令模式
这类问题通常发生在,mbr可以找到对应的磁盘与各分区,却无法找到可用有效的grub.cfg。
这时候,相关的模组已经载入,所以比grub rescue好处理,打错可以重打一次覆盖之前的命令,也可以用上下键重复之前的命令。
同样用 ls 找出相关的分区,并检查哪个分区是根目录,哪个分区是 /boot ,方法与之前的grub rescue相同。现在假设 / 是(hd0,3),/boot 是(hd0,2)
命令有四行:
grub> set root=(hd0,3)
grub> linux (hd0,2)/vmlinuz-3.11.0-18-generic root=/dev/sda3
grub> initrd (hd0,2)/initrd.img-3.11.0-18-generic
grub> boot
第一行:设置根目录所在的分区
第二行:设置核心所在,并设置根目录所在分区
第三行:设置虚拟系统启动核心所在。
第四行:开机
我怎麼知道核心的完整名称为何?用ls去查一下就可以了。
假如你的 /boot 没有额外分割,第二行要改成 (hd0,3)/boot/vmlinuz-3.11.0-18-generic,且后面指定root=/dev/sda3可以省略;第三行要改成(hd0,3)/boot/initrd.img-3.11.0-18-generic。
假如你系统的其他部份没有问题,应该就会进入系统了。不会见到grub菜单。
进入系统后,记得 处理grub的异常状况
注:我删除grub.cfg来重现这种错误。
三、可见到grub menu,但无法开机
系统可以找到grub.cfg,但是上头的资料有问题,无法找到核心。常发生在变更分割表后,因grub无法辨识uuid或者label造成.
在grub menu可选择'e',对menuentry进行修改
修改前,大约会如下:
setparams 'Ubuntu'
recordfail
load_video
insmod gzio
insmod part_msdos
insmod ext2
set root='hd1,msdos2'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd1,msdos2 --hint-baremetal=ahci1,msdos2 1ad522f5-2d6f-4a74-b827-245e168e8b35
else
search --no-floppy --fs-uuid --set=root 1ad522f5-2d6f-4a74-b827-245e168e8b35
fi
echo'Loading Linux 3.11.0-18 ...'
linux/boot/vmlinuz-3.11.0-18-generic root=UUID=1ad522f5-2d6f-4a74-b827-245e168e8b35 ro quiet splash $vt_handoff
echo'Loading initial ramdisk ...'
initrd/boot/initrd.img-3.11.0-18-generic
可以把他修改成最基本的样式:
setparams 'Ubuntu'
set root=(hd0,3)
linux (hd0,2)/vmlinuz-3.11.0-18-generic root=/dev/sda3
initrd (hd0,2)/initrd.img-3.11.0-18-generic
输入完成后,按Ctrl-x或者F10开机。
是不是很像 开机出现grub指令模式 的处理方法?因为两者都是grub.cfg的异常所造成,所以必须告诉grub核心在哪里。
还有一个小技巧,其实两者的处理方式可以一模一样:按下Ctrl-c或者F2,就会进入指令模式,与 开机出现grub指令模式 的处理方法 完全相同。若是你搞不清楚哪个分区是/boot?哪个是根目录?指令模式会比较好用。
进入系统后,记得 处理grub的异常状况。
注:我修改grub.cfg来造成这样的问题。
四、开机进入initramfs模式
假如开机过程,一直到载入核心都没问题,但是其他的文件系统却无法正常挂载,导致开机失败,就会进入initramfs模式。
什麼是initramfs?就是initrd.img,他其实就是一个核心的内存版,开机过程中,直接放上内存,形成一个虚拟的系统,然后再把其他的文件系统挂载进来,换成真正的核心来控制。
所以你可以 ls 看一下,就会发现就是一个类似linux系统的文件结构。
但他真的很简陋,你可以到bin与sbin下看看,就知道这个系统有多简陋。所以我们必须把原有磁盘中的文件系统挂载进来。其实这个过程,就跟真的开机过程类似。小心,initramfs下不会显示所在的目录,小心「迷路」。
blkid可以检视有哪些磁盘与分区(没有fdisk可用...),我们可以利用mount挂载进来看。我们假设你已经确认:/ 在/dev/sda3,/boot在/dev/sda2
mkdir mnt
mount /dev/sda3 /mnt
mount /dev/sda2 /mnt/boot
这两个顺序不要颠倒,因为/boot是在根目录之下的
接著需要把一些必要设备档、系统档、与内存挂载到真实的根目录去,以提供真实的根目录使用。
mount --bind /dev /mnt/dev
mount --bind /sys /mnt/sys
mount -t proc proc /mnt/porc
假如你还有其他分区,也要一并挂载到相对应的目录。
再来就要把根目录切换到真实的根目录去了:
chroot /mnt
好了,现在你应该看到每行最前面的initramfs已经变成root@(none),你已经开始使用真实的根目录,很多工具也回来了。如果你对系统够了解,加载模组,连上网路都是可行的。
稍微解释一下chroot。这个指令会把你的根目录切换到你指定的地方,切换过去后,你会从这里开始你的root身份,在这里你拥有所有的权限。这个技巧很重要,不仅用在修复系统。到目前为止,你所作的事,就跟真实的开机流程类似。有兴趣的人,不妨多了解一点。
不过现在首要的事情,是 处理grub的异常状况(请看第五段),因为你已经进入系统了,虽然功能不全,但已经足以让你处理问题了。
这里额外提供一个技巧,blkid可以查看磁盘分区的uuid,比对 /etc/fstab 后,可能你会需要修改 /etc/fstab 里的数据。为了方便修改,你可以先把查询的结果放在 /etc/fstab 的后面:
blkid >> /etc/fstab
上下比对修改应该不会太难。最后记得把旧的设置,前面加上'#',这样才不会冲突。存档。键入sync。重新开机。(因为很多模组没有挂上,你无法reboot或shutdown,只能直接电源键关机。)
假如都正常了,应该就会进入系统。大多数的状况下,不需要额外的处理。因为你已经处理完了。
注:我利用tune2fs修改分区的uuid,来造成这样的问题。
五、处理grub的异常状况
会出现grub异常状况,几乎都与挂载设置,grub设置,或磁盘开机区有关,所以请处理以下三件事:
检查并修改 /etc/fstab :
/etc/fstab 是系统挂载分区的必要文件。请确认里面的uuid是否与实际状况相符?实际的uuid可以藉由sudo blkid取得。若有不符的状况,请修改。现在ubuntu已经默认使用uuid来辨识分区,这种辨识方式,可以避免系统的混淆。当然他仍支持以往用设备名称辨识的方法。更新 /boot/grub/grub.cfg :
sudo update-grub
- 重新安装grub到磁盘开头的开机区
sudo grub-install /dev/sda
若有问题,可能需要强制安装
sudo grub-install /dev/sda --force
若不是/dev/sda,请自行修改。
以下三个参数要注意,必要时要特别加入
--boot-directory=[path]
--efi-directory=[path]
--uefi-secure-boot
详情请man grub-install