对linux系统启动流程的理解是熟悉linux系统的重要一步,今天来简要梳理linux启动流程。然后根据linux启动时几个关键阶段可能出现的问题进行模拟排错。
(一)先来介绍RHEL系列系统引导过程如下:
1) 通电(计算机中cpu,内存为电子设备,即通电才可以运行。硬盘为物理机械设备,即使无电,也可以持久保存数据)
Tips:一块硬盘出厂后首先进行低级初始化,然后我们可以进行分区(partition),分区是为了为硬盘建立逻辑边界,这样一个分区就可以对应一个文件系统。然而对于硬盘上0扇区0磁道前512bytes部分来说,它是一个独立于操作系统的部分,是一个全局重要区域。称之为MBR,MBR对于系统启动至关重要!
2) BIOS初始化
BIOS(Basic Input/Output System),基本输入输出系统,该系统存储于主板的ROM芯片上,计算机在开机时,会最先读取该系统,然后会有一个加电自检(POST)过程,这个过程其实就是检查CPU和内存,计算机最基本的组成单元(控制器、运算器和存储器),还会检查其他硬件,若没有异常就开始加载BIOS程序到内存当中。
这里注意:在实际情况中,内存条,声卡,显卡等设备损坏系统无法在第一阶段正常通过。
BIOS还有主要的一个功能就是存储了磁盘的启动顺序,BIOS会按照启动顺序去查找第一个磁盘头的MBR信息,并加载和执行MBR中的Bootloader程序,若第一个磁盘不存在MBR,则会继续查找第二个磁盘(启动顺序可以在BIOS的界面中进行设置),一旦BootLoader程序被检测并加载内存中,BIOS就将控制权交接给了BootLoader程序。
(其中MBR对于启动操作系统至关重要!MBR(Master Boot Record),主引导记录,MBR存储于磁盘的头部,大小为512bytes,其中,446bytes用于存储BootLoader程序,64bytes用于存储分区表信息,最后2bytes用于MBR的有效性检查。)
3 )grub2磁盘引导阶段
其实分为两个阶段:Stage1与Stage1_5。
Stage1:其实就是MBR,它的主要工作就是查找并加载第二段Bootloader程序(stage2),但系统在没启动时,MBR根本找不到文件系统,也就找不到stage2所存放的位置,因此,就有了stage1_5
Stage1_5:该步骤就是为了识别文件系统,
4)grub2文件引导阶段
GRUB程序会根据/boot/grub/grub.conf文件查找Kernel的信息,然后开始加载Kernel程序,当Kernel程序被检测并在加载到内存中,GRUB就将控制权交接给了Kernel程序。
注意:实际上这个步骤/boot还没被挂载,GRUB直接识别grub所在磁盘的文件系统,所以实际上应该是/grub/grub.conf文件,该配置文件的信息如下:(非常重要)
grub.conf:
#boot=/dev/sda
default=0 #设定默认启动的title的编号,从0开始
timeout=5 #等待用户选择的超时时间
splashimage=(hd0,0)/boot/grub/splash.xpm.gz #GRUB的背景图片
hiddenmenu #隐藏菜单
title CentOS (2.6.18-194.el5PAE) #内核标题
root (hd0,0) #内核文件所在的设备
kernel /vmlinuz-2.6.18-194.el5PAE ro root=LABEL=/ #内核文件路径以及传递给内核的参数
initrd /initrd-2.6.18-194.el5PAE.img #ramdisk文件路径
5 )指定boot所在分区
6 )启动内核,只读挂在/设备
Kernel,内核,Kernel是Linux系统最主要的程序,实际上,Kernel的文件很小,只保留了最基本的模块,并以压缩的文件形式存储在硬盘中,当GRUB将Kernel读进内存,内存开始解压缩内核文件。讲内核启动,应该先讲下initrd这个文件,
initrd(Initial RAM Disk),它在grub文件引导这个步骤就被拷贝到了内存中,这个文件是在安装系统时产生的,是一个临时的根文件系统(rootfs)。因为Kernel为了精简,只保留了最基本的模块,因此,Kernel上并没有各种硬件的驱动程序,也就无法识rootfs所在的设备,故产生了initrd这个文件,该文件装载了必要的驱动模块,当Kernel启动时,可以从initrd文件中装载驱动模块,直到挂载真正的rootfs,然后将initrd从内存中移除。
Kernel会以只读方式挂载根文件系统,当根文件系统被挂载后,开始装载第一个进程(用户空间 的进程),执行/sbin/init,之后就将控制权交接给了init程序。
7)启动init程序,进入初始化阶段
8) 启动systemd初始化进程
9 )取/etc/systemd中的文件
10) 启动程序
11)启动登陆环境
总结:整个过程基本可以分为POST–>BIOS–>MBR(GRUB)–>Kernel–>Init–>Runlevel。如图所示:
启动级别:
0: 系统停机模式
1: 单用户模式,root权限,用于系统维护,禁止远程登录,类似windows的安全模式
2: 多用户模式,没有NFS和网络支持
3: 完整的多用户文本模式,有NFS和网络,登陆后进入控制台命令行模式
4: 系统未使用,保留的,一般不用
5: 图形化模式
6: 重启模式
(二)系统排错
这部分对linux启动中几个关键阶段以启动先后顺序来模拟演示排错。
问题(1):GRUB硬盘引导阶段中 mbr前446bytes出错
模拟:#dd if=/dev/zero of=/dev/vda bs=446 count=1
解决:
1 系统关机状态下,添加光盘镜像
2 选择光盘启动
3 选择troubleshooting中的挽救模式
4 选择1-->continue--> 回车打开shell chroot /mnt/sysimage/
5 更改挂载目录为根目录执行grub2-install
6 启动分区所在硬盘执行grub2-install /dev/vda
exit退出两次
执行挽救后选择从硬盘启动
实验:
模拟mbr前446bytes损坏:
系统无法启动:
选择从光盘启动,添加光盘,导入镜像:
启动选择从光盘启动:
选择troubleshooting中的挽救模式rescue:
选择1–>continue–> 打开shell ,切换到真实根环境chroot /mnt/sysimage/,重新安装grub,grub2-install /dev/vda,exit退出两次
最后,选择硬盘启动,系统恢复正常
问题(2):GRUB文件引导阶段出现问题,即cpu在内存中找不到/boot/grub2/grub.cfg
模拟:rm -rf /boot/grub2/grub.cfg
解决:
1.当系统没有重新启动时,可以直接挽救:
grub2-mkconfig > /boot/grub2/grub.cfg
2.若重新启动,则系统因为找不到grub.cfg里面的重要信息,则可以如下进行挽救:
1 当系统被重启时:
2 grub > set root=’hd0,msdos1’ ##此位置不固定,为/boot所在分区
3 grub > linux16 /boot/vmlinuz-3.10.0-123.e17.x86_64 ro root=/dev/vda #根区分所在位置
4 grub > initrd16 /boot/initramfs-3.10.0-123.e17.x86_64.img
5 grub > boot
6 以上操作虽然可以正常进入系统,但是只时临时的,所以还需执行:
grub2-mkconfig > /boot/grub2/grub.cfg
上面执行的操作其实质是grub.cfg里面的信息,目的是用命令将grub引导过程顺利进行下去。
实验:
模拟grub配置文件丢失:
当系统无重启时,这时可以直接挽救:
当重启后,可以在挽救模式下手动执行命令使grub阶段可以正常下去:
再开机后,还是要将grub配置文件生成:
问题(3):grub阶段后,linux将控制权交给内核,bootloader解压缩内核,将控制权交给内核,此时内核读取各种配置文件.当内核文件被删除后,无法加载内核,导致不能正常启动。
模拟:rm -rf /boot/vmlinuz-3.10.0-123.e17.x86_64
解决:镜像文件ios的packages中存在有内核相关文件,我们可以使用光盘启动,在packages包中将需要的内核文件复制到原来的位置中
1 切换成光盘启动,进入挽救模式:
2 执行chroot /mnt/sysimage ,mount /dev/cdrom /media ,cd /media/Packages
3 拷贝完整的内核文件: cp kernel-3.10.0-514.el7.x86_64.rpm /mnt
4 cd /mnt 执行 rpm2cpio kernel-3.10.0-514.el7.x86_64 | cpio -id
5 cd boot
6 cp vmlinuz-3.10.0-514.el7.x86_64 /boot
7 exit exit 然后切换成硬盘启动
实验:
模拟内核文件丢失:
切换为光盘启动,进入挽救模式,将光盘中的内核文件拷贝得到:
问题(4):系统初始化镜像文件丢失。内核启动,initrd文件至关重要,initrd(Initial RAM Disk),它在GRUB stage2这个步骤就被拷贝到了内存中,这个文件是在安装系统时产生的,是一个临时的根文件系统(rootfs)。因为Kernel为了精简,只保留了最基本的模块,因此,Kernel上并没有各种硬件的驱动程序,也就无法识rootfs所在的设备,故产生了initrd这个文件,该文件装载了必要的驱动模块,当Kernel启动时,可以从initrd文件中装载驱动模块,直到挂载真正的rootfs,然后将initrd从内存中移除。
模拟: rm -rf /boot/initramfs-3.10.0-123.e17.x86_64.img
解决:
当系统重新启动后
进入挽救模式
1)当系统没有重启时:mkinitrd /boot/initramfs-$(umane -r).img $(uname -r)
2)当系统重启后:切换成光盘启动,进入挽救模式
chroot /mnt/sysimage
mkinitrd /boot/initramfs-$(uname -r).img $(uname -r)
exit两次 切换成硬盘启动
实验:
模拟虚拟根文件系统丢失,系统未重启前,可以直接挽救:
系统重启后,可以在挽救模式下执行:
问题(5):/boot分区不存在,一步一步恢复所需要的东西。grub程序,内核文件,grub配置文件。
实验:
模拟问题(6):当开机启动级别出现问题,如果被改为重启级别,系统会一直重启,无法开机。
解决:
1 开机按上下键按“E”进入编辑模式
2 选择内核启动行 linux16 /vmlinuz-xxxxxxx ro xxxxxxxxxxxxx 改为: linux16 /vmlinuz-xxxxxxxx ro xxxxxxxxxx
3 启动系统 然后在系统中重新设定 systemctl set-default graphical.target
4 然后ctrl +x
实验:
模拟问题(7):系统root密码忘记
解决:
1 在系统启动阶段按上下健停止系统引导,按“E”进行编辑
2 找到linux16引导条目这一行,从这行最后删除到ro选项,并把ro改为rw,然后添加rd.break选项
3 ctrl+x启动设定过后的系统引导条目 chroot /sysroot/ ,切换到真实的系统环境
修改密码:echo westos | passwd --stdin root
4 建立文件/.autorelabel让系统从新扫描所有文件
5 exit两次使系统自动重新启动
实验:
启动按上下键按E进入编辑模式: