linux bootloader与grub


一.bootloader:Grub2

回到顶部

bootloader是加载linux內核的重要工具,目前linux下主流的bootloader就是grub2!
系统开机启动执行的第一个程序是BIOS,BIOS在完成开机自检后就会读取第一个启动设备的MBR。 并加载MBR中存放的bootloader。
bootloader具有菜单选项功能、加载linux內核文件以及控制权移交等功能, 系统必须要有 loader 才有办法加载该操作系统的內核就是了。
MBR是整个硬盘的第一个扇区sector,总共就512字节,最后64字节用来存储磁盘分区表信息, 只有446bytes可用来存放bootloader代码。即使是GPT也没有很大的扇区来储存bootloader的数据。
在安装linux的时候,将bootloader分为两个部分,主程序代码部分写入MBR扇区,而相关的配置文件则写入/boot目录下。
在开机启动的时候,bootloader会去/boot目录下读取自己的配置文件grub.cfg。经常将/boot作为单独的分区。 grub2相关的配置文件都存放在/boot/grub2目录下:

            [root@initroot ~]# ls -al /boot/grub2/
            total 52
            drwx------. 5 root root  4096 Aug  6  2019 .
            dr-xr-xr-x. 5 root root  4096 Aug  6  2019 ..
            -rw-r--r--. 1 root root    64 Oct 15  2017 device.map         #grub2的设备对应文件(底下会谈到)
            drwxr-xr-x. 2 root root  4096 Oct 15  2017 fonts              #开机过程中的画面会使用到的字型数据
            -rw-------  1 root root  6027 Aug  6  2019 grub.cfg           #grub2 的主配置文件!相当重要!
            -rw-------  1 root root  5189 Aug  6  2019 grub.cfg.1565084671.rpmsave
            -rw-r--r--. 1 root root  1024 Aug  6  2019 grubenv            #一些环境区块的符号
            drwxr-xr-x. 2 root root 12288 Oct 15  2017 i386-pc            #针对一般 x86 PC 所需要的 grub2 的相关模块
            drwxr-xr-x. 2 root root  4096 Oct 15  2017 locale             #就是语系相关的数据啰
            drwxr-xr-x. 2 root root  4096 Oct 15  2019 themes             #一些开机主题画面数据
          
i386-pc目录下存放着适用于i386平台的grub2相关模块:
            [root@initroot ~]# ls -l /boot/grub2/i386-pc
            -rw-r--r--. acpi.mod #电源管理有关的模块
            -rw-r--r--. ata.mod #磁盘有关的模块
            -rw-r--r--. chain.mod #进行 loader 控制权移交的相关模块
            -rw-r--r--. command.lst #一些指令相关性的列表
            -rw-r--r--. efiemu32.o #底下几个则是与 uefi BIOS 相关的模块
            -rw-r--r--. efiemu64.o -rw-r--r--. efiemu.mod -rw-r--r--. ext2.mod #EXT 文件系统家族相关模块
            -rw-r--r--. fat.mod #FAT 文件系统模块
            -rw-r--r--. gcry_sha256.mod #常见的加密模块
            -rw-r--r--. gcry_sha512.mod -rw-r--r--. iso9660.mod #光盘文件系统模块
            -rw-r--r--. lvm.mod #LVM 文件系统模块
            -rw-r--r--. mdraid09.mod #软件磁盘阵列模块
            -rw-r--r--. minix.mod #MINIX 相关文件系统模块
            -rw-r--r--. msdospart.mod #一般 MBR 分区表
            -rw-r--r--. part_gpt.mod #GPT 分区表
            -rw-r--r--. part_msdos.mod #MBR 分区表
            -rw-r--r--. scsi.mod #SCSI 相关模块
            -rw-r--r--. usb_keyboard.mod #底下两个为 USB 相关模块
            -rw-r--r--. usb.mod -rw-r--r--. vga.mod #VGA 显示适配器相关模块
            -rw-r--r--. xfs.mod #XFS 文件系统模块
          
上面仅列出了部分模块!/boot/grub2/目录下最重要的就是配置文件grub2.cfg以及i386-pc目录下各种文件系统模块的定义! bootloader读取文件系统模块后,就可以识别文件系统并读取文件系统中的內核文件了。
总体上,grub2有如下优点:
支持较多的文件系统与磁盘分区格式,grub2可以直接识别文件系统中的內核文件;
开机的时候,可以自行编辑与修改开机设置项目,类似bash的指令模式;
可以动态识别配置文件,而不需要在修改配置文件后重新安装grub2。即修改完配置文件/boot/grub2/grub.cfg后,下次开机配置直接生效!

磁盘与分区在grub2中的代号

回到顶部

bootloader grub2最重要的任务就是从磁盘中加载內核文件, grub2必须要能够识别到硬盘才行! grub2中的硬盘代号与Linux磁盘设备文件名是完全不同的! grub2对硬盘的识别使用的是如下的代号:
(hd0,1) #默认语法,由grub2自动判断分区格式
(hd0,msdos1) #磁盘的分区为传统的MBR模式
(hd0,gpt1) # 磁盘的分区为GPT模式
硬盘代号以小括号( )括起来;
硬盘以hd后接数字编号表示;以识别顺序做为硬盘的编号!(这个重要!)
第一个识别到的硬盘为0号,第二个为1号,以此类推;
每颗硬盘的第一个partition代号为1 ,依序类推。
第一颗识别到的硬盘代号为:(hd0),该硬盘的第一个分区为(hd0,1),另外为了区分不同的分区格式, 磁盘后面的分区编号可以使用类似msdos1与gpt1的方式来调整! 磁盘的编号是由0开始,分区的编号则由1开始! 由于BIOS可以调整磁盘的开机顺序,磁盘对应的(hdN)那个编号N可能是会变动的!
所以说,整个硬盘代号为:
硬盘识别顺序
在Grub2中的代号
第一颗(MBR) (hd0) (hd0,msdos1) (hd0,msdos2) (hd0,msdos3)....
第二颗(GPT) (hd1) (hd1,gpt1) (hd1,gpt2) (hd1,gpt3)....
第三颗(hd2) (hd2,1) (hd2,2) (hd2,3)....
第一颗硬盘的MBR安装处的硬盘代号就是(hd0), 第一颗硬盘的第一个分区的bootsector代号就是(hd0,msdos1) 第一颗硬盘的第一个逻辑分区的bootsector代号为(hd0,msdos5)!
假设系统仅有一颗SATA硬盘,该硬盘的第一个逻辑分区在Linux与grub2当中的文件名与代号:
Linux中的文件名为/dev/sda5(1~4保留给primary与extended)。
grub2中的磁盘代号是(hd0,msdos5)或(hd0,5)。

grub2配置文件/boot/grub2/grub.cfg

回到顶部

CentOS grub2配置文件/boot/grub2/grub.cfg内容如下:

            [root@initroot ~]# vim /boot/grub2/grub.cfg
            # 开始是 /etc/grub.d/00_header 这个脚本执行的结果展示,主要与基础设置与环境有关
            ### BEGIN /etc/grub.d/00_header ###
            set pager=1
            if [ -s $prefix/grubenv ]; then
            load_env
            fi
            .....(中间省略).....if [ x$feature_timeout_style = xy ] ; then
            set timeout_style=menu
            set timeout=5
            # Fallback normal timeout code in case the timeout_style feature is
            # unavailable.
            else
            set timeout=5
            fi
            ### END /etc/grub.d/00_header ###
            # 开始执行 /etc/grub.d/10_linux,主要针对实际的 Linux 內核文件的开机环境
            ### BEGIN /etc/grub.d/10_linux ###
            menuentry 'CentOS Linux 7 (Core), with Linux 3.10.0-229.el7.x86_64' --class rhel fedora \
            --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option
            \
            'gnulinux-3.10.0-229.el7.x86_64-advanced-299bdc5b-de6d-486a-a0d2-375402aaab27' {
            load_video
            set gfxpayload=keep
            insmod gzio
            insmod part_gpt
            insmod xfs
            set root='hd0,gpt2'
            if [ x$feature_platform_search_hint = xy ]; then
            search --no-floppy --fs-uuid --set=root --hint='hd0,gpt2'
            94ac5f77-cb8a-495e-a65b-...
            else
            search --no-floppy --fs-uuid --set=root 94ac5f77-cb8a-495e-a65b-2ef7442b837c
            fi
            linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/mapper/centos-root ro
            \
            rd.lvm.lv=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet \
            LANG=zh_TW.UTF-8
            initrd16 /initramfs-3.10.0-229.el7.x86_64.img
            }
            ### END /etc/grub.d/10_linux ###
            .....(中间省略).....
            ### BEGIN /etc/grub.d/30_os-prober ###
            ### END /etc/grub.d/30_os-prober ###
            ### BEGIN /etc/grub.d/40_custom ###
            ### END /etc/grub.d/40_custom ###
            .....(底下省略).....
          
grub2不希望用户修改grub.cfg配置文件,而是修改几个特定的配置文件,然后使用grub2-mkconfig命令产生新的grub.cfg文件。 不过还是得要了解一下grub2.cfg文件的大致内容。 grub.cfg文件的最开始部份,大多是环境设置与默认值设置等,比较重要的是默认由哪个选项开机(set default)以及默认的秒数(set timeout), 然后是每一个菜单选项的设置,就是在menuentry这个设置值之后的项目! 在默认的配置文件当中是有两个menuentry的,也就是说,在开机的时候应该就会有两个可以选择的菜单选项!
menuentry之后会有几个项目的规范,包括--class, --unrestricted --id等的指定项目, 之后通过{ }将这个菜单选项会用到的数据框起来, 在选择这个菜单选项之后就会进行括号内的动作的意思。
如果真的点选了这个菜单选项,那 grub2 首先会加载模块,例如上表中的load_video, insmod gzio,insmod part_gpt, insmod xfs等项目, 都是在加载要读取內核文件所需要的磁盘、分区、文件系统、解压缩等驱动程序。
之后就是三个比较重要的项目:
set root='hd0,gpt2'
root为grub2配置文件所在的磁盘设备。我们的测试机当初安装的时候分区出/与/boot两个分区, 而grub2是在/boot/grub2这个位置上, 而这个位置的磁盘文件名为/dev/vda2,因此完整的grub2磁盘名称就是(hd0,2)! 因为我们的系统用的是GTP的磁盘分区格式, 因此全名就是hd0,gpt2!
linux16 /vmlinuz-... root=/dev/mapper/centos-root ...
这个就是Linux內核文件以及內核执行时传递的内核参数。內核文件不是/boot/vmlinuz-xxx吗?怎么这里的设置是在根目录呢? 这个跟上面的root有关啦!大部分的系统大多有/boot这个分区,如果/boot没有分区, 那会是怎么回事呢?我们用底下的迭代来说明一下:
如果没有 /boot 分区,仅有 / 分区:所以文件名会这样变化喔:
/boot/vmlinuz-xxx -> (/)/boot/vmlinuz-xxx -> (hd0,msdos1)/boot/vmlinuz-xxx
如果 /boot 是独立分区,则文件名的变化会是这样:
/boot/vmlinuz-xxx -> (/boot)/vmlinuz-xxx -> (hd0,msdos1)/vmlinuz-xxx
linux16后面接的文件名得要跟上面的root搭配在一起,才是完整的绝对路径文件名!
至于linux16 /vmlinuz-xxx root=/file/name那个root指的是linux文件系统中,根目录所在的分区设备!
从本章一开始的开机流程中,我们就知道內核会主动去挂载根目录,并且从根目录中读取配置文件, 再进一步开始开机流程。
所以,內核文件后面一定要接根目录的设备啊!
我们从/etc/fstab里面也知道根目录的挂载可以是设备文件名、UUID与LABEL名称,因此这个root后面也是可以带入类似root=UUID=1111.2222.33...!
initrd16 /initramfs-3.10...
这个就是initramfs所在的文件名,跟linux16那个vmlinuz-xxx相同,这个文件名也是需要搭配set root=xxx项目的设备,才会得到正确的位置!

grub2配置文件维护/etc/default/grub与/etc/grub.d

回到顶部

grub2的主配置文件为grub.cfg,但是因为该文件的内容太过复杂,数据量非常庞大,grub2官方说明不建议用户手动修改! 而是应该通过/etc/default/grub这个环境配置文件与/etc/grub.d/目录内的相关配置文件来处理!
/etc/default/grub环境配置文件的内容如下:

            [root@initroot ~]# cat /etc/default/grub
            GRUB_TIMEOUT=5                    #指定默认倒数读秒的秒数
            GRUB_DEFAULT=saved                #指定默认由哪一个菜单选项来开机,默认开机菜单选项之意
            GRUB_DISABLE_SUBMENU=true         #是否要隐藏次菜单选项,通常是藏起来的好!
            GRUB_TERMINAL_OUTPUT="console"    #指定数据输出的终端机格式,默认是通过文字终端机
            GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet"  #就是在menuentry括号内的linux16项目后续的內核参数
            GRUB_DISABLE_RECOVERY="true"      #取消救援菜单选项的制作
          
几个重要的设定项目说明如下:
倒数时间参数:GRUB_TIMEOUT
这个设置值相当简单,后面接要倒数的秒数即可。例如要等待30秒,就在这边改成GRUB_TIMEOUT=30! 如果不想等待则输入0,如果一定要用户选择,则填-1即可!
是否隐藏菜单选项项目:GRUB_TIMEOUT_STYLE
可选择的设置值有menu, countdown, hidden等。这个项目主要是在设置要不要显示菜单选项! 如果没有设置默认是menu。如果不想要让用户看到菜单选项, 可以设置为countdown!countdown会在屏幕上显示剩余的等待秒数,而hidden则不会显示。除非有特定的需求,一般建议设置为menu!
讯息输出的终端机模式:GRUB_TERMINAL_OUTPUT
指定输出的画面应该使用哪一个终端机来显示,主要的设置值有console, serial, gfxterm, vga_text等。一般使用console!
默认开机菜单选项项目:GRUB_DEFAULT
这个项目在指定要用哪一个菜单选项(menuentry)来作为默认开机。 能使用的设置值包括有saved, 数字, title名, ID名等。 假设有个menuentry项目:
menuentry '1st linux system' --id 1st-linux-system { ...}
menuentry '2nd linux system' --id 2nd-linux-system { ...}
menuentry '3rd win system' --id 3rd-win-system { ...}
几个常见的设置值是这样的:
GRUB_DEFAULT=1
代表使用第二个 menuentry 开机,因为数字的编号是以 0 号开始编的!
GRUB_DEFAULT=3rd-win-system
代表使用第三个menuentry开机,因为里头代表的是ID的项目!它会找到--id!
GRUB_DEFAULT=saved
代表使用grub2-set-default来设置哪一个menuentry为默认值。 通常默认为0。一般来说,默认就是以第一个开机菜单选项来作为默认项目,如果想要有不同的菜单选项设置,可以在这个项目填选所需要的--id。id不应该重复!
內核的外加参数功能:GRUB_CMDLINE_LINUX
这里加入內核在启动的时候还需要加入额外的参数! 举例来说,如果你除了预设的內核参数之外,还需要让你的磁盘读写机制为deadline, 可以这样处理:
GRUB_CMDLINE_LINUX="..... crashkernel=auto rhgb quiet elevator=deadline"
在暨有的项目之后加上如同上表的设置,这样就可以在开机时额外的加入磁盘读写的机制项目设定了!
更多内容可以参考info grub。
额外设置的项目就是设置/etc/default/grub文件。
该环境配置文件编写完毕后必须要使用grub2-mkconfig来重建grub.cfg!毕竟grub.cfg文件才是grub2要真正读取的配置文件,
假设需要
(1)开机菜单选项等待40秒钟、
(2)默认用第一个菜单选项开机、
(3)菜单选项请显示出来不要隐藏、
(4)內核外带elevator=deadline的参数值,
那应该要如何处理grub.cfg呢?直接编辑主要环境配置文件后,再以 grub2-mkconfig 来重建 grub.cfg!
1. 先编辑主要环境配置文件/etc/default/grub:
            [root@initroot ~]# vim /etc/default/grub
            GRUB_TIMEOUT=40
            GRUB_DEFAULT=0
            GRUB_TIMEOUT_STYLE=menu
            GRUB_DISABLE_SUBMENU=true
            GRUB_TERMINAL_OUTPUT="console"
            GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb
            quiet elevator=deadline"
            GRUB_DISABLE_RECOVERY="true"
          
2. 使用grub2-mkconfig重建grub.cfg文件:
            [root@initroot ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
            Generating grub configuration file ...Found linux image: /boot/vmlinuz-3.10.0-229.el7.x86_64
            Found initrd image: /boot/initramfs-3.10.0-229.el7.x86_64.img
            Found linux image: /boot/vmlinuz-0-rescue-309eb890d09f440681f596543d95ec7a
            Found initrd image: /boot/initramfs-0-rescue-309eb890d09f440681f596543d95ec7a.img
            done
          
3. 检查grub.cfg文件的内容是否真的是改变了:
            [root@initroot ~]# grep timeout /boot/grub2/grub.cfg
            set timeout_style=menu
            set timeout=40
            [root@initroot ~]# grep default /boot/grub2/grub.cfg
            set default="0"
            [root@initroot ~]# grep linux16 /boot/grub2/grub.cfg
            linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/.... elevator=deadline
            linux16 /vmlinuz-0-rescue-309eb890d09f440681f5965.... elevator=deadline
          
菜单选项建置的脚本 /etc/grub.d/* 你应该会觉得很奇怪, grub2-mkconfig执行之后,屏幕怎么会主动的去抓到linux的內核,还能够找到对应內核版本的 initramfs 呢? 其实grub2-mkconfig会去分析/etc/grub.d/*里面的文件,然后执行该文件来建置grub.cfg! /etc/grub.d/* 里面的文件就显得很重要了。一般来说,该目录下会有这些文件存在:
00_header:主要在建立初始的显示项目,包括需要加载的模块分析、屏幕终端机的格式、倒数秒数、菜单选项是否需要隐藏等, 大部分在/etc/default/grub里面所设置的变量,大概都会在这个脚本当中被利用来重建grub.cfg。
10_linux:根据分析/boot底下的文件,尝试找到正确的linux內核与读取这个內核需要的文件系统模块与参数等, 都在这个脚本运作后找到并设置到grub.cfg中。这个脚本会将所有在/boot底下的每一个內核文件都对应到一个菜单选项, 因此內核文件数量越多,开机菜单选项就越多了。 如果未来你不想要旧的內核出现在菜单选项上,就可以移除旧內核文件。
30_os-prober:这个脚本默认会到系统上找其他的 partition 里面可能含有的操作系统,然后将该操作系统做成菜单选项来处理就是了。 如果你不想要让其他的操作系统被侦测到并拿来开机,那可以在/etc/default/grub里面加上GRUB_DISABLE_OS_PROBER=true取消这个文件的运作。
40_custom:如果你还有其他想要自己手动加上去的菜单选项项目,或者是其他的需求,那么建议在这里补充即可!
一般来说,我们会更动到的就是仅有40_custom这个文件。那这个文件内容也大多在放置管理员自己想要加进来的菜单选项项目就是了。 我们知道menuentry就是一个选单,那后续的项目有哪些东西呢?简单的说,就是这个menuentry有几种常见的设置? 亦即是menuentry的功能啦!常见的有这几样:
直接指定內核开机
基本上如果是Linux的內核要直接被用来开机,那么你应该要通过grub2-mkconfig去抓10_linux这个脚本直接制作即可, 因此这个部份你不太需要记忆! 因为在 grub.cfg 当中就已经是系统能够捉到的正确的內核开机菜单选项了! 不过如果你有比较特别的参数需要进行呢?这时候你可以这样作:
(1)先到grub.cfg当中取得你要制作的那个內核的菜单选项项目,然后将它复制到40_custom 当中
(2)再到40_custom当中依据你的需求修改即可。
如果你想要使用第一个原有的menuentry取出来后,增加一个选单,该选单可以强制systemd使用graphical.target来启动Linux系统, 让该菜单选项一定可以使用图形界面而不用理会default.target的连结,该如何设计?
当內核外带参数中,有个systemd.unit=???的外带参数可以指定特定的target开机!先到grub.cfg当中复制第一个menuentry,然后进行如下的设置:
            [root@initroot ~]# vim /etc/grub.d/40_custom
            menuentry 'My graphical CentOS, with Linux 3.10.0-229.el7.x86_64' --class rhel fedora
            --class gnu-linux --class gnu --class os --unrestricted --id 'mygraphical' {
            load_video
            set gfxpayload=keep
            insmod gzio
            insmod part_gpt
            insmod xfs
            set root='hd0,gpt2'
            if [ x$feature_platform_search_hint = xy ]; then
            search --no-floppy --fs-uuid --set=root --hint='hd0,gpt2'
            94ac5f77-cb8a-495e-a65b-...
            else
            search --no-floppy --fs-uuid --set=root 94ac5f77-cb8a-495e-a65b-2ef7442b837c
            fi
            linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/mapper/centos-root ro rd.lvm.lv=
            centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet
            elevator=deadline systemd.unit=graphical.target
            initrd16 /initramfs-3.10.0-229.el7.x86_64.img
            }
          
上面的资料都是从grub.cfg里面复制过来的!
            [root@initroot ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
            
再次reboot时,系统就会多出一个菜单选项了!选择该菜单选项后,系统就可以直接进入图形界面(必须安装X window),而不必考虑default.target了!
通过chainloader方式移交loader控制权 所谓的chain loader(开机管理程序的链结)仅是在将控制权交给下一个bootloader, 所以grub2并不需要认识与找出kernel的文件名 ,
他只是将boot的控制权交给下一个boot sector或MBR 内的 bootloader而已 所以通常也不需要去查验下一个bootloader的文件系统! 一般来说, chain loader的设置只要两个就够了,一个是预计要前往的boot sector所在的分区代号, 另一个则是设置chainloader在那个分区的boot sector (第一个扇区)上! 假设Windows分区在/dev/sda1,且只有一颗硬盘,那么要grub将控制权交给windows的loader只要这样就够了:
            menuentry "Windows" {
            insmod chain                    #要先加载 chainloader 的模块对吧?
            insmod ntfs                     #建议加入windows所在的文件系统模块较佳!
            set root=(hd0,1)                #是在哪一个分区~最重要的项目!
            chainloader +1                  #请去boot sector将loader软件读出来的意思!
            }
          
通过这个项目就可以让grub2交出控制权了!
假设测试系统上面使用MBR分区,并且出现如下的数据:
            [root@initroot ~]# fdisk -l /dev/vda
            Device Boot
            Start End Blocks Id System
            2048 10487807 5242880 83 Linux
            10487808 178259967 83886080 7 178259968 241174527 31457280 83
            /dev/vda1
            /dev/vda2
            /dev/vda3
            *
            HPFS/NTFS/exFAT
            Linux
          
其中/dev/vda2使用是windows 7的操作系统。现在我需要增加两个开机选项,一个是取得windows 7的开机菜单选项, 一个是回到MBR的默认环境,应该如何处理呢?
windows 7在/dev/vda2亦即是hd0,msdos2这个地方,而MBR则是hd0即可,不需要加上分区!整个设置会变这样:
            [root@initroot ~]# vim /etc/grub.d/40_custom
            menuentry 'Go to Windows 7' --id 'win7' {
            insmod chain
            insmod ntfs
            set root=(hd0,msdos2)
            chainloader +1
            }
            menuentry 'Go to MBR' --id 'mbr' {
            insmod chain
            set root=(hd0)
            chainloader +1
            }
          
            [root@initroot ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
          
如果每次都想要让windows变成默认的开机选项,那么在/etc/default/grub当中设定好GRUB_DEFAULT=win7然后再次grub2-mkconfig! 不用算menuentry的顺序编号!通过 --id内容即可!
19.3.4 initramfs 的重要性与建立新 initramfs 文件 initramfs的目的在于提供开机过程中所需要的最重要內核模块,以让系统开机过程可以顺利完成。 会需要initramfs的原因,是因为內核模块放置于/lib/modules/$(uname -r)/kernel/当中, 这些模块必须要根目录(/)被挂载才能够被读取。 如果內核本身不具备磁盘的驱动程序, 就会无法挂载根目录,也就没有办法取得驱动程序,也就无法正常开机了。
initramfs可以将/lib/modules/...内的开机过程中需要的模块打包成一个initramfs文件, 在开机时通过主机的INT 13硬件功能将该文件读出来解压缩,initramfs在内存内会仿真成为根目录, 此虚拟文件系统(Initial RAM Disk)主要包含磁盘与文件系统模块,因此我们的內核最后就能够认识实际的磁盘,那就能够进行实际根目录的挂载啦! 所以说initramfs内所包含的模块大多是与开机过程有关,而主要以文件系统及硬盘模块(如 usb, SCSI 等)为主!
一般来说,需要initramfs的时刻为:
根目录所在磁盘为SATA、USB 或 SCSI等连接接口;
根目录所在文件系统为LVM, RAID等特殊格式;
根目录所在文件系统为非传统Linux认识的文件系统时;
其他必须要在內核加载时提供的模块。
之前忽略 initrd 这个文件的重要性,是因为很穷... ^_^。因为的 Linux 主 机都是较早期的硬件, 使用的是 IDE 接口的硬盘,而且并没有使用 LVM 等特殊格式的文件系统,而 Linux 核 心本身就认识 IDE 接口的磁盘, 因此不需要 initramfs 也可以顺利开机完成的。自从 SATA 硬盘流行起来后,没 有 initramfs 就没办法开机了! 因为 SATA 硬盘使用的是 SCSI 模块来驱动的,而 Linux 默认将 SCSI 功能编译成为模块....
一般来说,各distribution提供的內核都会附上initramfs文件,但如果妳有特殊需要所以想重制initramfs文件的话, 可以使用dracut或mkinitrd 来处理的。这个文件的处理方式很简单, man dracut或man mkinitrd就知道了!。 CentOS 7应该要使用dracut才对,不过mkinitrd还是有保留下来!
            [root@initroot ~]# dracut [-fv] [--add-drivers 列表] initramfs 文件名 內核版本
          
选项与参数:
-f :强迫编译出 initramfs ,如果 initramfs 文件已经存在,则覆盖掉旧文件
-f :显示 dracut 的运作过程
--add-drivers列表:在原本的默认內核模块中,增加某些你想要的模块!模块位于內核所在目录/lib/modules/$(uname -r)/kernel/*
initramfs文件名:就是你需要的文件名!开头最好就是 initramfs,后面接版本与功能 內核版本 :默认当然是目前运作中的內核版本,不过你也可以手动输入其他不同版本!
--modules :将 dracut 所提供的开机所需模块(內核核模块)加载,可用模块在底下的目录内/usr/lib/dracut/modules.d/
--gzip|--bzip2|--xz:尝试使用哪一种压缩方式来进行initramfs压缩。默认使用 gzip!
--filesystems :加入某些额外的文件系统支持!
以dracut的默认功能建立一个initramfs虚拟磁盘文件:
            [root@initroot ~]# dracut -v initramfs-test.img $(uname -r)
            Executing: /sbin/dracut -v initramfs-test.img 3.10.0-229.el7.x86_64
            # 先加载 dracut 本身的模块支持
            *** Including module: bash ***
            *** Including module: nss-softokn ***
            *** Including modules done ***
            .....(中间省略)..... # 底下两行在处理內核模块
            *** Installing kernel module dependencies and firmware ***
            *** Installing kernel module dependencies and firmware done ***
            .....(中间省略).....
            *** Generating early-microcode cpio image ***
            # 建立微指令集
            *** Constructing GenuineIntel.bin ****
            *** Store current command line parameters ***
            *** Creating image file ***
            # 开始建立 initramfs 啰!
            *** Creating image file done ***
          
额外加入e1000e网卡驱动与ext4/nfs文件系统在新的initramfs内:
            [root@initroot ~]# dracut -v --add-drivers "e1000e" --filesystems "ext4 nfs" \
            > initramfs-new.img $(uname -r)
            [root@initroot ~]# lsinitrd initramfs-new.img
            | grep -E '(e1000|ext4|nfs)'
            usr/lib/modules/3.10.0-229.el7.x86_64/kernel/drivers/net/ethernet/intel/e1000e
            usr/lib/modules/3.10.0-229.el7.x86_64/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko
            usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/ext4
            usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/ext4/ext4.ko
            usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/nfs
            usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/nfs/nfs.ko
          
可以看得到,新增的模块现在正在新的initramfs当中了!
initramfs建立完成之后,同时內核也处理完毕后,我们就可以使用grub2来建立菜单选项了! 19.3.5 测试与安装 grub2 如果你的 Linux 主机本来就是使用 grub2 作为 loader 的话,那么你就不需要重新安装 grub2 了, 因为grub2本来就会主动去读取配置文件啊! 但如果你的 Linux 原来使用的并非 grub2 ,那么就需要来安装啦!首先,你必须要使用grub-install将一些必要的文件复制到/boot/grub2里面去:
            [root@initroot ~]# grub2-install [--boot-directory=DIR] INSTALL_DEVICE
          
选项与参数:
--boot-directory=DIR :DIR为实际的目录,使用grub2-install默认会将grub2所有的文件都复制到/boot/grub2/*,如果想要复制到其他目录与设备去,就得要用这个参数。
INSTALL_DEVICE 安装的设备代号!
将grub2安装在目前系统的MBR底下,我的系统为/dev/vda:
            [root@initroot ~]# grub2-install /dev/vda
          
原本/dev/vda就是使用grub2,所以似乎不会出现什么特别的讯息。
如果去查阅一下/boot/grub2的内容,会发现所有的文件都更新了,因为我们重装了!
但是注意到,我们并没有配置文件喔!那要自己建立!
基本上,grub2-install大概仅能安装grub2主程序与相关软件到/boot/grub2/那个目录去,如果后面的设备填的是整个系统(/dev/vda, /dev/sda...), 那loader的程序才会写入到MBR里面去。如果是XFS文件系统的/dev/vda2设备的话(个别 partition), 那grub2-install就会告诉你,该文件系统并不支持grub2的安装!也就是你不能用grub2-install将你的主程序写入到boot sector里头去! 可以强迫写入一下看看!
尝试看一下你的系统中有没有其他的xfs文件系统,且为传统的partition类型
            [root@initroot ~]# df -T |grep -i xfs
            /dev/mapper/centos-root xfs
            10475520 4128728
            6346792 40% /
            /dev/mapper/centos-home xfs 5232640
            665544 4567096 13% /home
            /dev/mapper/raidvg-raidlv xfs 1558528 33056 1525472 /dev/vda2 xfs 1038336 144152 894184 /dev/vda4 xfs 1038336 63088 975248
            3% /srv/raidlvm
            14% /boot
            7% /srv/myproject
          
仅有/dev/vda4比较适合做个练习,将grub2主程序安装到/dev/vda4去看看!
            [root@initroot ~]# grub2-install /dev/vda4
            Installing for i386-pc platform.
            grub2-install: error: hostdisk//dev/vda appears to contain a xfs filesystem which isn't
            known to reserve space for DOS-style boot.
            Installing GRUB there could result in
            FILESYSTEM DESTRUCTION if valuable data is overwritten by grub-setup (--skip-fs-probe
            disables this check, use at your own risk).
          
说是xfs恐怕不能支持你的boot sector概念!这个应该是误判!所以我们还是给它强制装一下:
            [root@initroot ~]# grub2-install --skip-fs-probe /dev/vda4
            Installing for i386-pc platform.
            grub2-install: warning: File system ‘xfs’ doesn't support embedding.
            grub2-install: warning: Embedding is not possible.
            setup by using blocklists.
            GRUB can only be installed in this
            However, blocklists are UNRELIABLE and their use is
            discouraged..
            grub2-install: error: will not proceed with blocklists.
          
失败!因为还是担心xfs被搞死~好!没问题!加个--force与--recheck重新处理一遍:
            [root@initroot ~]# grub2-install --force --recheck --skip-fs-probe /dev/vda4
            Installing for i386-pc platform.
            grub2-install: warning: File system ‘xfs’ doesn't support embedding.
            grub2-install: warning: Embedding is not possible.
            setup by using blocklists.
            GRUB can only be installed in this
            However, blocklists are UNRELIABLE and their use is
            discouraged..
            Installation finished. No error reported.
          
原本是无法安装的错误,现在仅有warning警告讯息,所以这样就安装到partition上了! 上面这样就将grub2的主程序安装到/dev/vda4以及重新安装到MBR里面去了。 我们知道grub2主程序会去找grub.cfg这个文件,大多是在/boot/grub2/grub.cfg里面, 我们的MBR与/dev/vda4都是到/boot/grub2/grub.cfg去抓设置吗? 如果是多重操作系统那怎办?这就需要重新进入新系统才能够安装啦:
假设测试系统上面使用MBR分区,并且出现如下的数据:
              [root@initroot ~]# fdisk -l /dev/vda
              Device Boot
              /dev/vda1
              /dev/vda2
              /dev/vda3
              *
              Start End Blocks Id System
              2048 10487807 5242880 83 Linux
              10487808 178259967 83886080 7 178259968 241174527 31457280 83
              HPFS/NTFS/exFAT
              Linux
            
其中/dev/vda1, /dev/vda3是两个CentOS 7系统,而/dev/vda2是windows 7系统。 安装的流程是依序/dev/vda1 -> /dev/vda2 -> /dev/vda3。 因此,安装好而且重新启动后,系统其实是默认进入 /dev/vda3 这个 CentOS 7 的系统的。 此时 MBR 会去读取的配置文件在(/dev/vda3)/boot/grub2/grub.cfg。
因为/dev/vda1应该是用来管理开机菜单选项的,而/dev/vda2及/dev/vda3在规划中就是用来让学生操作的, 默认情况下,/dev/vda1内的CentOS系统应该只会在开机的时候用到,或者是出问题时会找他来使用。 至于 /dev/vda3 及 /dev/vda2 则可能因为学生的误用, 因此未来可能会升级或删除或重灌等。 那妳如何让系统永远都是使用/dev/vda1开机?
因为MBR的bootloader应该要去(/dev/vda1)/boot/grub2/grub.cfg读取相关设置才是正常的! 所以,你可以使用几种基本的方式来处理:
CentOS 7会主动找到其他操作系统,因此可以在/dev/vda3的开机菜单选项中找到/dev/vda1的开机选项,请用该选项进入系统,你就能够进入/dev/vda1了!
假设没能抓到/dev/vda1,那妳可以在/dev/vda3底下使用chroot来进入/dev/vda1! 使用救援光盘去抓到正确的/dev/vda1,然后取得/dev/vda1的系统!
等到进入系统后, 修改/etc/default/grub及/etc/grub.d/40_custom之后 , 使用grub2-mkconfig -o /boot/grub2/grub.cfg, 重新grub2-install /dev/vda就能够让你的MBR去取得/dev/vda1内的配置文件了!
测试机目前为40秒倒数,且有一个强制进入图形界面的My graphical CentOS7菜单选项! 现在我们想要多加两个菜单选项,一个是回到MBR的chainloader,一个是使用/dev/vda4的chainloader,
因为没有必要重新安装grub2 ,直接修改即可。修改40_custom成为这样:
              [root@initroot ~]# vim /etc/grub.d/40_custom
              # 最底下加入这两个项目即可!
              menuentry 'Goto MBR' {
              insmod chain
              insmod part_gpt
              set root=(hd0)
              chainloader +1
              }
              menuentry 'Goto /dev/vda4' {
              insmod chain
              insmod part_gpt
              set root=(hd0.gpt4)
              chainloader +1
              }
              [root@initroot ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
            
最后总结一下:
1. 如果是从其他bootloader转成grub2时,得先使用grub2-install安装grub2配置文件;
2. 承上,如果安装到partition,可能需要加上额外的许多参数才能够顺利安装上去!
3. 开始编辑/etc/default/grub及/etc/grub.d/*这几个重要的配置文件;
4. 使用grub2-mkconfig -o /boot/grub2/grub.cfg来建立开机的配置文件!

开机前的额外功能修改

回到顶部

事实上,前几个小节设置好之后,你的 grub2 就已经在你的 Linux 系统上面了,而且同时存在于MBR 与 boot sector 当中呢! 所以,我们已经可以重新启动来查阅看看啦! 另外,如果你正在进行 开机,那么请注意,我们可以在默认菜单选项 (的范例当中是 40 秒) 按下任意键, 还可以进行 grub2的在线编修功能喔! 真是棒啊!先来看看开机画面吧! 图 19.3.1、grub2 开机画面示意图 由于默认菜单选项就没有隐藏,因此你会直接看到这 5 个菜单选项而已,同时会有读秒的咚咚在倒数。 菜单选项 部分的画面其实就是 menuentry 后面的文字啦!你现在知道如何修改 menuentry 后面的文字了吧!
然后如果你点选了Goto MBR与Goto /dev/vda4时,怪了!怎么发现到菜单选项又重新回来了呢? 这是因为这两个Goto的菜单选项都是重新读取主配置文件,而MBR与/dev/vda4配置文件的读取都是来自(/dev/vda2)/boot/grub2/grub.cfg的缘故! 因此这个画面就会重复出现了!这样了解乎? 另外,如果你再仔细看的话,会发现到上图中底部还有一些细部的选项,似乎有个 'e' edit 的样子! grub2 支持在线编修指令喔!这是个很有用的功能! 假如刚刚你将 grub.cfg 的内容写错了,导致出现无法开机的问题时, 我们可以查阅该 menuentry 菜单选项的内容并加以修改喔! 举例来说,我想要知道第一个菜单选项的实际内容时,将反白光棒移动到第一个菜单选项, 再按下 'e' 会进入如下画面: 图 19.3.2、grub2 额外的指令编辑模式 因为CentOS 7默认没有提供美美的底图给我们使用,因此这里会看到无法分辨的两个区块! 事实上它真的是两个区块, 上方是实际你可以编辑的内容区段,仔细看,这不就是我们在grub.cfg里面设定的东西吗? 没错!此时你还可以继续进一步修改喔! 用上/下/左/右按键到你想要编辑的地方,直接删除、新增即可!
至于下方画面则仅是一些编辑说明,重点在告诉你,编辑完毕之后,若想要取消而回到前一个画面, 请使用 [crtl]+c 或者是 [esc] 回去, 若是修改完毕,想要直接开机时,请使用 [crtl]+x 来开机啰!
现在我想要让系统开机的过程中,让这个系统进入救援模式(rescue) ,而不想要进入系统后使用systemctl rescue时,该如何处理?
仔细看到图 19.3.2 的画面,按下向下的箭头键,直到出现linux16那一行,然后在那一行的最后面加上systemd.unit=rescue.target, 画面有点像这样:
然后再按下[crtl]+x来进入系统,就能够取得rescue的环境了! 登入后有点像这样: 接着下来你就可以开始救援系统啰! 你可能会觉得很讶异!早期SystemV的系统中,进入runlevel 1的状态是不需要输入root密码的, 在systemd的年代,哇!! 竟然需要密码才能够进入救援模式耶!而且是强制要有root密码耶! 如果你是root密码忘记要救援,救个鬼啊~还是需要root密码啊!

关于开机画面与终端机画面的图形显示方式

回到顶部

如果你想要让你的开机画面使用图形显示方式,例如使用中文来显示你的画面啊!因为我们默认的 locale 语系就是 zh_TW.utf8 嘛! 所以理论上 grub2 会显是中文出来才对啊!有没有办法达成呢? 是有的~通过图形显是的方法即可!不过, 我们得要重新修改 grub.cfg 才行喔!依据底下的方式来 处理:
# 先改重要的配置文件

              [root@initroot ~]# vim /etc/default/grub

              .....(前面省略).....
              GRUB_TERMINAL=gfxterm # 设置主要的终端机显示为图形界面!
              GRUB_GFXMODE=1024x768x24 # 图形界面的 X, Y, 彩度资料
              GRUB_GFXPAYLOAD_LINUX=keep # 保留图形界面,不要使用 text 喔!
              # 重新建立配置文件
            
              [root@initroot ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
            
再次的重新启动,这时你会看到有点像底下的模样的画面喔!
图 19.3.3、使用图形显示模式的开机画面 看到没有?上图中有繁体中文喔!中文喔喔喔喔喔喔~真是开心啊! 未来如果你有需要在你的开机 菜单选项当中加入许多属于你自己的公司/企业的画面,那就太容易啰! ^_^

为个别菜单选项加上密码

回到顶部

想象一个环境,如果你管理的是一间计算机教室,这间计算机教室因为可对外开放,但是你又担心某 些 partition 被学生不小心的弄乱,因此你可能会想要将某些开机菜单选项作个保护。这个时候,为每个 菜单选项作个加密的密码就是个可行的方案啦!
另外,从本章前面的 19.3.6 小节介绍的开机过程中,你会知道用户可以在开机的过程中于 grub2 内选择进入某个菜单选项,以及进入 grub2 指令模式去修改菜单选项的参数数据等。 也就是说,主要的 grub2 控制有:(1)grub2 的菜单选项指令列修改与 (2)进入选择的菜单选项开机流程。好了,如刚刚谈到的计算机教 室案例, 你要怎么让某些密码可以完整的掌控 grub2 的所有功能,某些密码则只能进入个别的菜单选项 开机呢?这就得要牵涉到 grub2 的账号机制了!

grub2 的账号、密码与菜单选项设置

回到顶部

grub2 有点在模拟 Linux 的账号管理方案喔!因为在 grub2 的菜单选项管理中,有针对两种身份进行密 码设置:
superusers: 设置系统管理员与相关参数还有密码等,使用这个密码的用户,将可在 grub2 内具有所有修 改的权限。 但一旦设置了这个 superusers 的参数,则所有的指令修改将会被变成受限制的!
users: 设置一般账号的相关参数与密码,可以设置多个用户喔!使用这个密码的用户可以选择要进入某些 菜单选项项目。 不过,菜单选项项目也得要搭配相对的账号才行喔!(一般来说,使用这种密码的账号并不能修改选 单的内容,仅能选择进入菜单选项去开机而已)
这样说可能你不是很容易看得懂,我们使用底下的一个范例来说明你就知道怎么处理了。另外,底下 的范例是单纯给读者们看看而已的~ 不能够直接用在我们的测试机器里面喔!
问:
假设你的系统有三个各别的操作系统,分别安装在 (hd0,1), (hd0,2), (hd0,3) 当中。假设 (hd0,1) 是所有人都可以选 择进入的系统, (hd0,2) 是只有系统管理员可以进入的系统,(hd0,3)则是另一个一般用户与系统管理员可以进入的 系统。另外,假设系统管理员的账号/密码设置为 initroot/abcd1234, 而一般账号为 peter/dcba4321 ,那该如何设定?
如果依据上述的说明,其实没有用到 Linux 的 linux16 与 initrd16 的项目,只需要 chainloader 的项目而已! 因 此,整个 grub.cfg 会有点像底下这样喔:
# 第一个部份是先设置好管理员与一般账号的账号名称与密码项目!

              set superusers="initroot" # 这里是设置系统管理员的账号名称为啥的意思!
password initroot abcd1234 # 当然要给予这个账号密码啊!
password peter dcba4321 # 没有输入 superuses 的其他账号,当然就是判定为一般账号
menuentry "大家都可以选择我来开机喔!" --unrestricted {set root=(hd0,1)
chainloader +1
}
menuentry "只有管理员的密码才有办法使用" --users "" { set root=(hd0,2) chainloader +1 } menuentry "只有管理员与 peter 才有办法使用喔!" --users peter { set root=(hd0,3) chainloader +1 }
如上表所示,你得要使用 superuses 来指定哪个账号是管理员!另外,这个账号与 Linux 的实体账 号无关,这仅是用来判断密码所代表的意义而已。 而密码的给予有两种语法: password_pbkdf2 账号 使用 grub2-mkpasswd-pbkdf2 所产生的密码 password 账号 没加密的明码
有了账号与密码之后,在来就是在个别的菜单选项上面加上是否要取消限制 (--unrestricted) 或者是给予哪 个用户 (--users) 的设置项目。 同时请注意喔,所有的系统管理员所属的密码应该是能够修改所有的 菜单选项,因此你无须在第三个菜单选项上面加入 initroot 这个管理员账号! 这样说你就可以了解了吧? 你很可能会这样说:
了解个头啦!怎么可能会了解!前面不是才说过:
「不要手动去修改 grub.cfg 」
吗?这里怎么直接列出 grub.cfg 的内容? 上面这些项目我是要在哪些环境配置文件里面修改啦?

grub2 密码设置的文件位置与加密的密码

回到顶部

还记得我们在前几小节谈到主要的环境设置是在 /etc/grub.d/* 里面吧?里面的文件文件名有用数字 开头,那些数字照顺序,就是 grub.cfg 的来源顺序了。 因此最早被读的应该是 00_header,但是那 个文件的内容挺重要的,所以 CentOS 7 不建议你改它~那要改谁?就自己建立一个名为 01_users 的文件即可! 要注意是两个数字开头接着底线的文件名才行喔!然后将账号与密码参数给它补进去!
现在让我们将 initroot 与 peter 的密码加密,实际在我们的测试机器上面建置起来吧!
# 1. 先取得 initroot 与 peter 的密码。底下我仅以 initroot 来说明而已!

              [root@initroot ~]# grub2-mkpasswd-pbkdf2
              Enter password: # 这里输入你的密码
              Reenter password: # 再一次输入密码
              PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.9A2EBF7A1F484...
            
# 上面特殊字体从 grub.pbkdf2.... 的那一行,全部的数据就是你的密码喔!复制下来!# 2. 将密码与账号写入到 01_users 文件内
              [root@initroot ~]# vim /etc/grub.d/01_users
              cat << eof
              set superusers="initroot"
              password_pbkdf2 initroot grub.pbkdf2.sha512.10000.9A2EBF7A1F484904FF3681F97AE22D58DFBFE65A...
              password_pbkdf2 peter grub.pbkdf2.sha512.10000.B59584C33BC12F3C9DB8B18BE9F557631473AED...
              eof
            
# 请特别注意,在 /etc/grub.d/* 底下的文件是执行脚本档,是要被执行的!
# 因此不能直接写帐密,而是通过 cat 或 echo 等指令方式来将帐密数据显示出来才行喔!
# 3. 因为 /etc/grub.d/ 底下应该是执行档,所以刚刚建立的 01_users 当然要给予执行权限
              [root@initroot ~]# chmod a+x /etc/grub.d/01_users
              [root@initroot ~]# ll /etc/grub.d/01_users
              -rwxr-xr-x. 1 root root 649 Aug 31 19:42 /etc/grub.d/01_users
            
很快的,你就已经将密码建置妥当了!接下来就来聊一聊,那么每个 menuentry 要如何修改呢?
为个别的菜单选项设置账号密码的使用模式
回想一下我们之前的设置,目前测试机器的 Linux 系统菜单选项应该有五个:
来自 /etc/grub.d/10_linux 这个文件主动侦测的两个 menuentry;
来自 /etc/grub.d/40_custom 这个我们自己设置的三个 menuentry
在 40_custom 内的设置,我们可以针对每个 menuentry 去调整,而且该调整是固定的,不会随便被 更改。至于 10_linux 文件中, 则每个 menuentry 的设置都会依据 10_linux 的数据去变更,也就是 由 10_linux 侦测到的內核开机菜单选项都会是相同的意思。
因为我们已经在 01_users 文件内设置了 set superusers="initroot" 这个设置值,因此每个菜单选项内的参数 除了知道 initroot 密码的人之外, 已经不能随便修改了喔!所以,选择 10_linux 制作出来的菜单选项开 机,应该就算正常开机,所以,我们默认不要使用密码好了! 刚刚好 10_linux 的 menuentry 设置 值就是这样:
              [root@initroot ~]# vim /etc/grub.d/10_linux
              .....(前面省略).....
              CLASS="--class gnu-linux --class gnu --class os --unrestricted"
            
# 这一行大约在 29 行左右,你可以利用 unrestricted 去识别即可!
# 默认已经不受限制 (--unrestricted) 了!如果想要受限制,在这里将 --unrestricted
# 改成你要使用的 --users "账号名称" 即可!不过,还是不建议修改啦!
现在我们假设在 40_custom 里面要增加一个可以进入救援模式 (rescue) 的环境,并且放置到最后一 个菜单选项中,同时仅有知道 peter 的密码者才能够使用, 那你应该这样作:
              [root@initroot ~]# vim /etc/grub.d/40_custom.....(前面省略).....
              menuentry 'Rescue CentOS7, with Linux 3.10.0-229.el7.x86_64' --users peter {
              load_video
              set gfxpayload=keep
              insmod gzio
              insmod part_gpt
              insmod xfs
              set root='hd0,gpt2'
              if [ x$feature_platform_search_hint = xy ]; then
              search --no-floppy --fs-uuid --set=root --hint='hd0,gpt2'
              94ac5f77-cb8a-...
              else
              search --no-floppy --fs-uuid --set=root 94ac5f77-cb8a-495e-a65b-2ef7442b837c
              fi
              linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/mapper/centos-root ro rd.lvm.lv
              =centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet
              systemd.unit=rescue.target
              initrd16 /initramfs-3.10.0-229.el7.x86_64.img
              }
              [root@initroot ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
            
最后一步当然不要忘记重建你的 grub.cfg 啰!然后重新启动测试一下,如果一切顺利,你会发现如 下的画面:
图 19.3.4、默认的菜单选项环境
你直接在 1, 2, 3 菜单选项上面按下 enter 就可以顺利的继续开机,而不用输入任何的密码,这是因为有 --unrestricted 参数的关系。 第 4, 5 菜单选项中,如果你按下 enter 的话,就会出现如下画面:图 19.3.5、需要输入账号密码的环境 你可能会怀疑,怪了!为啥 4, 5 需要输入密码才行?而且一定要 initroot 这个系统管理员的密码才可 接受?使用 dmstai 就不可以! 这是因为我们在 4, 5 忘记加上 --users 也忘记加上 --restricted 了! 因此这两个项目一定要系统管理员才能够进入与修改。
最后,你在第 6 个菜单选项上面输入 e 来想要修改参数时,输入的帐密确实是 peter 的帐密,但是, 就是无法修改参数耶!怎么回事啊? 我们前面讲过了, grub2 两个基本的功能 (1)修改参数与 (2) 进入菜单选项开机模式,只有系统管理员能够修改参数,一般用户只能选择可用的开机菜单选项啦! 这样说, 终于理解了吧?哈哈!
问:
我的默认菜单选项里面没有加上 --unrestricted 项目,同时已经设置了 set superusers="initroot" 了, 那请教一下,开机 的时候能不能顺利开机 (没有输入账密的情况下?)
答:
因为没有写上 --unrestricted 的项目,同时又加上了 superusers="initroot" 的设置项目,这表示 grub.cfg 内的所有 参数都已经受到限制了, 所以,当倒数读秒结束后,系统会叫出账号密码输入的窗口给你填写,如果没有填写 就会一直卡住了!因此无法顺利开机喔!

开机过程的问题解决

回到顶部

很多时候,我们可能因为做了某些设置,或者是因为不正常关机 (例如未经通知的停电等等) 而导致 系统的 filesystem 错乱,此时,Linux 可能无法顺利开机成功,那怎么办呢?难道要重灌?当然不需 要啦! 进入 rescue 模式去处理处理,应该就 OK 的啦!底下我们就来谈一谈如何处理几个常见的 问题!

直接开机就以 root 执行 bash 的方法

回到顶部

除了上述的 rd.break 之外,我们还可以直接开机取得系统根目录后,让系统直接丢一个 bash 给我 们使用喔! 使用的方法很简单,就同样在开机的过程中,同在 linux16 的那一行,最后面不要使用 rd.break 而是使用 init=/bin/bash 即可! 最后开机完成就会丢一个 bash 给我们!同样不需要 root密码而有 root 权限!
但是要完整的操作该系统是不可能的,因为我们将 PID 一号更改为 bash 啦!所以,最多还是用在 救援方面就是了! 而且,同样的,要操作该系统你还是得要 remount 根目录才行啊!否则无法更改 文件系统啦!基本上,这个系统的处理方法你应该是要这样作的:
图 19.4.2、直接开机使用 bash 的方法
如上图的完整截图,你会发现由于是最默认的 bash 环境,所以连 PATH 都仅有 /bin 而已~所以你 不能下达 reboot !同时, 由于没有 systemd 或者是 init 的存在,所以真的使用绝对路径来下达 reboot 时,系统也是无法协助你重新启动啦! 此时只能按下 reset 或者是强制关机后,才能再次开 机!所以...感觉上还是 rd.break 比较保险...
同时请注意,上面刻意忘记处理 /.autorelabel 的文件建置~你如果按照上述的方法实作的话, 嘿嘿!此时应该是无法登入的喔! 请重新启动进入 rd.break 模式,然后使用 SELinux 改为permissive 的方法来实验看看。 等到可以顺利以 root 登入系统后, 使用 restorecon -Rv /etc 来瞧一瞧,应该会像底下这样:

              [root@initroot ~]# getenforce
              Permissive
              [root@initroot ~]# restorecon -Rv /etc
              restorecon reset /etc/shadow context system_u:object_r:unlabeled_t:s0
              ->system_u:object_r:shadow_t:s0
              restorecon reset /etc/selinux/config context system_u:object_r:unlabeled_t:s0
              ->system_u:object_r:selinux_config_t:s0
              [root@initroot ~]# vim /etc/selinux/config
              SELINUX=enforcing
              [root@initroot ~]# setenforce 1
            

因文件系统错误而无法开机

回到顶部

如果因为设置错误导致无法开机时,要怎么办啊?这就更简单了!最容易出错的设置而导致无法顺利 开机的步骤,通常就是 /etc/fstab 这个文件了,尤其是用户在实作 Quota/LVM/RAID 时,最容易写 错参数, 又没有经过 mount -a 来测试挂载,就立刻直接重新启动,真要命!无法开机成功怎么办? 这种情况的问题大多如下面的画面所示:
图 19.4.3、文件系统错误的示意图
看到最后两行,他说可以输入 root 的密码继续加以救援喔!那请输入 root 的密码来取得 bash 并以 mount -o remount,rw / 将根目录挂载成可擦写后,继续处理吧!其实会造成上述画面可能的原因除了 /etc/fstab 编辑错误之外,如果你曾经不正常关机后,也可能导致文件系统不一致 (Inconsistent) 的情 况, 也有可能会出现相同的问题啊!如果是扇区错乱的情况,请看到上图中的第二行处, fsck 告 知其实是 /dev/md0 出错, 此时你就应该要利用 fsck.ext3 去检测 /dev/md0 才是!等到系统发现错 误,并且出现clear [Y/N]时,输入 y 吧!当然啦,如果是 XFS 文件系统的话,可能就得要使用 xfs_repair 这个指令来处理。
这个 fsck/xfs_repair 的过程可能会很长,而且如果你的 partition 上面的 filesystem 有过多的数据损毁时, 即使 fsck/xfs_repair 完成后,可能因为伤到系统槽,导致某些关键系统文件数据的损毁,那么依旧是 无法进入 Linux 的。此时,就好就是将系统当中的重要数据复制出来,然后重新安装,并且检验一 下,是否实体硬盘有损伤的现象才好!不过一般来说,不太可能会这样啦~ 通常都是文件系统处理完毕后,就能够顺利再次进入 Linux 了。

initroot编辑整理,转载请注明www.initroot.com

100次点赞 100次阅读