感谢支持
我们一直在努力

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会提供多种文件系统的驱动,如下:

[root@localhost grub]# ls -1F
device.map
e2fs_stage1_5
fat_stage1_5
ffs_stage1_5
grub.conf
iso9660_stage1_5
jfs_stage1_5
menu.lst@
minix_stage1_5
reiserfs_stage1_5
splash.xpm.gz
stage1
stage2
ufs2_stage1_5
vstafs_stage1_5
xfs_stage1_5
[root@localhost 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)为菜单提供保护机制。可以为编辑菜单提供认证,用户需要通过认证方可编辑指定菜单;也可以为内核或操作系统提供认证,用户需要通过认证方可启动指定的内核或操作系统;

演示:

启动时进入编辑菜单:

wKioL1izdmCj6-ypAAAvhQUYt4M663.png

键入e键可以编辑菜单,如下所示,再此时再键入一次e键就可以编辑选定的参数了。

wKiom1izduHxyaqWAAA7UN7KhW8150.png

按下Esc键可以返回第一个菜单界面,再键入c键可以直接进入命令行模式(交互式接口):

wKioL1izd-zAmZ_fAAAfIVMnF3g994.png

通过’help’可查看帮助,而’help KEYWORD’则可以查看指定项的详细帮助:

wKiom1izeIPRcyQ9AABeqd5rBRc140.png

wKiom1izeNCwFvfaAABY-1o1S0M072.png

可以通过find命令查找文件,例如查找/boot分区下的内核文件:

wKiom1izjSCzdo2PAAAsNPoZRjw226.png

用户可以通过这个交互式接口指定要加载的内核及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的“根”下的文件路径,如下所示:

wKioL1iziBiQ4nkTAAAxOEwscoc810.png

这里在Kernel指定路径之后至少还要传递两个参数,一个是’ro’,指明是以只读方式挂载根文件系统,’root=xxx’这一样则指明根文件系统所在分区,这里实验环境的根文件系统所在分区是一个LVM逻辑卷。最后键入’boot’即可加载指定的内核或操作系统并完成启动。

更多详情见请继续阅读下一页的精彩内容: http://www.linuxidc.com/Linux/2017-03/141971p2.htm

Grub的配置文件:/boot/grub/grub.conf <— /etc/grub.conf(链接文件)

配置项:

defaults=#:设定默认要启动的菜单项;菜单项(title)从0开始编号;

timeout=#:设定菜单项等待用户选择的时长;

splashimage=(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文件,如图:

wKiom1izpKyhgA07AACpU_BV0wo569.png

保存退出,并重新启动:

[root@localhost ~]# reboot

可以看到如下界面:

wKiom1izpbOQBJLqAAAuJJBJxZU185.png

重新编辑菜单,为CentOS 6 (test)这一菜单项指向的内核添加启动认证:

[root@localhost ~]# grub-md5-crypt 
Password:         //输入设定的密码;
Retype password: 
$1$n.0tB/$AStqQTLYFdyC5GcI0BymR/        //得到单向加密后的密码字符串;
[root@localhost ~]#

复制加密得到的密码字符串,添加至/etc/grub/grub.conf文件中CentOS 6 (test)菜单项之下:

wKioL1izp87QUMh4AAC4w9jJco8298.png

重新启动至菜单界面,这时如果要选择CentOS 6 (test)这一菜单项来启动时就需要通过密码验证才能加载内核:

wKiom1izqSiQLxGBAAACLD-ESJg970.png

同样可添加菜单编辑认证,在/etc/grub/grub.conf文件中作如下修改:

wKioL1izquPDkmIdAADTlOfXhh4945.png这里全局的菜单编辑认证加密的密码同样可以由grub-md5-crypt生成,此处直接使用内核认证的密码。

重新启动,进入菜单界面:

wKioL1izq_nCpAPNAAAmij9P-lU567.png

这里只能先键入p键并输入密码才能编辑菜单。

实例一:

新加硬盘,为这块新添加的硬盘安装grub程序,制作成在用户空间能单独运行bash的系统,并把硬盘拆下来装至另外的物理主机。

首先添加一块20G的硬盘:

wKioL1izrajTf9WYAABRzx8T80o739.png

启动主机,首先为这块硬盘分区:/dev/sdb1, /dev/sdb2, /dev/sdb3,其中/dev/sdb1作为/boot分区,/dev/sdb2作为swap分区,而/dev/sdb3作为/分区:

[root@localhost ~]# fdisk /dev/sdb

分区后强制让内核重新识别:

[root@localhost ~]# 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
[root@localhost ~]
[root@localhost ~]# 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

对各分区进行格式化:

[root@localhost ~]# mke2fs -t ext4 /dev/sdb1
[root@localhost ~]# mke2fs -t ext4 /dev/sdb3
[root@localhost ~]# mkswap /dev/sdb2

根分区挂载至/mnt/sysroot/,/boot分区挂载至/mnt/sysroot/boot:

[root@localhost ~]# mkdir /mnt/sysroot
[root@localhost ~]# mkdir /mnt/sysroot/boot
[root@localhost ~]# mount /dev/sdb3 /mnt/sysroot/
[root@localhost ~]# mount /dev/sdb1 /mnt/sysroot/boot/

给/dev/sdb这块磁盘安装grub:

[root@localhost ~]# 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
[root@localhost ~]#

查看文件:

[root@localhost ~]# cd /mnt/sysroot/boot/
[root@localhost boot]# ls        //查看/mnt/sysroot/boot分区下的文件;
grub  lost+found        //缺少Kernel文件和ramdisk文件;
[root@localhost boot]# cd grub/
[root@localhost 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上的文件):

[root@localhost ~]# cp /boot/vmlinuz-2.6.32-642.el6.x86_64 /mnt/sysroot/boot/vmlinuz 
[root@localhost ~]# 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在根目录下创建各个基础目录:

[root@localhost ~]# cd /mnt/sysroot/
[root@localhost sysroot]# mkdir etc bin sbin usr var dev mnt media proc sys root lib 
lib64 home

拷贝/bin/bash程序及其所依赖到的库文件:

[root@localhost ~]# cp /bin/bash /mnt/sysroot/bin/
[root@localhost ~]
[root@localhost ~]# 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)
[root@localhost ~]
[root@localhost ~]# cp /lib64/libtinfo.so.5 /mnt/sysroot/lib64/
[root@localhost ~]# cp /lib64/libdl.so.2 /mnt/sysroot/lib64/
[root@localhost ~]# cp /lib64/libc.so.6 /mnt/sysroot/lib64/
[root@localhost ~]# cp /lib64/ld-linux-x86-64.so.2 /mnt/sysroot/lib64/

以同样的方法,拷贝/bin/ls程序及其所依赖到的库文件。

所有步骤完成之后,先执行根切换测试一下:

[root@localhost ~]# 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
[root@localhost ~]
[root@localhost ~]# sync    //执行同步;

测试成功!

关机之后,查看刚才添加的磁盘文件名 ==> CentOS 6.8-1.vmdk:

wKiom1izwfXQdXthAAFD7FKCMis309.png

新建虚拟机:

wKiom1izwG3jpt_VAABTE4NI-K0711.png

创建时选择“使用现有虚拟磁盘”:

wKiom1izwfahI5wNAACnMpb_aac940.png

选择刚才查看到的磁盘文件(CentOS 6.8-1.vmdk):

wKioL1izwfaAx_LLAAIu3i9DGkc302.png

创建完成之后启动新建的虚拟机,可以看到菜单界面如下:

wKioL1izwtOQEBrNAAAxqsJwbDw562.png

因为默认会开启selinux,而这里系统没有selinux的相关程序及配置文件,因此必须编辑菜单,关闭内核的selinux功能:

wKioL1izxRCDnTJsAAAkFcI8G6I849.png

编辑完之后,点击’b’键启动:

wKiom1izxRDwHu8mAAA6jFs3nXc704.png

启动之后顺利取得bash,并且可以运行ls程序:

wKiom1izxY2h6MdbAABTNTztiMk292.png

实验到此结束。

实例二:

破坏本机grub stage1,在不重启的情况下修复号grub。

用dd命令破坏grub:

[root@localhost ~]# 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
[root@localhost ~]
[root@localhost ~]# 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:

方式一:
[root@localhost ~]# grub-install --root-directory=/ /dev/sda
 
方式二:
[root@localhost ~]# 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
[root@localhost ~]# 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
[root@localhost ~]#
 
//注意:在grub命令行之下执行setup安装时,它会自动去读取指定设备的/boot/grub目录下的stage1
、stage1.5以及stage2文件,如果被破坏或者不存在则重新安装。

实例三:

破坏本机grub stage1,而后在救援模式下修复之。

破坏grub:

[root@localhost ~]# 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的是光盘,所以直接进入光盘,看到如下界面,这里选择进入救援模式:

wKioL1izzFeQdNTLAAYtzg6w3Xc174.png

系统提示会将原有的根文件系统挂载至光盘系统的/mnt/sysimage目录下,选择”Continue”。

wKioL1izzavD8juFAAA-BQx9wNM672.png

wKiom1izzavwo9d1AAAgDbp1PCQ689.png

wKioL1izzayjUXKwAAAOKsNFNok873.png

点击”OK”进入光盘的shell:

wKiom1izza2QPBesAABD28U6Hvo534.png

执行根切换,并安装grub,而后重新启动:

wKiom1izztej1c7mAAAq0VhjnPM800.png

这样就可以正常启动系统了。

本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-03/141971.htm

赞(0) 打赏
转载请注明出处:服务器评测 » GRUB应用详解
分享到: 更多 (0)

听说打赏我的人,都进福布斯排行榜啦!

支付宝扫一扫打赏

微信扫一扫打赏