CentOS 6启动故障修复

2018-01-19|Categories: Linux, Magedu-training|

本文所有操作全部基于VMware虚拟机,物理实体机器上的操作可能不同。

修复故障的通用操作

VMware虚拟机开机画面特殊按键

下图就是VMware虚拟机的开机画面:

在这个画面可以快速按以下三个键,功能如下:

  • F2: SETUP(进入BIOS设置画面)
  • F12: Network Boot(从网络引导)
  • ESC: Boot Menu(选择从哪个设备引导系统,如下图所示)

进入光盘救援模式

  • 开机画面按ESC键,进入Boot Menu
  • 选择CD-ROM Drive,从光盘启动(系统安装光盘必须提前挂载)
  • 选择Rescue installed system

  • 等待光盘文件被读入内存

  • 设置救援模式的语言和键盘布局

  • 选择是否设置网络(我选择No

    • 稍后如果需要连接网络,可以通过ifconfig eth0 192.168.0.7/24这样的方式临时指定IP地址

  • 选择是否以读写模式挂载根分区(我选择Continue

    • Continue:以读写模式挂载
    • Read-Only:以只读模式挂载
    • Skip:跳过挂载,直接进入shell
    • Advanced:激活SAN设备

  • 读写模式挂载成功,并提示如何切换到硬盘根目录

  • 启动shell

    • 所有救援操作完成之后,输入exit回到这个画面,选择reboot重启系统

  • chroot /mnt/sysimage切换到硬盘根目录

进入单用户模式

  • 在GRUB画面按下任意键,显示GRUB菜单

  • 在要启动的内核上按a键,修改内核启动参数

  • 在启动参数末尾添加single,按下ENTER键启动系统

    • single换成(s|S|1)这三个字符的任何一个都是同样效果
  • 系统启动到单用户模式,不需要密码就获取root权限

硬件故障

硬盘分区表被破坏

警告:如果分区表没有提前备份,破坏后将无法修复!

备份MBR分区表

$ dd if=/dev/sda of=/mbr-61 bs=1 count=64 skip=446

$ file /mbr-61
/mbr-61: 8086 relocatable (Microsoft)

# 必须把分区表备份到另一台主机,
# 如果保存在本机,破坏分区表之后将无法读取
$ scp /mbr-61 root@172.16.125.71:~

破坏MBR分区表

dd if=/dev/zero of=/dev/sda bs=1 count=64 seek=446

故障表现

黑屏上显示Error 22

修复方法

必须进入光盘救援模式修复。因为没有分区表,救援模式尝试挂载硬盘根分区会报错:

虽然没有分区表无法挂载文件系统,但操作系统可以识别连接的设备,通过fdisk -l可以列出当前连接的硬盘设备,从下图可以看到,硬盘/dev/sda确实没有分区信息:

此时可以从备份主机取回备份的分区表,然后用dd命令写入硬盘:

# 指定IP地址,使本机可以连接其它主机
ifconfig eth0 172.16.125.61/24

# 从其它主机取回备份的分区表
scp root@172.16.125.71:~/mbr-61 .

# 把分区表写入硬盘
dd if=mbr-61 of=/dev/sda bs=1 seek=446

# 查看分区表写入结果
fdisk -l /dev/sda

从上图可以看到,分区信息已成功写入,修复完成。输入exit退出救援模式,重启系统。

重启过程中禁用SELinux检查

由于修改了系统重要文件,SELinux会自动检查其管辖的文件,并重新打标签(relabeling),完成之后会自动重启。这个检查过程可能耗时良久,可以添加内核启动参数selinux=0将其禁用:

这种方式只是临时禁用SELinux检查,下次重启依旧会检查,如果想彻底关闭,必须在/etc/selinux/config文件中彻底禁用SELinux,然后重启系统生效:

sed -i.bak -r 's/^(SELINUX=).*/\1disabled/' /etc/selinux/config

Boot loader (GRUB Legacy) 故障

Stage 1 被破坏

破坏方式

执行破坏操作前,务必做好备份!

dd if=/dev/zero of=/dev/sda bs=1 count=446

故障表现

因为找不到Stage 1,BIOS认为硬盘不可引导,等同于没有安装操作系统,于是BIOS会尝试从可移动设备、光盘或网络引导,具体取决于引导设备的顺序。

修复方法

必须进入光盘救援模式修复。

# 必须chroot,否则系统找不到`grub-install`的路径
chroot /mnt/sysimage
grub-install /dev/sda

# 把内存数据写入到硬盘,可执行多次
sync

注意:grub-install执行完之后,不要立即重启系统!否则内存中的数据可能没有完全写入硬盘,将导致修复失败。

修复过程实际上是重新写入了下图红色方框中的文件:

如果误操作破坏Stage 1之后,没有重启系统,而上图红色方框中的文件都完整保存在/boot/grub目录,也可以使用grub交互式命令来修复:

从上图可以看到,进入grub的交互式命令行之后,

  • 首先执行root (hd0,0),设定/boot目录的位置(在这里是第一块硬盘的第一个分区),grub命令会自动检测分区的文件系统类型。如果不确定/boot目录的位置,可以执行find /boot/grub/stage1
  • 然后执行setup (hd0)
    • 把GRUB Stage 1安装到第一块硬盘的MBR。
    • 把文件系统驱动安装到MBR之后的扇区。e2fs_stage1_5驱动总共13428字节,因此占用27个扇区。

如果想把GRUB安装到分区的引导扇区而不是硬盘的MBR,就需要指定分区号setup (hd0,0),但如此一来就需要链式载入(chain load)这个GRUB。
https://www.gnu.org/software/grub/manual/legacy/Installing-GRUB-natively.html

Stage 1.5 被破坏

破坏方式

执行破坏操作前,务必做好备份!

# Stage 1.5存储的文件系统驱动不同,具体需要破坏的扇区数不同,
# e2fs驱动总共占用27个扇区,因此这里破坏26个扇区,
# 如果破坏的扇区太少,系统仍然可能启动。

dd if=/dev/zero of=/dev/sda bs=512 count=26 seek=1

故障表现

系统可以从硬盘引导,但由于找不到/boot所在分区的文件系统驱动,因此无法显示GRUB菜单,也无法进一步加载内核,只能显示一个黑屏,黑屏上没有任何信息。

修复方法

必须进入光盘救援模式修复。

# 必须`chroot`,否则系统找不到`grub-install`的路径
chroot /mnt/sysimage
grub-install /dev/sda

# 把内存数据写入到硬盘,可执行多次
sync

Stage 2 被破坏

破坏方式

Stage 1 和 1.5 的代码是以二进制的方式存储在硬盘上,因此只能通过dd这种直接读写硬盘块(block)的工具来破坏和修复,而Stage 2代码是存储在/boot/grub/stage2这个文件,只要将其移动或删除,就破坏了Stage 2。

故障表现

黑屏上显示Error 15

修复方法

必须进入光盘救援模式修复。

  • 如果做过备份,把备份文件放回/boot/grub/目录即可,文件名必须是stage2
  • 如果没有备份,仍然使用grub-install命令恢复。

实际上,grub-install命令可以修复所有GRUB Legacy引导阶段的错误。

/boot/grub/grub.conf被删除

故障表现

无法显示GRUB菜单,只能显示GRUB shell:

修复方法

临时指定引导参数:

# 指定`/boot`目录所在分区,
# 这里的 root 仅仅是GRUB的概念,不能与硬盘根分区混淆。
grub> root (hd0,0)

# 指定kernel路径,文件名可以用`<tab>`键补全,
# 必须用`root=`指定硬盘根分区,否则内核找不到根分区,将无法启动系统。
grub> kernel /vmlinuz-`uname -r` root=/dev/sda2

# 指定`initramfs`路径,文件名可以用`<tab>`键补全
grub> initrd /initramfs-`uname -r`.img

# 使用以上参数引导
grub> boot

系统启动成功之后,必须修复/boot/grub/grub.conf文件:

vim /boot/grub/grub.conf

至少包含如下内容:

# 用户在5秒内没有操作,将使用默认内核启动
timeout=5
# 默认用第一个`title`指定的内核启动
default=0

# title后面的名字可以自定义
title CentOS 6.9 (2.6.32-696.el6.x86_64)
    root (hd0,0)
    # `ro root=`这个顺序很重要,`ro`必须在`root=`前面,
    # 我第一次手写的时候,把顺序弄反了,结果重启后正确的用户名和密码无法登录,调整顺序立即恢复正常!
    # `root=`后面也可以直接写`/dev/sda2`这样的分区名称。
    kernel /vmlinuz-2.6.32-696.el6.x86_64 ro root=UUID=5561d4f2-d938-4bbd-98e9-d5a09a6731ec
    initrd /initramfs-2.6.32-696.el6.x86_64.img

CentOS 6默认的其它内核引导参数:

KEYBOARDTYPE=pc
KEYTABLE=us
LANG=en_US.UTF-8
SYSFONT=latarcyrheb-sun16
crashkernel=auto
quiet
rd_NO_DM
rd_NO_LUKS
rd_NO_LVM
rd_NO_MD
rhgb

完整的内核引导参数列表可以通过man dracut,然后搜索KERNEL COMMAND LINE查看。

/boot分区故障

initramfs被删除

故障表现

系统可以从硬盘引导,可以显示GRUB菜单,但由于加载内核之后无法挂载根分区的文件系统,无法启动PID 1进程,只能显示一个黑屏,黑屏上没有任何信息。

修复方法

initramfs的完整路径是/boot/initramfs-$(uname -r).img,删除后必须进入光盘救援模式修复。

# 必须chroot,否则mkinitrd会因为找不到文件报错
chroot /mnt/sysimage
cd /boot
mkinitrd initramfs-$(uname -r).img $(uname -r)

Kernel被删除

故障表现

黑屏上显示两行信息:

Error 15: File not found
Press any key to continue...

修复方法

必须进入光盘救援模式修复。

chroot /mnt/sysimage

# 挂载系统安装光盘
mount /dev/sr0 /mnt/cdrom

cd /mnt/cdrom/Packages
rpm -ivh --force kernel-$(uname -r).rpm

/boot目录被删除

故障表现

黑屏上显示Error 15

修复方法

必须进入光盘救援模式修复。

第一步,恢复/boot目录下的文件:

chroot /mnt/sysimage
mount /dev/sr0 /mnt/cdrom
cd /mnt/cdrom/Packages
rpm -ivh --force kernel-$(uname -r).rpm

第二步,恢复/boot/grub目录下的文件:

# 不需要手工创建`/boot/grub`目录
grub-install /dev/sda

第三步,恢复/boot/grub/grub.conf文件:

vim /boot/grub/grub.conf

timeout=5
default=0

title CentOS 6.9 Fixed
    root (hd0,0)
    kernel /vmlinuz-2.6.32-696.el6.x86_64 ro root=/dev/sda2
    initrd /initramfs-2.6.32-696.el6.x86_64.img

/boot目录和/etc/fstab被删除

故障表现

黑屏上显示Error 15

注意:如果仅仅是删除了/etc/fstab文件,系统仍然可以启动。

修复方法

必须进入光盘救援模式修复。

必须先修复/etc/fstab文件,此时只能先列出硬盘分区,然后临时挂载每个分区,根据分区的文件来推测其正确的挂载点。

fdisk -l
mkdir /mnt/guess
mount /dev/sda2 /mnt/guess

从上图显示的文件可以推测/dev/sda2正确的挂载点应该是/,然后就可以修复/etc/fstab文件:

umount /dev/sda2
mount /dev/sda2 /mnt/sysimage
cd /mnt/sysimage/etc

cat > fstab <<EOF
> /dev/sda2     /       ext4    defaults 0 0
> /dev/sda1     /boot   ext4    defaults 0 0
> /dev/sda3     /app    ext4    defaults 0 0
> /dev/sda5     swap    swap    defaults 0 0
> EOF

修复完成后必须重启,让救援模式自动挂载文件系统,然后就可以执行上一小节的三步来恢复/boot目录的所有文件。

救援模式挂载逻辑卷(LVM)分区

如果/分区是逻辑卷,必须先激活卷组(Volume Group)才可以挂载:

vgchange -ay

启动文件故障

/sbin/init被删除

/sbin/init是内核挂载硬盘根分区之后启动的第一个进程,其它所有系统进程都是/sbin/init的子进程,如果/sbin/init被删除,系统将无法真正启动。

故障表现

shell报错cannot set terminal process group (-1),shell提示符后面无法输入任何字符,敲回车键就重复显示shell提示符本身:

修复方法

重启系统,在GRUB菜单添加内核启动参数init=/bin/bash,然后按b键,使用刚添加的参数引导内核,内核会把/bin/bash作为第一个进程启动,启动成功后,执行如下操作:

# 必须用读写模式重新挂载根分区
mount -o remount,rw /

mount /dev/sr0 /mnt/cdrom
cd /mnt/cdrom/Packages
rpm -ivh --force `rpm -qf /sbin/init`.rpm
reboot

/etc/rc.d/rc.sysinit被删除

这个脚本的用途很多,是系统启动必不可少的文件:

  • 打印欢迎信息
  • 设定主机名称
  • 设定系统时间
  • 初始化网络
  • 挂载/proc文件系统
  • 挂载/etc/fstab列出的文件系统
  • 根据/etc/sysctl.conf文件设置内核参数
  • 基于内核引导参数初始化硬件
  • 初始化SELinux
  • 清理/var等目录
  • 激活LVM及Software RAID设备
  • 加载额外设备的驱动程序
  • ……

故障表现

备注:/etc/rc.sysinit是指向/etc/rc.d/rc.sysinit的软链接,若只是软链接被删除,系统仍然能够启动。

修复方法

必须进入光盘救援模式修复。

chroot /mnt/sysimage
mount /dev/sr0 /mnt/cdrom
rpm -ivh --force /mnt/cdrom/Packages/$(rpm -qf /etc/rc.d/rc.sysinit).rpm
reboot

Leave A Comment