目录
- 一.bootloader: Grub2
- bootloader 的两个 stage
- grub2 的配置文件 /boot/grub2/grub.cfg 初探
- 磁盘与分区在 grub2 中的代号
- /boot/grub2/grub.cfg 配置文件
- grub2 配置文件维护 /etc/default/grub 与 /etc/grub.d
- 开机前的额外功能修改
- 关于开机画面与终端机画面的图形显示方式
- 为个别菜单选项加上密码
- grub2 的账号、密码与菜单选项设置
- grub2 密码设置的文件位置与加密的密码
- 开机过程的问题解决
- 忘记 root 密码的解决之道
- 直接开机就以 root 执行 bash 的方法
- 因文件系统错误而无法开机
一.bootloader:Grub2
回到顶部
系统开机启动执行的第一个程序是BIOS,BIOS在完成开机自检后会加载第一启动设备MBR中存放的bootloader。
bootloader是加载內核的重要工具,具有菜单选项功能、加载內核文件以及控制权移交等功能.
MBR是磁盘的第一个扇区sector,共512字节,最后64字节用来存储磁盘分区表信息,只有446字节用来存放bootloader代码。
通常将bootloader分为两个部分,主程序代码部分写入MBR扇区,配置文件则写入/boot目录,可以将/boot挂载到单独的分区.
开机启动的时候,bootloader会去/boot目录下读取自己的配置文件grub.cfg。
linux主流的bootloader就是grub.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有如下优点:
1.支持较多的文件系统与磁盘分区格式,grub2可以直接识别文件系统中的內核文件;
2.开机的时候,可以自行编辑与修改开机设置项目,类似bash的指令模式;
3.可以动态识别配置文件,即修改完配置文件/boot/grub2/grub.cfg后,下次开机直接生效!
磁盘与分区在grub2中的代号
回到顶部
grub必须先识别到硬盘,才能从硬盘中加载內核文件.grub中的硬盘代号与Linux磁盘设备文件名不同.
grub2使用如下格式标识硬盘:
(hd0,1) #默认语法,由grub2自动判断分区格式硬盘代号使用小括号括起来;
(hd0,msdos1) #磁盘的分区为传统的MBR模式
(hd0,gpt1) #磁盘的分区为GPT模式
硬盘以hd后接数字编号表示,按照识别顺序编号,第一个识别到的硬盘为0号,第二个为1号,以此类推;
每个硬盘的第一个partition代号为1,依序类推。
磁盘的编号是由0开始,分区的编号则由1开始!
第一个识别到的硬盘代号为:(hd0),该硬盘的第一个分区为(hd0,1),另外为了区分不同的分区格式, 磁盘后面的分区编号可以使用类似msdos1与gpt1的方式区分.
由于BIOS可以调整磁盘的开机顺序,磁盘对应的(hdN)那个编号N可能是会变动的!
整个硬盘代号为:
硬盘识别顺序 在Grub2中的代号第一个硬盘的MBR安装处的硬盘代号就是(hd0), 第一个硬盘的第一个分区的bootsector代号就是(hd0,msdos1) 第一个硬盘的第一个逻辑分区的bootsector代号为(hd0,msdos5)!
第一个(MBR) (hd0) (hd0,msdos1) (hd0,msdos2) (hd0,msdos3)....
第二个(GPT) (hd1) (hd1,gpt1) (hd1,gpt2) (hd1,gpt3)....
第三个(hd2) (hd2,1) (hd2,2) (hd2,3)....
假设系统仅有一个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,官方建议不要直接修改该文件.而是修改/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,grub会在屏幕上显示剩余的等待秒数,设置为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文件才是grub要真正读取的配置文件.
假设需要
(1)开机菜单选项等待40秒钟;
(2)默认用第一个菜单选项开机;
(3)开机时显示菜单选项;
(4)內核外带elevator=deadline参数值.
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 done3. 检查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=deadlinegrub2-mkconfig会去分析/etc/grub.d/目录里的文件,根据这些文件来构建grub.cfg.一般该目录下会有如下这些文件:
00_header: 大部分在/etc/default/grub中设置的变量,都会被这个脚本用来构建grub.cfg。 包括需要加载的模块分析、屏幕终端机的格式、倒数秒数、是否隐藏菜单选项等;
10_linux: 该脚本分析/boot目录下的文件,尝试找到正确的linux內核与读取这个內核需要的文件系统模块与参数等, 然后设置到grub.cfg中。这个脚本会将所有在/boot目录下的每一个內核文件都对应到一个菜单选项, 內核文件数量越多,开机菜单选项就越多。 如果不想要旧的內核出现在菜单选项上,就可以删除旧的內核文件。
30_os-prober:该脚本默认会到其他分区查找可能存在的操作系统,并加到开机菜单选项。 可以在/etc/default/grub文件里面加上GRUB_DISABLE_OS_PROBER=true取消该脚本的运行.
40_custom:如果还有其他需要的菜单选项,可以在该文件中加入!一般来说,我们应该只修改40_custom这个文件.
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内容即可!
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 文件已经存在,则覆盖掉旧文件以dracut的默认功能建立一个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 :加入某些额外的文件系统支持!
[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来建立菜单选项了!
测试与安装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/*,如果想要复制到其他目录与设备去,就得要用这个参数。将grub2安装在目前系统的MBR底下,我的系统为/dev/vda:
INSTALL_DEVICE 安装的设备代号!
[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就已经安装到MBR 与 boot sector中了.
重启开机就可以在默认菜单选项 (的范例当中是 40 秒) 按下任意键, 还可以进行 grub2的在线编辑操作!
来看看开机画面吧!
图 19.3.1、grub2 开机画面示意图
默认菜单选项没有隐藏,可以直接看到这5个菜单选项,同时会有倒计时计数。
菜单选项部分的画面就是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 额外的指令编辑模式
上方是编辑的内容区段,就是我们在grub.cfg里面设置的内容.用上/下/左/右按键将光标移动到想要编辑的地方,直接删除、新增即可!
下方画面则是一些编辑说明,使用 [crtl]+c 或者是 [esc] 返回, 修改完毕,使用 [crtl]+x直接开机时.
如果想让系统开机后直接进入救援模式(rescue) ,而不是手动使用systemctl rescue时,该如何处理?
按下向下的箭头键,直到出现linux16那一行,然后在那一行的最后面加上systemd.unit=rescue.target:
然后按下[crtl]+x来进入系统,就可以直接进入rescue环境了!
早期SystemV的系统,进入runlevel 1环境是不需要输入root密码的,而systemd强制需要root密码才能够进入救援模式.
图形方式显示开机画面
回到顶部
可以使用图形方式显示开机画面,修改grub.cfg配置文件:
[root@initroot ~]# vim /etc/default/grub ....省略.... GRUB_TERMINAL=gfxterm #设置终端机显示为图形界面 GRUB_GFXMODE=1024x768x24 #图形界面的 X, Y, 彩度 GRUB_GFXPAYLOAD_LINUX=keep #保留图形界面,不要使用text! #重新建立配置文件 [root@initroot ~]# [root@initroot ~]# grub2-mkconfig -o /boot/grub2/grub.cfg再次的重新启动,这时你会看到有点像底下的模样的画面喔!
图 19.3.3、使用图形显示模式的开机画面 如果需要在开机菜单选项当中加入属于你自己的公司/企业的画面就很容易了.
grub2的账号、密码与菜单选项设置
回到顶部
可以为每个菜单选项加密.
用户可以在开机的过程中于 grub2内选择进入某个菜单选项,以及进入 grub2 指令模式去修改菜单选项的参数数据等。
也就是说,主要的 grub2控制有:
(1)grub2 的菜单选项指令列修改;
(2)进入选择的菜单选项开机流程。
怎么让某些密码可以完整的掌控 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.
按照上述的说明,我们来看看grub.cfg文件的配置.其实没有用到 Linux 的 linux16 与 initrd16 的项目,只需要 chainloader 的项目.
# 第一个部份是先设置好管理员与普通账号的账号名称与密码:
set superusers="initroot" #设置系统管理员的账号名称 password initroot abcd1234 #设置账号密码 password peter dcba4321 #设置普通账号密码 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生成的密码接下来就是在菜单选项上加上是否要取消限制 (--unrestricted) 或者是给予哪个用户 (--users) 权限的设置项目。 系统管理员的密码默认可以修改所有的菜单选项,因此无须在第三个菜单选项上面加入 initroot 这个管理员账号! 上面直接列出 grub.cfg 的内容,但是我们不能直接修改grub.cfg.上面这些项目我是要在哪些环境配置文件里面修改啦?
password 账号 #无加密的明码
主要的配置文件在/etc/grub.d/目录下.文件名用数字开头,数字的顺序就是被执行的顺序,也是grub.cfg的生成顺序。
最先被执行的是00_header,但是该文件的内容很重要,不建议直接修改.我们可以自己建立一个名为01_users的文件,在该文件中配置账号和密码.
1. 先生成 initroot 与 peter 的加密密码:
[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. 给予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 要如何修改呢?
按照前面的设置,我们的grub开机菜单选项应该有五个:
来自 /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"默认已经不受限制(--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重新启动测试一下,如果一切顺利,你会发现如下的画面:
图、默认的菜单选项环境
直接在 1, 2, 3 菜单选项上按下 enter 就可以顺利开机,而不用输入任何的密码,这是因为有--unrestricted 参数的关系。
第 4, 5 菜单选项中,如果按下 enter 的话,就会出现如下画面:
图、需要输入账号密码的环境
4, 5 一定要 initroot 这个的密码才可以,这是因为4, 5 没有 --users 也没有 --restricted,因此这两个项目一定要系统管理员才能够进入与修改。
最后,在第 6 个菜单选项上面输入 e 来修改参数时,必须输入peter 的帐密,但是,就是无法修改参数耶! grub2 两个基本的功能 (1)修改参数与 (2)进入菜单选项开机模式,只有系统管理员能够修改参数,一般用户只能选择可用的开机菜单选项啦!
我的默认菜单选项里面没有加上 --unrestricted 项目,同时已经设置了 set superusers="initroot" 了, 那请教一下,开机 的时候能不能顺利开机 (没有输入账密的情况下?)
因为没有写上 --unrestricted 的项目,同时又加上了 superusers="initroot" 的设置项目,这表示 grub.cfg 内的所有参数都已经受到限制了, 所以,当倒数读秒结束后,系统会叫出账号密码输入的窗口给你填写,如果没有填写就会一直卡住了!
直接开机就以root执行bash的方法
回到顶部
有时Linux可能无法正常开机,这时可进入 rescue 模式去处理
除了上述的 rd.break 之外,可以让linux开机取得系统根目录后,直接启动一个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挂载测试,就立刻重新启动,导致无法开机.
这种情况的问题大多如下面的画面所示:
图. 文件系统错误的示意图
这时可以输入 root 密码来取得 bash,使用mount -o remount,rw / 命令将根目录挂载成可擦写,就可以进行后续的恢复处理了!
除了/etc/fstab 编辑错误外,异常关机导致的文件系统不一致(Inconsistent)也会出现相同的问题!
如果是扇区错乱,例如图中的第二行处, fsck报告是/dev/md0 出错, 此时应该用fsck.ext3检测/dev/md0,
直到fsck发现错误,并且出现clear [Y/N]时,输入 y即可!
如果是 XFS 文件系统,可能就得要使用 xfs_repair 命令来处理。
fsck/xfs_repair 的过程可能会很长,通常文件系统处理完毕后,就能够顺利进入 Linux 了.
但如果分区上的文件系统有过多的数据损毁,即使 fsck/xfs_repair 完成后,
可能因为伤到系统槽,导致某些关键系统文件数据的损毁,那么依旧是无法进入 Linux 的。
此时最好将系统中的重要数据复制出来,然后重新安装,并且检验一下,是否实体硬盘有损伤的现象!
initroot编辑整理,转载请注明www.initroot.com