grub应用
bootloader及grub概述
启动引导装载程序(bootloader),就是系统启动时在执行POST加电自检功能的BIOS程序之后、操作系统内核运行之前这中间所运行的一段程序,bootloader的主要作用是加载内核,并将整个系统的控制权移交给内核。常见的bootloader有Windows的ntloader、Linux的lilo、grub及grub2等。其中,在CentOS 5/6系列上使用的是grub,而在CentOS 7开始则使用grub;lilo则常见于手机,因此lilo是使用者最多的一种bootloader。
Windows:
ntloader
Linux:
LILO:LInux LOader
GRUB:Grand Unified Bootloader
GRUB 0.X:Grub Legacy
GRUB 1.X:Grub2
就MBR分区方法而言,大多数Bootloader都分为多个阶段来引导,其中第一阶段存放于MBR中,用于引导装载第二阶段。而grub作为Bootloader的一种也不例外,它是分为stage1,stage2,stage1.5这三个阶段来引导的:stage1的主要工作是加载stage1.5,stage1.5的主要工作是加载文件系统驱动,让stage1中的bootloader能够识别stage2所在分区的上的文件系统,stage1.5会提供多种文件系统的驱动,如下:
[[email protected] grub]# ls -1F device.map e2fs_stage1_5 fat_stage1_5 ffs_stage1_5 grub.conf iso9660_stage1_5 jfs_stage1_5 [email protected] minix_stage1_5 reiserfs_stage1_5 splash.xpm.gz stage1 stage2 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 [[email protected] grub]#
可以看见,每个stage1.5文件对应一种文件系统,而借助于stage1.5阶段所提供的文件系统驱动,stage1就可以通过加载其中某一种文件系统驱动来识别stage2所在分区的文件系统了。举个例子,如果stage2所在分区上的文件系统是ext4,那么stage1就会通过stage1.5提供的e2fs_stage1_5来识别stage2。完成对stage2的识别和加载之后,stage2就能够加载stage2所在分区上(即/boot所在分区)的内核文件和ramdis文件(注意:ramdisk文件并非必须)至内存中了。此外,grub的功能主要是通过stage2来实现的,在系统启动时,stage2可以向用户提供菜单,并提供交互式接口,允许用户通过菜单选择要加载的内核或操作系统,另外,如果用户有需要,stage2还可以为菜单提供保护机制,而保护机制有两种,一种是为编辑菜单提供认证,另外一种是为启动的内核或操作系统提供认证。以下总结grub(stage2)的主要功能:
grub(stage2)的功用:
(1)向用户提供菜单,并提供交互式接口。例如,在启动时可进入菜单,通过键入e键进入编辑模式,可以编辑菜单,此时会读取配置文件;也可以通过键入c键可以进入命令行模式,即进入交互式接口,可以自己手动指定要启动的内核而不读取grub配置文件;
(2)加载用户选择的内核或操作系统。在选择时允许用户传递参数给内核,也可以隐藏菜单的具体内容;
(3)为菜单提供保护机制。可以为编辑菜单提供认证,用户需要通过认证方可编辑指定菜单;也可以为内核或操作系统提供认证,用户需要通过认证方可启动指定的内核或操作系统;
演示:
启动时进入编辑菜单:
键入e键可以编辑菜单,如下所示,再此时再键入一次e键就可以编辑选定的参数了。
按下Esc键可以返回第一个菜单界面,再键入c键可以直接进入命令行模式(交互式接口):
通过'help'可查看帮助,而'help KEYWORD'则可以查看指定项的详细帮助:
可以通过find命令查找文件,例如查找/boot分区下的内核文件:
用户可以通过这个交互式接口指定要加载的内核及ramdisk文件,但在此之前要先指定grub的根分区(注意:stage2所在分区即为grub的根分区,这里grub的根不一定是文件系统的根),而要指定grub的根分区则必须采用grub识别设备的方式来指定,grub识别设备是通过命令'root (hd#,#)'来指定的,各部分解释如下:
root:用于切换grub所在分区; hd#:磁盘编号,用数字表示;从0开始编号; #:分区编号,用数字表示;从0开始编号;
需要注意的是,用户在指定要加载的内核或操作系统时,通常需要指定grub的根(root (hd#,#)),并且指定Kernel及initrd所在路径,必要时传递一些参数给Kernel。但是,Kernel及initrd是以grub的“根”作为起始目录的,也就是说如果/boot作为基本磁盘分区独立出来时,那么Kernel及initrd在指定路径时的起始目录为'/';如果/boot不作为基本磁盘分区,而是根分区('/')之下的一个目录时,那么此时grub的“根”即为文件系统的根,Kernel及initrd的起始目录为/boot/。
用户可在交互式接口下手动指定要加载的Kernel及initrd。在进入菜单时和刚才一样,键入c键进入grub命令行模式(交互式接口),而当/boot为独立分区时,分别指定kernel及initrd的在grub的“根”下的文件路径,如下所示:
这里在Kernel指定路径之后至少还要传递两个参数,一个是'ro',指明是以只读方式挂载根文件系统,'root=xxx'这一样则指明根文件系统所在分区,这里实验环境的根文件系统所在分区是一个LVM逻辑卷。最后键入'boot'即可加载指定的内核或操作系统并完成启动。
grub的配置文件:/boot/grub/grub.conf <--- /etc/grub.conf(链接文件)
配置项:
defaults=#:设定默认要启动的菜单项;菜单项(title)从0开始编号;
timeout=#:设定菜单项等待用户选择的时长;
splashp_w_picpath=(hd#,#)/PATH/TO/XPM_PIC_FILE:指明菜单项背景图片的文件路径;
hiddenmenu:隐藏菜单;
password [--md5] STRING:菜单编辑认证;
title TITLE:定义菜单项“标题”;可出现多次;
root (hd#,#):grub查找stage2及Kernel等文件所在设备的分区,即grub的“根”;
kernel /PATH/TO/VMLINUZ-FILE [PARAMETERS]:指明启动的内核;
initrd /PATH/TO/INITRAMFS-FILE:指明内核匹配的ramdisk文件;
password [--md5] STRING:启动选定的内核或操作系统时进行认证;
演示:
添加系统启动时的菜单项,首先编辑/etc/grub/grub.conf文件,如图:
保存退出,并重新启动:
[[email protected] ~]# reboot
可以看到如下界面:
重新编辑菜单,为CentOS 6 (test)这一菜单项指向的内核添加启动认证:
[[email protected] ~]# grub-md5-crypt Password: //输入设定的密码; Retype password: $1$n.0tB/$AStqQTLYFdyC5GcI0BymR/ //得到单向加密后的密码字符串; [[email protected] ~]#
复制加密得到的密码字符串,添加至/etc/grub/grub.conf文件中CentOS 6 (test)菜单项之下:
重新启动至菜单界面,这时如果要选择CentOS 6 (test)这一菜单项来启动时就需要通过密码验证才能加载内核:
同样可添加菜单编辑认证,在/etc/grub/grub.conf文件中作如下修改:
这里全局的菜单编辑认证加密的密码同样可以由grub-md5-crypt生成,此处直接使用内核认证的密码。
重新启动,进入菜单界面:
这里只能先键入p键并输入密码才能编辑菜单。
实例一:
新加硬盘,为这块新添加的硬盘安装grub程序,制作成在用户空间能单独运行bash的系统,并把硬盘拆下来装至另外的物理主机。
首先添加一块20G的硬盘:
启动主机,首先为这块硬盘分区:/dev/sdb1, /dev/sdb2, /dev/sdb3,其中/dev/sdb1作为/boot分区,/dev/sdb2作为swap分区,而/dev/sdb3作为/分区:
[[email protected] ~]# fdisk /dev/sdb
分区后强制让内核重新识别:
[[email protected] ~]# partx -a /dev/sdb BLKPG: Device or resource busy error adding partition 1 BLKPG: Device or resource busy error adding partition 2 BLKPG: Device or resource busy error adding partition 3 [[email protected] ~]# [[email protected] ~]# cat /proc/partitions //查看内核分区信息; major minor #blocks name 8 0 41943040 sda 8 1 512000 sda1 8 2 41430016 sda2 8 16 20971520 sdb 8 17 112423 sdb1 //内核已识别; 8 18 2104515 sdb2 8 19 5253255 sdb3 253 0 37330944 dm-0 253 1 4096000 dm-1
对各分区进行格式化:
[[email protected] ~]# mke2fs -t ext4 /dev/sdb1 [[email protected] ~]# mke2fs -t ext4 /dev/sdb3 [[email protected] ~]# mkswap /dev/sdb2
根分区挂载至/mnt/sysroot/,/boot分区挂载至/mnt/sysroot/boot:
[[email protected] ~]# mkdir /mnt/sysroot [[email protected] ~]# mkdir /mnt/sysroot/boot [[email protected] ~]# mount /dev/sdb3 /mnt/sysroot/ [[email protected] ~]# mount /dev/sdb1 /mnt/sysroot/boot/
给/dev/sdb这块磁盘安装grub:
[[email protected] ~]# grub-install --root-directory=/mnt/sysroot /dev/sdb //注意:这里--root-directory不能指为/mnt/sysroot/boot,因为它会自动到/mnt/sysroot目录下 查找boot目录; Probing devices to guess BIOS drives. This may take a long time. Installation finished. No error reported. This is the contents of the device map /mnt/sysroot/boot/grub/device.map. Check if this is correct or not. If any of the lines is incorrect, fix it and re-run the script `grub-install'. (fd0) /dev/fd0 (hd0) /dev/sda (hd1) /dev/sdb [[email protected] ~]#
查看文件:
[[email protected] ~]# cd /mnt/sysroot/boot/ [[email protected] boot]# ls //查看/mnt/sysroot/boot分区下的文件; grub lost+found //缺少Kernel文件和ramdisk文件; [[email protected] boot]# cd grub/ [[email protected] grub]# ls -1 //查看/mnt/sysroot/boot/grub目录下的文件; device.map e2fs_stage1_5 fat_stage1_5 ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 reiserfs_stage1_5 stage1 stage2 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 //在grub目录下缺少grub的配置文件grub.conf;
为/mnt/sysroot/boot目录下添加Kernel及ramdisk文件(此处直接复制/dev/sda上的文件):
[[email protected] ~]# cp /boot/vmlinuz-2.6.32-642.el6.x86_64 /mnt/sysroot/boot/vmlinuz [[email protected] ~]# cp /boot/initramfs-2.6.32-642.el6.x86_64.img /mnt/sysroot/boot/init ramfs.img
创建grub的配置文件(/mnt/sysroot/boot/grub/grub.conf),并设定各属性:
default=0 //设定启动第一项; timeout=5 //设定等待用户选择菜单的时长为5秒; title CentOS 6 (Express) //设定菜单标题; root (hd0,0) //原本是(hd1,0),但拆下来装至另一空物理机上则为(hd0,0); kernel /vmlinuz ro root=/dev/sda3 init=/bin/bash //这里也一样,在本机上是/dev/sdb3,但装至另一空物理主机上则转为/dev/sda3; //此外,这里设定内核启动用户空间的第一个应用程序是/bin/bash,而不是原来的upstart; initrd /initramfs.img
根据FHS在根目录下创建各个基础目录:
[[email protected] ~]# cd /mnt/sysroot/ [[email protected] sysroot]# mkdir etc bin sbin usr var dev mnt media proc sys root lib lib64 home
拷贝/bin/bash程序及其所依赖到的库文件:
[[email protected] ~]# cp /bin/bash /mnt/sysroot/bin/ [[email protected] ~]# [[email protected] ~]# ldd /bin/bash //查看bash程序所依赖到的库文件; linux-vdso.so.1 => (0x00007ffdd21fa000) //库文件的访问入口; libtinfo.so.5 => /lib64/libtinfo.so.5 (0x0000003f02200000) libdl.so.2 => /lib64/libdl.so.2 (0x0000003efda00000) libc.so.6 => /lib64/libc.so.6 (0x0000003efde00000) /lib64/ld-linux-x86-64.so.2 (0x0000003efd600000) [[email protected] ~]# [[email protected] ~]# cp /lib64/libtinfo.so.5 /mnt/sysroot/lib64/ [[email protected] ~]# cp /lib64/libdl.so.2 /mnt/sysroot/lib64/ [[email protected] ~]# cp /lib64/libc.so.6 /mnt/sysroot/lib64/ [[email protected] ~]# cp /lib64/ld-linux-x86-64.so.2 /mnt/sysroot/lib64/
以同样的方法,拷贝/bin/ls程序及其所依赖到的库文件。
所有步骤完成之后,先执行根切换测试一下:
[[email protected] ~]# chroot /mnt/sysroot/ bash-4.1# bash-4.1# ls -1 bin boot dev etc home lib lib64 lost+found media mnt proc root sbin sys usr var bash-4.1# bash-4.1# exit //由bash内嵌命令exit退出; exit [[email protected] ~]# [[email protected] ~]# sync //执行同步;
测试成功!
关机之后,查看刚才添加的磁盘文件名 ==> CentOS 6.8-1.vmdk:
新建虚拟机:
创建时选择“使用现有虚拟磁盘”:
选择刚才查看到的磁盘文件(CentOS 6.8-1.vmdk):
创建完成之后启动新建的虚拟机,可以看到菜单界面如下:
因为默认会开启selinux,而这里系统没有selinux的相关程序及配置文件,因此必须编辑菜单,关闭内核的selinux功能:
编辑完之后,点击'b'键启动:
启动之后顺利取得bash,并且可以运行ls程序:
实验到此结束。
实例二:
破坏本机grub stage1,在不重启的情况下修复号grub。
用dd命令破坏grub:
[[email protected] ~]# dd if=/dev/sda of=/tmp/mbr.bak count=1 bs=512 //先备份MBR; 1+0 records in 1+0 records out 512 bytes (512 B) copied, 0.000376481 s, 1.4 MB/s [[email protected] ~]# [[email protected] ~]# dd if=/dev/zero of=/dev/sda count=1 bs=100 //开始执行破坏操作; 1+0 records in 1+0 records out 100 bytes (100 B) copied, 0.0010733 s, 93.2 kB/s //注意:破坏其前446Bytes即可。
修复grub:
方式一: [[email protected] ~]# grub-install --root-directory=/ /dev/sda 方式二: [[email protected] ~]# dd if=/dev/zero of=/dev/sda count=1 bs=100 1+0 records in 1+0 records out 100 bytes (100 B) copied, 0.000691542 s, 145 kB/s [[email protected] ~]# grub .....(中间省略)..... grub> grub> root (hd0,0) //查看设备; root (hd0,0) Filesystem type is ext2fs, partition type 0x83 grub> grub> setup (hd0) //安装grub; setup (hd0) Checking if "/boot/grub/stage1" exists... no Checking if "/grub/stage1" exists... yes Checking if "/grub/stage2" exists... yes Checking if "/grub/e2fs_stage1_5" exists... yes //这里只安装对应文件系统的stage1.5文件(当前为ext4文件系统); Running "embed /grub/e2fs_stage1_5 (hd0)"... 27 sectors are embedded. succeeded Running "install /grub/stage1 (hd0) (hd0)1+27 p (hd0,0)/grub/stage2 /grub/grub.conf"... succeeded Done. grub> grub> quit quit [[email protected] ~]# //注意:在grub命令行之下执行setup安装时,它会自动去读取指定设备的/boot/grub目录下的stage1 、stage1.5以及stage2文件,如果被破坏或者不存在则重新安装。
实例三:
破坏本机grub stage1,而后在救援模式下修复之。
破坏grub:
[[email protected] ~]# dd if=/dev/zero of=/dev/sda count=1 bs=100 1+0 records in 1+0 records out 100 bytes (100 B) copied, 0.000432857 s, 231 kB/s
重新启动,因为硬盘上的grub程序被破坏,这时第一个被扫描到有bootloader的是光盘,所以直接进入光盘,看到如下界面,这里选择进入救援模式:
系统提示会将原有的根文件系统挂载至光盘系统的/mnt/sysp_w_picpath目录下,选择"Continue"。
点击"OK"进入光盘的shell:
执行根切换,并安装grub,而后重新启动:
这样就可以正常启动系统了。
转载于:https://blog.51cto.com/xuweitao/1901659