Linux系统诊断小技巧(13):启停问题之如何修复grub损坏-阿里云开发者社区

开发者社区> 阿里云支持与服务> 正文
登录阅读全文

Linux系统诊断小技巧(13):启停问题之如何修复grub损坏

简介: grub损坏,是导致系统启动失败比较常见的致因之一,重新安装即能修复。但是系统没有启动,怎么重新安装gurb呢?有哪些要注意的事项?

grub损坏,是导致系统启动失败比较常见的原因。如何解决这类问题呢?

解决问题,好用的工具很重要。我们先讨论下好用的工具。

三大利器

关于工具的重要性我们就不絮叨了。解决启停问题,一定要有三大利器的辅助

  • 快照
  • VNC
  • 录屏工具

快照

快照对排查启停问题,有三个方面的用处。一是保留现场。有了这个现场,不管我们排查中做了什么变更,我们总是能够回撤到现场。这是现实版后悔药。二是在没有办法进入系统的情况下,快照可以让我们把问题磁盘挂载到其他实例上。这样我们有了一个排查、诊断和修复的途径。三是快照提供了多种可选择的途径让我们可以使用修复后的数据和结构。比如新建磁盘挂载拷贝、制作安装镜像覆盖有问题的系统盘等等。
988343E03D9EAC6D8E55E38EF760A9EC

VNC

高速公路是有应急车道的。同样我们的业务系统也需要应急车道,用以解决异常、紧急等非常规问题。VNC就是我们的应急车道。

当然,VNC不是唯一可用的方案。这里的关键是在系统异常时,提供一个root shell供排查只用就好。

录屏工具

各主流平台都有好用的录屏工具,功能大同小异,大家使用顺手即可。为什么我们要建议大家都配备录屏工具呢?

系统启停时,Linux控制台上的系统输出很快。有些关键的报错信息,你可能完全没有机会看到就过去了。如果类似信息完全没有记录到日志中。那么,你可能被后面的日志给误导。

题外话:bind挂载

修复启停时经常需要做chroot操作,即我们要在一个新的根文件系统内操作。但是,只执行chroot是不够的。我们还需要挂载/dev/proc/sys目录。

但是,因为/dev/proc/sys不是设备,直接挂载是不可行的。这里的技巧是使用bind挂载方式。

mount --bind /olddir /newdir # bind挂载选项实例
for d in dev proc sys;do mount /$d /new_root_dir/$d;done # 切换根文件执行chroot前,先挂载需要的系统目录

回到话题

如何复现现场?

我们通过覆盖磁盘第一扇区来破坏grub的引导代码部分,观察下grub被破坏后,实例启动的情况
35480567BC1EBCBFB46CD6D1DD0B2DE4

具体操作的命令如下。注意,危险操作,切勿随意模仿。

fdisk -l -u /dev/{xvda,vda} # 确定系统盘设备路径
dd if=path_to_sys_disk bs=448 count=1 2>/dev/null | od -tx1 # 查看MBR内容
dd if=/dev/zero bs=448 count=1 of=path_to_sys_disk # 覆盖MBR
dd if=path_to_sys_disk bs=448 count=1 2>/dev/null | od -tx1 # 验证已经覆盖了MBR
reboot # 重启

执行过程如下(fdisk操作没有显示)

ADD70628FE61D191CA858513D8C69367

修复

那么,怎么修复呢?grub损坏的修复方法简洁明了:重新安装grub即可。但是当前实例启动失败了,无法对问题系统进行读写处理。

所以我们需要解决的问题是两个:

  1. 通过什么方式来处理系统盘。
  2. 怎么重新安装grub。

解决第一个问题的方法很多。这里我们给大家推荐能够使用快照的方法。这个方法虽然稍显啰嗦,但是却能让我们全程掌控。

如何使用快照?

我们为问题实例的系统盘做快照。然后再从快照新建磁盘。新建磁盘和系统盘内容一样,但是可以作为数据盘挂载到正常实例上。

这样我们就可以在正常实例上对新创建的磁盘做处理。调整配置、适当修改,而后重新安装grub。

整个思路图示如下
75944F2FA72CD1D112D3C39D34D5D8DE

具体操作示例如下

首先做快照
D149F323F79A2710F4A3DC0CD5E619BE

给快照个显著的名字
DB7B625AA6286AE201DD71670C375CEE

良好规划和维护的系统盘,一般都尺寸不大
EBED2326730C86E3113F72FA780EB6F8

现在新建磁盘

4A521F26FF0CAD259A80C38293ECAD4E

处理系统盘的问题解决了。那么,怎么重新安装grub呢?

重装grub

主流Linux发行版都提供了grub-install工具(名称也可能是grub2-install),大家直接调用即可。但是有几点大家要注意。

小提示

首先,grub的引导器默认使用BIOS磁盘命名惯例,这与Linux是不同。所以grub提供了配置文件,用来在BIOS的磁盘命名和Linux系统的磁盘命名之间转换。

这些配置文件如下:

版本 应用配置 系统配置
grub /boot/grub/device.map /etc/{sysconfig,default}/grub
grub2 /boot/grub2/device.map /etc/{sysconfig,default}/grub

如果是KVM实例,则磁盘是vda;如果是较老的XEN实例,则磁盘是xvda。

第二,grub-install的操作对象是磁盘还是分区。不要给错参数。

第三,如果您的系统比较老。那么,您可能会碰到已知bug:grub-install工具不能处理/dev/xvda*路径

重装步骤

有了以上的铺垫,我们给出重新安装grub的步骤

  1. 把新建磁盘挂载到正常实例上,以便对之读写、修改。
  2. 挂载目标根文件系统,我们需要改动grub的device.map文件。
  3. 把/dev、/proc和/sys挂载到新挂载文件系统。这样我们就能够使用内核导出的系统数据了。
  4. chroot到目标根文件系统,使之成为当前跟文件系统。
  5. 检查和核实/boot/{grub,grub2}/device.map和/etc/{sysconfig,default}/grub配置文件中磁盘名称是否正确。
  6. 使用grub-install来重新安装grub。

这些步骤,用脚本来表达,如下

# 1. 挂载新建磁盘到正常实例需要在控制台操作
# 2. 把新建磁盘在实例内部挂载上。这里我们假设/dev/vdb是系统盘
mount /dev/vdb1 /mnt
# 3. 通过bind方式,挂载系统目录到新根文件系统
for d in dev proc sys;do mount --bind /$d /mnt/$d;done
# 4. 切换到新根文件系统
chroot /mnt
# 5. 检查/boot/grub/device.map或者/boot/grub2/device.map文件,确认磁盘名称不当。如有则修改
cat /boot/{grub,grub2}/device.map
# 6. 重新安装grub。因为是在其他实例上以数据盘的方式,因此是第二块磁盘。
grub-install /dev/vdb

我们按照上面的步骤,把前面破坏的那台实例的grub重新安装下。

首先,挂载磁盘到正常实例

6802FC4BA13B6E205A5830218611DDA7

实例内部挂载

D7BFFDF1F285F94FE3026BF1923B942C

接下来我们bind挂载/dev、/proc和/sys

096FE01912E0A485E4BED7ECD16F0F9E

现在切换到新根文件系统

53870A7B65C809FEBBDFAD97BB05EF24

第五步,检查磁盘名称是否需要修改,需要则修改之

0D43CB5A63537636BEE2954E0019BDDF

最后一步,重新安装grub

94D67B63FFE6F38E150B70D8547C0DEF

再次请快照出场

怎么通过修正完毕的新建磁盘来修复问题实例的系统呢?这里需要注意

  1. 我们没有办法直接使用新建的快照回滚问题实例的系统盘。
  2. 数据盘的快照不能创建安装镜像。但是,开通了白名单就可以。

我们新创建磁盘是数据盘,其创建的快照是不能回滚问题实例的系统盘的。所以我们只能通过把新创建磁盘转为系统盘,而后创建安装镜像的方式来恢复问题实例。当然,这需要开通白名单。

即整体思路是这样的
75944F2FA72CD1D112D3C39D34D5D8DE

怎么把数据盘转为系统盘?我们会专题讨论下。

终焉

祝探索愉快。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享: