GRUB(Boot Loader):
grub:GRand Unified Bootloader
grub 0.x:grub legacy
grub 1.x:grub2
grub主要有2个版本,传统型版本0系列的为grub legacy,1系列的版本为grub2是完全重写的,只在工作特性上兼容grub legacy,但在实现上有了巨大差别;
grub legacy
stage1:mbr
stage1_5:mbr之后的扇区,上stage1中的bootloader能识别stage2所在的分区上的文件系统;
stage2:磁盘分区(/boot/grub/)
配置文件:/boot/grub/grub.conf <-- /etc/grub.conf
stage2及内核等通常放置于一个基本磁盘分区;
功用:
(1)提供菜单、并提供交互式接口
e:编辑模式,用于比较菜单;
c:命令模式,交互式接口;
(2)加载用户选择的内核或操作系统
允许传递参数给内核
可隐藏此菜单
(3)为菜单提供了保护机制
为编辑菜单进行认证
为启动内核或操作系统进行认证
以CentOS 5,6说明,grub legacy的应用;
grub legacy整个运行大体分3个运行阶段,第一阶段是安装在mbr中的;
第二阶段为stage1.5阶段,存放在mbr之后的扇区中,主要作用是让stage1中的bootloader能识别第三阶段(stage2)所在分区上的文件系统;
第三阶段才是真正的stage2,这才提供菜单和编辑时能够看到的界面,叫stage2是存放在磁盘分区上的,一般是挂载至/boot/grub/目录下;grub也有自己的配置文件:/boot/grub/grub.conf且通常有个符号链接文件:/etc/grub.conf;
当系统启动时,加载grub所在磁盘时,会读取磁盘上的MBR,从此能加载到stage1,加载后会尝试读取随后扇区中的stage1.5阶段,读取1.5阶段以后从而就能驱动真正第二阶段stage2所在的磁盘分区了,加载的这个磁盘分区上不但有grub的第二阶段,还包括了内核文件及ramdisk等都在这个分区上存放的;所以这就是为什么grub随后就能够加载内核文件的原因;
注意:当前硬件平台,主板BIOS必须能识别硬盘,然后BIOS才能加载硬盘中的Bootloader,磁盘中的Bootloader自身加载完以后,就能够识别当前主机上的硬盘设备了;但硬盘设备能识别,并不代表硬盘上的文件系统能识别,因为文件系统是额外附加的一层软件组织的文件结构,所以要能够对接一种文件系统,必须要用到文件系统驱动;
对应的应用程序必须能识别和理解这样的文件系统才可以,这种程序就称为文件系统驱动;grub的1.5阶段就是给gurb提供了文件系统驱动的,从而就能够访问对应的第二阶段和内核所在的分区了,这通常是一个基本磁盘分区;所以grub第二阶段以及内核和ramdisk文件通常都会放在一个基本磁盘分区上;因为grub驱动不了逻辑卷,除非给它提供一个特别复杂的接口,才能访问逻辑卷;如果把stage2放在逻辑卷上,就意味着没法被grub1阶段或1.5阶段所加载的;
grub第二阶段的功用或称grub的功用:
第一:提供菜单或交互式接口,例如e编辑菜单,c命令模式,对应grub完全不用读取配置文件,能允许打开内置的命令行提示符,在键入的命令支持下,完成某些操作,这才是真正的交互式接口;
在虚拟机启动时输入任意键,可以进入grub内置命令行接口,输入:c键,显示grub>提示符;例如:
显示帮助命令:grub> help
设定基本磁盘分区设备所在位置:grub> root (hd0,0)
也可手动指明内核:grub> kernel /vmlinuz-2.6.32-504.el6.x86_64 ro root=/dev/mapper/vg0-root
还可指明initrd就跟菜单显示的一样:grub> initrd /initramfs-2.6.32-504.el.x86_64.img
然后使用boot命令启动即可:grub> boot
这就正常启动了;
第二:能加载用户选择的内核或操作系统;加载用户选择的内核时,允许用户通过编辑菜单,传递参数给内核,还可以隐藏此菜单,在打开CentOS 6时就隐藏了;
第三:为菜单通过了保护机制,用户如果想启动内核,有2种机制,第一种是如果要编辑菜单需要输入密码,第二种要启用内核或操作系统要输入密码;
如何设备设备:
(hd#,#)
hd#:磁盘编号,用数字表示,从0开始编号;
#:分区编号,用数字表示,从0开始编号;
(hd0,0)
grub的命令行接口
help:获取帮助列表;
help KEYWORD:获取详细帮助信息;
find (hd#,#)/PATH/TO/SOMEFILE:查找文件;
root (hd#,#):设定指定磁盘分区为grub根;
kernel /PATH/TO/KERNEL_FILE:设定本次启动时用到的内核文件;额外还可添加许多内核支持使用的命令行(command line)参数;
例如:init=/path/to/init, selinux=0, init=1
initrd /PATH/TO/INITRANFS_FILE:设定我选定的内核提供额外文件的ramdisk;
boot:引导启动选定的内核;
查看指定命令的帮助:
grub> help root
root命令是设置当前使用的根设备,对于启动时grub根设备,不是文件系统的根设备,而是第二阶段所在的磁盘分区才是根,这是设置grub的根设备的;
grub是在boot目录下的,而boot是否为单独分区,也就是说根文件系统下有boot目录,这个boot目录是否为单独分区;
在系统启动以后,看到的boot目录有2种可能:boot目录就是grub所在位置,第一种可能是,如果有2个分区,一个为boot分区1(boot单独分区),一个为根分区2:
任何一个存储设备要能访问到,前提是在当前根文件系统上某个路径下必须挂载这个设备并作为其入口;也就是说在分区2的根文件系统上必须有个目录是boot,而boot没作为单独使用的存储空间,而是把它当做另外一个分区(分区1)的访问入口这叫挂载;
因此通过boot所访问的文件,例如要访问/boot/grub文件,这个grub文件是直接存在分区1上的,再例如要找/boot/vmlinuz文件,则vmlinuz文件是直接存在分区1上的;如果操作系统没启动,即grub刚启动时,操作系统还没有启动,就是说bootloader刚加载,内核还没加载根文件系统更不可能加载呢;那么,分区2的根文件系统没加载,就不能通过分区2的根文件系统访问分区1上的/boot/vmlinuz文件,但是,要需要访问分区1上的这个vmlinuz文件,所以对于grub的访问路径就是把分区1当做grub的根分区,所以grub是直接访问自己根下的vmlinuz文件,grub有个root命令就是用来设置grub的根所在磁盘分区的;
所以grub要在第二阶段要去找分区1上的vmlinuz文件,就要把分区1设为grub的根;此时grub绕过了根系统,因为内核都还没启动更别说根文件系统也不可能存在;而由于grub有文件系统驱动,所以能够直接访问分区1,而把这个分区设定为根以后,就可以直接访问这里面的文件了,如vmlinuz文件,就是/vmlinuz,如果访问grub目录下的grub.conf文件,就是/grub/grub.conf;这就是所谓如果boot目录单独分区,grub就可把这个单独分区设定为根,它的访问路径与系统启动后在文件系统上看到的路径是不一样的;
第二种可能,就是boot(grub)不单独分区,还是在分区2根文件上有boot目录,在系统启动前还是没有装载这个根文件系统的,grub的第一阶段加载以后,要去访问grub第二阶段或要找到vmlinuz文件时,此时grub只能把分区2设为自己的根,而boot目录又没有单独分区,这样grub的访问路径是/boot/vmlinuz,例如访问grub目录下的grub.conf文件,路径就是/boot/grub/grub.conf;
boot目录是否为单独的分区或这个引导分区是否为独立的分区,决定了在grub中访问的路径可能是不一样的;
对于grub里的root命令而言,就是用来指明这个根分区是哪的,如果boot目录的单独分区则直接指明这个分区为grub根分区,访问路径就把这个boot路径去了,如果boot目录没有单独挂载分区,就在根分区上的,那么就加上boot路径即可,这与其是否被挂载没有关系,只是要注意,grub要访问某一分区,这一分区必须是基本磁盘分区;
因为grub里面不能提供非常复杂的启动程序(软raid,逻辑卷,btree文件系统);基于软件的设备,grub就不要放上去了;这也就是为什么boot要单独分区的原因,有时要把根做的很复杂,比如把根放在逻辑卷上,将来可以扩展空间,但是如果把boot也放在根(逻辑卷)上,grub就没办法找到grub第二阶段了,所以只能把boot放在基本磁盘分区上;不使用逻辑卷boot可是不单独分区的;在CentOS 5,6上逻辑卷都是官方默认采用的根分区的分区类型,所以创建分区时总是把boot单独创建一个分区;
对于grub legacy来说,识别识别时都以hd开头,标记磁盘时第个一个数字表示第几个磁盘,第二数字表示磁盘的第几分区;例如(hd0,0)表示第一块磁盘的第一个分区(从0开始编号的,grub2就从1开始编号了);
find命令,查找磁盘分区上的文件;例如:
grub> find (hd0,0)/vmlinuz--2.6.32-504.el6.x86_64
指定文件路径,如果有此文件,可使用Tab键补全文件路径或文件名的,可通过find可定位文件位置;
root命令,设定grub的根位置:
grub> root (hd0,0)
kernel命令,指明内核文件的路径,内核文件名中的z表示压缩格式,要先使用root命令指明根后再使用kernel命令;
initrd命令,用来指明ramdisk文件或initrd文件,对CentOS 6是initramfs文件;ramdisk文件版本号必须与内核版本号完全匹配,否则ramdisk中的文件,即模块版本与内核版本不一致,将无法被内核装载;
手动在grub命令行接口启动系统(centos 6):
grub> root (hd#,#)
grub> kernel /vmlinuz-VERSION-RELEASE ro root=/dev/DEVICE
grub> initrd /initramfs-VERSION-RELEASE.img
(centos 5是initrd文件)
grub> boot
演示完整过程:(见截图)
e键进入grub编辑模式,c键进入命令模式,然后指的根,指明内核,可以加上quiet,表示为静默模式,;指明initrd文件,最后使用boot启动;
虚拟机开机时,按任意键,进入GRUB界面;
键入c,输入help命令
键入e
键入c
指定grub根所在位置和内核文件
指定initrd后开始引导启动
配置文件:/boot/grub/grub.conf,或链接文件:/etc/grub.conf
常用配置项:
default=#:设定默认启动的菜单项,菜单项(title)编号从0开始;
timeout=#:指定菜单项等待用户选择的等待时长,要键入回车确定;
splashimage=(hd#,#)/PATH/TO/XPM_PIC_FILE:指明菜单背景图片文件路径;
hiddenmenu:隐藏菜单;
password [--md5] STRING:菜单编辑认证;
titile TITLE:定义菜单项的“标题”,可出现多次;
(缩进)root (hd#,#):grub查找stage2即kernel文件所在设备分区;为grub的“根”;
kernel /PATH/TO/VMLINUZ_FILE [PARAMETERS]:启动的内核;
initrd /PATH/TO/INITRAMFS_FILE:内核匹配的ramfs文件;
password [--md5] STRING:启用选定的内核或操作系统时进行认证;
opsenssl命令;
grub-md5-crypt命令;
配置文件内容:
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS 6 (2.6.32-573.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-573.el6.x86_64 ro root=UUID=74c3491c-52c8-46f1-8e7f-84cd079620e3 rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
initrd /initramfs-2.6.32-573.el6.x86_64.img
title后面设置的内容就是菜单显示的内容;下面缩进的内容,就是子菜单所显示的内容;
可以添加title,指明多个内核,能改变菜单显示;
default是指明默认启动的内核;而titile就是从上至下开始从0编号的;
splashimage设定使用的启动背景图片;格式为xpm格式且要压缩,色深很高分辨率就很高逼真细腻,此处的图片只支持色深14位色,代表只能显示2^14次方种颜色;
使用openssl命令生成grub加密时的密码串,使用比较麻烦;可使用grub-md5-crypt命令;例如:
~]# grub-md5-crypt
Password:
Retype password:
$1$/dqoi$rYUKkuBwaYsq/DFarMf/t1
输入密码后,计算出密文密码;这样就可以在grub配置文件中,设置grub中的密码了,如:
password --md5 $1$/dqoi$rYUKkuBwaYsq/DFarMf/t1
自定义grub配置文件内容:
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
password --md5 $1$/dqoi$rYUKkuBwaYsq/DFarMf/t1
hiddenmenu
title CentOS 6 (2.6.32-573.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-573.el6.x86_64 ro root=UUID=74c3491c-52c8-46f1-8e7f-84cd079620e3 rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
initrd /initramfs-2.6.32-573.el6.x86_64.img
title CentOS 6 (my linux)
root (hd0,0)
kernel /vmlinuz-2.6.32-573.el6.x86_64 ro root=UUID=74c3491c-52c8-46f1-8e7f-84cd079620e3 rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
initrd /initramfs-2.6.32-573.el6.x86_64.img
password --md5 $1$/dqoi$rYUKkuBwaYsq/DFarMf/t1
只要title标题不一样就可以,其它都可以一样;
进入单用户模式:
(1)编辑grub菜单(选定要编辑的title,然后使用“e”命令);
(2)在选定的kernel后附加
1,s,S或singel都可以;
(3)在kernel所在行,键入“b”命令;
安装grub:
(1)grub-install
grub-install --root-directory=ROOT /dev/DISK
(2)grub
grub> root (hd#,#)
grub> setup (hd#)
如果grub配置文件被删了,只是没有提示菜单了,可在命令上手动启动,启动后在手动编辑一个grub配置文件即可;如果grub中的文件损坏,例如mbr中的bootloader损坏,就要修复bootloader,只有一个办法,进入救援模式,或把硬盘拆下来放到其它主机上修复;
使用grub命令可以重新安装和修复grub的,第一种情况,如果当前系统启动完好,那么如果有两块硬盘,想把第二块硬盘安装grub此时就用到grub命令;
第二种情况,如果当前系统没有grub但能借助光盘上的grub来启动,只有能看到grub提示符就能启动硬盘上的系统;
还有一种情况,双系统共存时,windows和linux系统,要先装windows系统,然后在装linux系统才能双系统共存;因为windows不引导其它系统,假如重装了windows系统后,开机linux系统就不能启动了,此时就可借助U盘或其它盘上的grub,启动linux,然后在linux启动后,在linux系统中重装一遍grub,依然会安装系统一样,把windows启动项重新进行编辑,而后把自己的bootloader安装在mbr中去,以后开机就能启动linux了;
使用grub-install命令安装grub,它是完整安装包括grub第一阶段,1.5阶段和第二阶段;第二阶段是在磁盘分区上的boot目录下装一个grub目录;所以必须要找到boot目录之后再此目录下创建一个grub;如果boot目录是一个单独分区,没有与根在同一分区上,面对这种情况,如果有第二块硬盘,要给第二块硬盘安装grub,安装完后boot是在单独分区上的;以后可以把这块硬盘拆下来,拿到启动主机上来启动系统,用虚拟机实现:
例如,再给虚拟机centos 6系统上加一块硬盘并创建分区,以便为boot(grub)单独分区使用,(命令过程省略);创建磁盘分区完成后,就需要挂载,grub要找boot目录,而当前系统的boot在使用,所以可在其它目录下创建一个boot目录就行,例如/mnt/boot/,然后把分区挂载这个boot目录下即可(命令过程省略)例如把/dev/sdb1挂载至/mnt/boot/;然后就可以把grub安装在sdb上:
]# mount /dev/sdb1 /mnt/boot/
注意:sdb1的以后要当做grub的根的;
]# grub-install --root-directory=/mnt /dev/sdb
注意:所以要指定grub根在/mnt下,指定根目录时不要写boot,只有/mnt就行因为它会自动找boot目录的;此时查看/mnt/boot/grub/目录下,就已经安装好了grub文件;但配置文件需要自己写;还需要把内核文件,initramfs文件复制一份;如下:
]# cp /boot/vmlinuz-2.6.32-573.el6.x86_64 /mnt/boot/vmlinuz
]# cp /boot/initramfs-2.6.32-573.el6.x86_64.img /mnt/boot/initramfs.img
]# vim /mnt/boot/grub/gurb.conf
default=0
timeout=5
title CentOS (Express)
root (hd0,0)
kernel /vmlinuz ro root=/dev/sda3(相当于当前主机的sdb3) selinux=0 init=/bin/bash(限定init为bash,而不是/sbin/init了)
initrd /initramfs.img
还有创建根文件系统目录结构:
]# mkdir /mnt/sysroot
]# mount /dev/sdb3 /mnt/sysroot/
]# mkdir -pv etc bin sbin lib lib64 dev proc sys tmp var usr home root mnt media
就复制一个bash文件,以便启动程序做演示,使用init环境比较复杂;
]# cp /bin/bash /mnt/sysroot/bin/
在查看bash依赖哪些库,也要把依赖文件复制过来,否则bash是无法运行的;
]# ldd /bin/bash
]# cp /lib64/libtinfo.so.5 /mnt/sysroot/lib64
]# cp /lib64/libdl.so.2 /mnt/sysroot/lib64
]# cp /lib64/libc.so.6 /mnt/sysroot/lib64
]# cp /lib64/ld-linux-x86-64.so.2 /mnt/sysroot/lib64
测试bash是否能用,要切换根测试;
]# chroot /mnt/sysroot/
此时要把grub配置文件中,加入init=/bin/bash;然后同步一下;
]# sync
然后再新建一个虚拟机,装载刚才制作grub的那块硬盘,此时就可以启动系统了,但没有什么命令可用;要想用命令,找二进制程序文件、库文件、配置文件;
修复grub的方法:
例如,手动破坏bootloader,再创建grub,提前备份bootloader:
]# dd if=/dev/sda of=/root/mbr.bak count=1 bs=512
]# dd if=/dev/zero of=/dev/sda bs=200 count=1
]# sync
]# grub-install --root-directory=/ /dev/sda
完成修复;
注意:指定根下--root-directory=并不要求有boot、grub目录;
另一种修复grub的方法:
进入grub:
]# grub
grub> root (hd0,0):设定根所在设备;
grub> setup (hd0):安装grub第一阶段,指明硬盘即可;
grub> exit
]# sync
]# reboot
注意:指定的根目录下root (hd0,0)必须要有boot、grub目录且里面要有stage1、stage1.5等文件才行;
用紧急救援模式,修复grub:
比如系统启动不起来了,此时要载入系统安装光盘,进入紧急救援模式;选择Rescue installed system;在命令行提示符下,输入:
boot:linux rescue
启动紧急救援模式了,类似于windows中的winPE;
插入安装光盘读取安装:
见截图;
选择Rescue installed system救援模式,或敲Esc键,进入救援模式输入linux rescue
选择语言
选择键盘类型
选择启动网络
查找操作系统,自动挂载至/mnt/sysimage目录下,选择Continue
搜索磁盘上安装的系统
找到磁盘上的系统且挂载至/mnt/sysimage下
确定
启动shell
输入grub-install或直接切换根
执行grub-install等命令
根就是当前系统的根,设备为当前硬盘sda
安装完成后,退回rescue模式
执行reboot
正常启动后,grub就修好了,以上就是紧急救援模式修复grub的过程;