分类:
2012-02-24 10:45:33
原文地址:GRUB修复有关的案例 作者:chaseey
来源:
以下是我在生产环境中所碰到的一些和GRUB修复有关的案例:
案例一:
GRUB无法找到kernel image的问题:
产生这类型问题的原因包括:
配置文件中指定了错误的kernel image名称或者路径,在/boot分区下kernel文件被删除或者更名,kernel image文件被破坏,Raid-1磁盘阵列更换故障盘后信息不同步等。
对于这类型问题的解决方法:
可以设法通过救援模式或者在开机的时候进入grub的shell,然后利用grub shell尝试手动指定和装载正确的kernel image信息或者在救援模式下检查和重写grub.conf文件。
需要注意的是,如果要通过救援模式进入grub命令行界面需要先chroot,即执行chroot /mnt/sysimage。在
grub>提示符之后执行:
# root (hd0,0)
# setup(hd0)
# quit
不管通过什么样的方法和配置,只要使GRUB能够正确找到kernel image是解决问题的关键。
在对grub修复的时候尤其要注意MBR信息在软件Raid上的恢复。
Linux的boot分区不能建立在软件Raid-0上,但是可以建立在Raid-1阵列上。也就意味着系统的GRUB也是同时写入到Raid-1磁盘阵列两块盘的MBR中。但是如果这个信息一旦这个信息没有正确写入或者正常完成写入,问题就会出现。
这种情况多发于对Raid-1阵列中的坏盘进行更换的时候。
一个典型的例子是,用户只有两块磁盘做Raid-1,他在两块盘上分别规划了同样的磁盘分区/boot swap以及/,对应的设备是md0,md1和md2。在其中的某一个磁盘出现问题的时候,用户更换一块新的磁盘,并且按照原来的盘规划了/boot,swap以及/,同时使用了命令mdadm -A对三个md都进行了重组,重组能够顺利完成,但是一旦重启系统在出现一个GRUB的提示对话框之后引导停止。
从这个情况看来,很显然,md0,md1和md2内的数据都由原来的磁盘向新的磁盘进行了同步,但是MBR的内容和信息没有同步过来。这就造成了系统启动的失败。
解决该问题的方法:
可以使用救援模式引导系统,或者使得GRUB能够检测到文件系统——即出现GRUB>提示符,执行下面的命令,将GRUB重装到第一块盘:
# root (hd0,0)
# setup(hd0)
# quit
然后执行,将GRUB重装到第二块盘:
# root (hd1,0)
# setup(hd0)
# quit
完成之后重启系统。这种方法还可以对付在BIOS中对启动引导管理器进行的修改。
案例二:
None System or Disk Error和GRUB的关系:
某个用户曾经报告一台HP的DL380服务器上原有40G和140G两块硬盘,并且按照第一块硬盘所能够提供的磁盘空间建立了一个软件Raid-0磁盘阵列。该用户在没有拔除这两块硬盘的情况下直接加入了两块新的硬盘并计划对原有的Raid-0阵列进行扩容。但在插入硬盘重启之后显示“None System or Disk Error”,在用户拔除这两块硬盘之后重启还出现同样的信息。
根据描述的系统启动过程来看,这个none system or disk error的报错,表明系统启动引导过程中并没有装在任何启动引导管理器(GRUB)信息,而之所以没有找到这些信息是因为这些磁盘的MBR里面没有用于引导的IPL或者说白了系统所用于引导的磁盘根本就不是启动盘。看来系统并没有使用用户设想的磁盘作为启动引导磁盘。那么也就时说这和在磁盘的GRUB没有任何关系,我们所要做的第一能够确保系统使用正确的磁盘引导,第二就是没有对原有的GRUB进行任何错误的修改就行。
按照我们对问题的分析,用户更换了硬盘所在的槽位,问题得到解决。
产生该问题的原因是因为HP DL380服务器在安装系统必须在阵列上进行,但是新加入的磁盘或者阵列会更改原来默认的启动引导顺序。尽管这和GRUB的修复没有任何关系,但是能够准确定位该问题的所在至少能够减少排错的时间以及一些不必要的麻烦。
案例三:
在RHEL3中HP服务器上的cciss和system-map的问题:
众所周知在GRUB中对设备进行命名的方法和系统命名的方法是不同的。不管系统中的启动引导磁盘是sd接口还是hd接口在GRUB中都会被统一识别为hd,并且hda/sdahd0,hdb/sdbhd1……依次类推。这和系统对设备的命名方式显然存在一些差异,但是这种差异通过在/boot/grub/device-map文件中进行解释和映射来实现系统对两种设备命名方法的映射。
这是一个device-map文件的内容:
遗憾的是,redhat老版本的操作系统如RHEL3的某个版本,在一些特殊的硬件上,如HP的cciss中对系统设备名和GRUB设备名的映射关系不正确而导致系统在这些硬件上无法启动。这可以认为是操作系统的一个bug,所幸该bug在RHEL3靠后的几个发行版后都得到了修复。
尽管碰到这种问题的几率极低,但需要明确一点,检查设备映射是否正确也是GRUB排错的一项内容。
这里顺别说一下:
cciss是惠普的smart array控制器的设备名,c0指channl 0,第一个SCSI通道,d0指逻辑盘1,d1指逻辑盘2……,p1指第一个分区,p2是第二个分区……。在这种情况下,我们可以看到很多HP的服务器在通过该设备连接硬盘的时候,经常看到的设备是/dev/cciss/c0d0p1,/dev/cciss/c0d0p2,/dev/cciss/c0d0p3等。
案例四:
在GRUB中向kernel传递了错误的根分区信息导致系统kernel panic:
在GRUB的配置中,根分区信息的指定是必须的,但是一旦错误指定了根分区或者根分区文件文件系统或卷标被破坏都回导致在启动引导过程中出现kernel panic情况。
这是在GRUB中对/分区指定的信息:
kernel /vmlinuz-2.6.18-8.1.1.el5 ro root=LABEL=/
那么一旦/卷标被删除,可以通过e2label的方式重新创建,或者将其直接更改为:
kernel /vmlinuz-2.6.18-8.1.1.el5 ro root=/dev/sda2
即以直接指定/分区名的方式来指定根分区。
这个操作可以在开机发现错误之后于GRUB命令行中直接修改,或者进入救援模式进行操作。当前所定义的内容如果成功,切记将其记录到/etc/grub.conf或者/boot/grub/grub.conf文件中。
其实这是一个非常典型的错误,出错的时候,屏幕上显示的大概情况如下:
Creating block devices
Creating root devices
mkrootdev:label / not found
Mounting root filesystem
Mount:error 2 mounting ext3
Pivotroot:pivot_root(/sysroot, /sysroot/initrd) failed:2
umount /initrd/proc failed:2
Freeing unused kernel memory:164k freed
Kernel panic:no init found. Try passing init = option to kernel.
很显然,这个时候如果是因为/文件系统无法找到或者挂载成功,必须的内核模块没有加载成功或者initrd文件被破坏都有可能出现同样的信息(这里所指的模块是包括了驱动器,硬件控制器以及作用于文件系统的驱动程序,当然如果是模块造成系统启动不成功的话,可以使用mkinitrd命令对initrd文件进行重建)。
具体的命令是:
# mkinitrd –f /boot/initrd-
例如:
# mkinitrd –f /boot/initrd-2.6.9-42.ELsmp.img 2.6.9-24.ELsmp
在完成了initrd镜像的重建之后可以重新启动系统。
如果问题确认是因为initrd镜像被破坏而导致无法识别文件系统,则通过上面的操作已经能够正确找到root文件系统并开启init进程。
案例五:
该案例实际上和上面的案例有紧密关系。上面的案例中由于GRUB无法正确加载根文件系统而导致kernel panic。造成这个问题的原因也是多种多样。但是即便通过上面的修复可以使得kernel加载根文件系统并且开启init进程,那么在下一步rc.sysinit脚本执行过程中任何区域出现错误也会导致系统无法启动。
因为在存储方面,sc.sysinit脚本会初始化软件raid以及lvm设备然后读取/etc/fstab,所以这个时候如果/etc/fstab文件配置不正确,也会造成系统启动不成功。
从出现的问题现象上基本可以断定是/etc/fstab的问题,但是好在这个时候可以进入修复模式,对问题的修复方法也容易很多。这是出现问题的时候的截屏:
Coundn’t find matching filesystem: LABEL=/
*** An error occurred during the file system check.
*** Dropping you to a shell; the system will reboot
*** when you leave the shell.
Give root password for maintenance
(or type Control-D to countinus):
在这个界面中输入root密码可以在出现的修复模式中运行命令修复。
另外一个会造成该现象的原因是在读/etc/fstab文件并挂载文件系统的时候文件系统检测失败。在这种情况下需要确保文件系统处于umount状态下运行e2fsck。
案例六:
对initrd文件的修复:
initrd是一种基于内存的文件系统,启动过程中,系统在访问真正的根文件系统/时,会先访问initrd文件系统。将initrd中的内容打开来看,会发现有bin、devetc、lib、procsys、sysroot、init等文件(包含目录)。其中包含了一些设备的驱动模块,比如scsi ata等设备驱动模块,同时还有几个基本的可执行程序 insmod, modprobe, lvm,nash。主要目的是加载一些存储介质的驱动模块,如上面所说的scsi ideusb等设备驱动模块,初始化LVM,把/根文件系统以只读方式挂载。
Linux Kernel需要适应多种不同的硬件架构,但是将所有的硬件驱动编入Kernel又是不实际的,而且Kernel也不可能每新出一种硬件结构,就将该硬件的设备驱动写入内核。实际上Linux Kernel仅是包含了基本的硬件驱动,在系统安装过程中会检测系统硬件信息,根据安装信息和系统硬件信息将一部分设备驱动写入 initrd 。这样在以后启动系统时,一部分设备驱动就放在initrd中来加载。
所以在启动过程中initrd文件会在1号进程被开启之前执行,如果一旦initrd文件被破坏或者非正常的更改就会导致系统无法启动。根据以前对initrd原理的解释,initrd中的init是使用nash解释器去执行,所以系统启动没有到nash的时候停住,可以基本上判断是initrd这里hang住。比较可行的办法是通过mkinitrd命令重建initrd,生成一个新的用于初始化和装载模块的ramdisk镜像。
具体的命令是:
# mkinitrd –f /boot/initrd-
例如:
# mkinitrd –f /boot/initrd-2.6.9-42.ELsmp.img 2.6.9-24.ELsmp
或者通过强制的方式重装一个kernel,因为kernel基本上以不变的方式覆盖原来kernel所安装的内容,同时会在rpm安装kernel命令中有重建initrd的脚本:
[root@dhcp-0-195 ~]# rpm -q --scripts kernel
postinstall scriptlet (using /bin/sh):
if [ `uname -i` == "x86_64" -o `uname -i` == "i386" ]; then
if [ -f /etc/sysconfig/kernel ]; then
/bin/sed -i -e 's/^DEFAULTKERNEL=kernel-smp$/DEFAULTKERNEL=kernel/' /etc/sysconfig/kernel || exit $?
fi
fi
/sbin/new-kernel-pkg --package kernel --mkinitrd --depmod --install 2.6.18-8.1.1.el5 || exit $?
if [ -x /sbin/weak-modules ]
then
/sbin/weak-modules --add-kernel 2.6.18-8.1.1.el5 || exit $?
fi
preuninstall scriptlet (using /bin/sh):
/sbin/new-kernel-pkg --rminitrd --rmmoddep --remove 2.6.18-8.1.1.el5 || exit $?
if [ -x /sbin/weak-modules ]
then
/sbin/weak-modules --remove-kernel 2.6.18-8.1.1.el5 || exit $?
fi
案例七:
在系统启动过程中对rc.sysinit脚本进行定位的方法:
在最近对一些客户问题进行处理的时候有时会发现一些因为对/etc/rc.d/rc.sysinit脚本的更改而导致系统无法启动成功的问题。由于rc.sysinit脚本所负责系统环境变量、存储,设备初始化、配额等多个部分的设置和初始化,所以在启动过程中出现如果是因为rc.sysinit的更改而出现dead lock不容易定位是哪个地方的设置出现问题。
由于rc.sysinit脚本是由多个部分组成,一个比较简单的办法就是在每个部分之间加上一个标记。例如:
sleep 10
echo “sleep 10”
这样系统在执行rc.sysinit脚本过程中的每个部分都会停10秒并显示一个提示信息“sleep 10”,这样可以通过显示的信息定位大概问题出在哪里。
案例八:
在系统启动过程中出现的初始化和启动swap的时候系统出现的dead lock的解决方法:
在某些情况下系统启动到enable swap的时候会长时间的dead lock现象,在某些时候系统悬挂于此而始终不能打开mgetty终端提供控制台。
swap交换分区是一个特殊的文件系统,该文件系统的基本作用就是可以使操作系统将一部分驻留于内存而暂时不操作的进程转移到swap分区中而腾出物理内存给新的需要执行的进程。
红帽官方推荐的使用交换分区的比例是2G物理内存以下,交换分区为物理内存的1.5-2倍;4G以上物理内存推荐交换分区与物理内存为1:1。
但一般情况下可能会有多种原因造成swap文件系统的初始化失败而且由于swap分区内容在用户空间无法操作,所以很难准确获得原因。但很多时候系统在启动到swap的时候并没有真正的dead lock,而是由于之后的一些其他服务的启动影响了系统打开终端并给用户造成系统启动swap失败的假象。
基本上一些启动顺序在swap之后的服务都有可能产生这种影响,但由于系统在安装之后默认加载在kernel parameter “rhgb quite”会掩盖整个的启动过程,所以在系统启动到GRUB的时候通过进入GRUB菜单,手动删除“rhgb quite”会防止在启动的时候屏蔽启动过程并显示完整的启动信息。
另外这个rhgb(redhat graphical boot)本身就有可能干扰后续的服务启动。在很多时候实际上后面的服务已经起来,但是系统会显示enable swap并停在该处。在这个时候可以使用ping的方法或者ssh去探测该主机是否已经可以登录并提供服务。