CentOS 6.x系统启动过程发生了较大的变化,使用Upstart启动服务取代了原先的System V init启动服务。Upstart启动服务的效率更高,启动速度更快。我们学习Linux的启动过程,有助于了解Linux系统的结构,也对系统的排错有很大的帮助。
启动过程比较复杂,我们先整理一下基本的启动过程, 有一个整体的印象,然后再进一步说明。目前CentOS 6.x的启动流程是这样的:
Boot Loader
(启动引导程序,最为常见的是GRUB)。Boot Loader
的设置加载内核,内核会再进行一遍系统检测。系统一般会采用内核检测硬件的信息,而不一定采用BIOS的自检信息。内核在检测硬件的同时,还会通过加载动态模块的形式加载硬件的驱动。/sbin/init
。/sbin/init
进程调用/etc/init/rcS.conf
配置文件,通过这个配置文件调用/etc/rc.d/rc.sysinit
配置文件。而/etc/rc.d/rc.sysinit
配置文件是用来进行系统初始化的,主要用于配置计算机的初始环境。/etc/init/rcS.conf
配置文件调用/etc/inittab
配置文件。通过/etc/inttab
配置文件来确定系统的默认运行级别。/etc/init/rc.conf
配置文件。/etc/init/rc.conf
配置文件调用并执行/etc/rc.d/rc
脚本,并传入运行级别参数。/etc/rc.d/rc
确定传入的运行级别,然后运行相应的运行级别目录/etc/rc[0-6].d/
中的脚本。/etc/rc[0-6].d/
目录中的脚本依据设定好的优先级依次启动和关闭。/etc/rc.d/rc.local
中的程序。简单来看启动过程就是这样的,接下来分别介绍每步启动过程。
BIOS (Basic Input Output System,基本输入/输出系统)是固化在主板上一个ROM (只读存储器)芯片上的程序,主要保存计算机的基本输入/输出信息、系统设置信息、开机自检程序和系统自启动程序,用来为计算机提供最底层和最直接的硬件设置与控制。
BIOS在系统的启动过程中会加载这些主机信息,并完成第一次系统的自检(第二次自检由内核完成),我们把BIOS的自检过程称作POST (Power On Self Test,加电自检)。自检完成之后,开始执行硬件的初始化,之后定义可以启动的设备的顺序,然后从第一个可以启动的设备的MBR (Main Boot Record,主引导记录)中读取Boot Loader
(启动引导程序)。Linux中最常见的Boot Loader
就是GRUB程序。
MBR也就是主引导记录,位于硬盘的0磁道、0柱面、1扇区中,主要记录了启动引导程序和磁盘的分区表。我们通过图11-1来看看MBR的结构。
图11-1 MBR的结构MBR共占用了一个扇区,也就是512 Byte。其中446 Byte安装了启动引导程序,其后64 Byte描述分区表,最后的2 Byte是结束标记。我们已经知道,每块硬盘只能划分4个主分区,原因就是在MBR中描述分区表的空间只有64 Byte。其中每个分区必须占用16Byte,那么64 Byte就只能划分4个主分区。每个分区的16字节的规划如表11-1所示。
存储字节 | 数据内容及含义 |
---|---|
第1个字节 | 引导标志; |
第2个字节 | 本分区的起始磁道号; |
第3个字节 | 本分区的起始扇面号; |
第4个字节 | 本分区的起始柱面号; |
第5个字节 | 分区类型,可以识别主分区和扩展分区; |
第6个字节 | 本分区的结束磁道号; |
第7个字节 | 本分区的结束扇面号; |
第8个字节 | 本分区的结束柱面号; |
第9~12个字节 | 本分区之前已经占用的扇区数; |
第13~16个字节 | 本分区的总扇区数; |
大家注意到了吧,MBR中最主要的功能就是存储启动引导程序。
BIOS的作用就是自检,然后从MBR中读取出启动引导程序。那么,启动引导程序最主要的作用就是加载操作系统的内核。当然,每种操作系统的启动引导程序都是不同的。
每种操作系统的文件格式不同,因此,每种操作系统的启动引导程序也不一样。不同的操作系统只有使用自己的启动引导程序才能加载自己的内核。如果我的服务器上只安装了一个操作系统,那么这个操作系统的启动引导程序就会安装在MBR中。BIOS调用MBR时读取出启动引导程序,就可以加载内核了。但是在有些时候,我的服务器中安装了多个操作系统,而MBR只有一个,那么在MBR中到底安装哪个操作系统的启动引导程序呢?
很明显,一个MBR是不够用的。每块硬盘只能有一个MBR是不能更改的,所以不可能增加MBR的数量。系统只能在每个文件系统(可以看成分区)中单独划分出一个扇区,称作引导扇区(Boot Sector)。在每个分区的引导扇区中也能安装启动引导程序,也就是说,在MBR和每个单独分区的引导扇区中都可以安装启动引导程序。这样多个操作系统才能安装在同一台服务器中(每个操作系统要安装在不同的分区中),而且每个操作系统都是可以启动的。
但是还有一个问题: BIOS只能找到MBR中的启动引导程序,而找不到在分区的引导扇区中的启动引导程序。那么,要想完成多系统启动,我们的方法是增加启动引导程序的功能,让安装到MBR中的启动引导程序(GRUB)可以调用在分区的引导扇区中的其他启动引导程序。所以启动引导程序就拥有了以下功能:
可以调用其他的启动引导程序,这是多系统启动的关键。不过需要注意的是,Windows的启动引导程序不能调用Linux的启动引导程序,所以我们一般建议先安装Windows,后安装Linux,是为了将Linux的启动弓|导程序安装到MBR中,覆盖Windows的启动引导程序。当然这个安装顺序不是绝对的,就算最后安装了Windows,我们也可以通过手工再安装一遍GRUB的方法,来保证MBR中安装的还是Linux的启动引导程序。
我们画一张示意图来看看启动引导程序的作用,如图11-2所示。
图11-2 启动引导程序的作用GRUB加载了内核之后,内核首先会再进行一次系统的自检,而不一定使用BIOS检测的硬件信息。这时内核终于开始替代BIOS接管Linux的启动过程了。内核完成再次系统自检之后,开始采用动态的方式加载每个硬件的模块,这个动态模块大家可以想象成硬件的驱动(默认Linux硬件的驱动是不需要手工安装的,如果是重要的功能,则会直接编译到内核当中;如果是非重要的功能,比如硬件驱动会编译为模块,则在需要时由内核调用。不过,如果没有被内核识别的硬件,要想驱动,就需要手工安装这个硬件的模块了。具体的安装方法我们在11.3节中介绍)。
那么,Linux的内核到底放在了哪里呢?当然是/boot
的启动目录中了,我们来看看这个目录下的内容吧。
# ls /boot/
我们已经知道,Linux会把不重要的功能编译成内核模块,在需要时再调用,从而保证了内核不会过大。在多数Linux中,都会把硬件的驱动程序编译为模块,这些模块保存在/lib/modules/
目录中。常见的USB、SATA和SCSI等硬盘设备的驱动,还有一些特殊的文件 系统(如LVM、RAID等)的驱动,都是以模块的方式来保存的。
如果Linux安装在IDE硬盘之上,并且采用的是默认的ext3/4文件系统,那么内核启动后加载根分区和模块的加载都没有什么问题,系统会顺利启动。但是如果Linux安装在SCSI硬盘之上,或者采用的是LVM文件系统,那么内核(内核加载入内存是启动引导程序GRUB调用的,并不存在硬盘驱动不识别的问题)在加载根目录之前是需要加载SCSI硬盘或LVM文件系统的驱动的。而SCSI硬盘和LVM文件系统的驱动都是放在硬盘的/lib/modules/
目录中的,既然内核没有办法识别SCSI硬盘或LVM文件系统,那怎么可能读取/lib/modules/
目录中的驱动呢?Linux给出的解决办法是使用initramfs
这个虚拟文件系统来处理这个问题。
CentOS 6.x中使用initramfs虚拟文件系统取代了CentOS 5.x中的initrd RAM Disk。它们的作用类似,可以通过启动引导程序加载到内存中,然后会解压缩并在内存中仿真成一个根目录,并且这个仿真的文件系统能够提供一个可执行程序,通过该程序来加载启动过程中所需的内核模块,比如USB、SATA、SCSI硬盘的驱动和LVM、RAID文件系统的驱动。也就是说,通过initramfs虚拟文件系统在内存中模拟出一个根目录,然后在这个模拟根目录中加载SCSI等硬件的驱动,就可以加载真正的根目录了,之后才能调用Linux的第一个进程/sbin/init
。
Initramfs虚拟文件系统主要有以下优点:
其实大家只需要知道initramfs是为了在内核中建立一个模拟根目录,这个模拟根目录是为了可以调用USB、SATA、SCSI LVM、RAID等硬盘接口或文件系统的驱动模块,加载了驱动模块后才可以加载真正的系统根目录。我们可以通过示意图11-3来表示这个过程。
图11-3 内核启动流程那么既然initramfs
是一个仿真根目录 那么我们是否可以看看这个仿真根目录中到底是什么样子的呢?当然可以,命令如下:
# mkdir /tmp/initramfs
在内核加载完毕,并完成硬件检测与驱动程序加载后,主机硬件已经准备完毕,内核会主动呼叫第一个进程,也就是/sbin/init
。/sbin/init
最主要的功能就是准备软件执行的环境,包括系统的主机名、网络设定、语言、文件系统格式及其他服务的启动等。这里和CentOS 5.x系统相比也有较大变化。在CentOS 5.x系统中,主要是通过init进程的配置文件/etc/inittab
来设定系统,并启动Linux的。但是在CentOS 6.x系统中,由于用Upstart启动服务来替换以前的init,所以在/etc/inittab
配置文件中只能定义系统的默认运行级别,而其他的功能是靠/etc/init/
目录中的其他配置文件实现的。大家可以把/etc/init/
目录中的配置文件看成以前/etc/inittab
这个文件功能的分拆。
加载/sbin/init
进程后,由init进程调用/etc/init/rcS.conf
配置文件。这个配置文件的主要功能如下:
/etc/rc.d/rc.sysinit
,由/etc/rc.d/rc.sysinit
配置文件进行Linux系统初始化。/etc/inittab
,由/etc/inittab
配置文件确定系统的默认运行级别。/etc/init/rcS.conf
配置文件会先调用/etc/rc.d/rc.sysinit
配置文件,如果我们查看这个配置文件,就会发现这个配置文件主要进行了以下几项工作:
我们可以查询/var/log/dmesg
文件或使用dmesg
命令查看系统的初始化信息。当然,我们也可以通过这个命令来看看Linux服务器的硬件信息。
接下来/etc/init/rcS.conf
配置文件会再调用/etc/inittab
配置文件,在CentOS 6.x中,这个配置文件只能用来设置系统的默认运行级别。那么,什么是运行级别呢?其实Linux是通过运行级别来确定系统启动时到底启动哪些服务的。Linux默认有7个运行级别,具体如表11-2所示。
运行级别 | 含义 |
---|---|
0 | 关机; |
1 | 单用户模式,可以想象为 windows 的安全模式,主要用于系统修复; |
2 | 不完全的命令行模式,不含 NFS 服务; |
3 | 完全的命令行模式,就是标准字符界面; |
4 | 系统保留; |
5 | 图形模式; |
6 | 重启动; |
在Linux系统中可以使用runlevel
命令来查看系统的运行级别,命令如下:
# runlevel
在这个命令的结果中,N3
中的N代表在进入这个级别前,上一个级别是什么; 3代表当前级别。N
就是None的意思,也就是说,系统是开机直接进入3运行级别的,没有上一个运行级别。那如果从图形界面切换到字符界面,再查看运行级别,就应该是这样的:
# runlevel
那么,可以手工改变当前的运行级别吗?当然可以了,只需使用init命令(注意这不是init进程) 即可,命令如下:
# init 5
不过要注意,使用init
命令关机和重启并不是太安全,容易造成数据丢失。所以推荐大家使用shutdown
命令进行关机和重启。
知道了运行级别的作用,我们回到系统启动过程中来。/etc/init/rcS.conf
配置文件调用/etc/inittab
配置文件的目的就是确定系统的默认运行级别,也就是系统一开机后会进入那个运行级别。这个文件的内容如下:
# vim /etc/inittab
注意这里的默认运行级别只能写3或5,其他的级别要么就是关机重启,要么就是保留或单用户,都不能作为系统默认运行级别。
一旦确定了默认运行级别,系统就会调用/etc/init/rc.conf
配置文件,传入默认级别作为参数。而/etc/init/rc.conf
配置文件的作用是调用/etc/rc.d/rc
脚本文件。
运行级别参数传入/etc/rc.d/rc
这个脚本文件之后,由这个脚本文件按照不同的运行级别启动/etc/rc[0-6].d/
目录中相应的程序。而/etc/rc[0-6].d/
目录中的程序已经设定好了优先级顺序,按照优先级顺序依次启动相应的程序即可。比如我们的默认运行级别是3,那么这个默认运行级别会先传入/etc/init/rc.conf
配置文件,然后再传入/etc/rc.d/rc
脚本文件,由此脚本文件调用/etc/rc3.d/
目录中所有的程序。这个目录中的程序一般如下:
/etc/rc3.d/k??
开头的文件(??是数字),会按照数字顺序依次关闭。/etc/rc3.d/S??
开头的文件(??是数字),会按照数字顺序依次启动。这些数字就是设定好的优先级,按照数字顺序依次启动和关闭相应的程序,系统就会启动。另外,/etc/rc3.d/
目录中的程序都是链接文件,例如:
# ll /etc/rc3.d/S10network
所以,启动了这些文件,实际上启动了/etc/init.d/
目录中的系统服务。
在/etc/rc[0-6].d/
目录中的程序启动之后,系统的启动就已经完成。不过我们总有一些程序是需要在系统启动之后随着系统一起启动的。这时我们并不需要自己把需要启动的服务链接到/etc/rc3.d/目录中,因为系统给我们准备了/etc/rc.d/rc.local
配置文件。
这个配置文件会在用户登录之前读取,这个文件中写入了什么命令,在每次系统启动时都会执行一次。也就是说,如果有任何需要在系统启动时运行的工作,则只写入/etc/rc.d/rc.locall
配置文件即可。这个文件的内容如下:
# ll /etc/rc.local
Linux的启动过程基本上就是这样的,我们把启动流程图完整,如图11-4所示。
图11-4 Linux启动流程系统的启动过程就是这样的,最终我们就能登录字符界面的Linux了。不过,如果需要启动图形界面的Linux,则还需要调用XWindow接口。
在启动过程中还有一个配置文件会生效,就是/etc/init/start-ttys.conf
,这个文件主要定义了Linux支持的1~6个本地终端(tty[1-6])。如果在本机,则可以使用快捷键Alt+F1 ~F6
来切换这6个本地终端;如果安装并启动了图形界面,则可以使用快捷键Ctrl+Alt+F7
来切换图形终端。
至此,字符界面的启动过程就介绍完了。是不是非常复杂?如果你是初学者,则只需了解,不需要彻底掌握。但是掌握了Linux系统的启动过程,会更加了解Linux的结构。当然,如果你非常自信,则可以尝试安装gentoo Linux这个版本,因为这个Linux版本到目前为止还是纯源码安装的,如果能够安装成功,就会对Linux系统的结构及启动过程有更深入的理解。
在刚刚的启动过程中,我们已经知道启动引导程序(Boot Loader,也就是GRUB)会在启动过程中加载内核,之后内核才能取代BIOS接管启动过程。如果没有启动引导程序,那么内核是不能被加载的。我们接下来就来看看启动引导程序加载内核的过程,当然initramfs
这个虚拟文件系统也是要靠启动引导程序调用的。在CentOS 6.x中,启动引导程序默认是GRUB,GRUB是现在最为流行的启动引导程序,我们也用GRUB来说明启动引导程序的作用。
早期的LILO引导程序已经不是很常见了,GRUB相比来讲有很多优势,主要有:
我们已经知道了GRUB的作用有以下几个:第一,加载操作系统的内核;第二,拥有一个可以让用户选择的菜单,来选择到底启动哪个系统;第三,可以调用其他的启动引导程序,来实现多系统引导。按照启动流程,BIOS在自检完成后,会到第一个启动设备的MBR中读取GRUB。在MBR中用来放置启动引导程序的空间只有446Byte,那么GRUB可以放到这里吗?答案是空间不够,GRUB的功能非常强大,MBR的空间是远不够使用的。那么Linux的解决办法是把GRUB的程序分成了三个阶段来执行。
Stage 1:执行GRUB主程序。 第一阶段是用来执行GRUB主程序的,这个主程序必须放在启动区中(也就是MBR或者引导扇区中)。但是MBR太小了,所以只能安装GRUB的最小的主程序,而不能安装GRUB的相关配置文件。这个主程序主要是用来启动Stage 1.5和Stage 2阶段的。
Stage 1.5:识别不同的文件系统。 Stage 2比较大,只能放在文件系统中(分区),但是Stage 1阶段不能识别不同的文件系统,所以不能直接加载Stage 2阶段。这时需要先加载Stage 1.5阶段,由Stage 1.5来加载不同文件系统中的Stage 2。不过还是有问题,Stage 1.5难道不是放在文件系统中的吗?如果是,那么Stage 1同样不能找到Stage 1.5。其实Stage 1.5还真没有放在文件系统中,而是在安装GRUB时,直接安装到紧跟MBR之后的32 KB的空间中,这段硬盘空间是空白无用的,而且是没有文件系统的,所以Stage 1可以直接读取Stage 1.5。读取了Stage 1.5就能识别不同的文件系统,才能加载Stage 2。
Stage 2:加载GRUB的配置文件。 Stage 2阶段主要就是加载GRUB的配置文件/boot/grub/grub.conf
,然后根据配置文件中的定义,加载内核和虚拟文件系统。接下来内核就可以接管启动过程,继续自检与加载硬件模块了。
Stage 2阶段会加载GRUB的配置文件,而GRUB的配置文件主要放置在/boot/grub/
目录中。我们来看看这个目录下到底有哪些文件。
# cd /boot/grub/
其实,这个目录中主要就是GRUB的配置文件和各种文件系统的Stage 1.5文件。不过GRUB的配置文件有两个:/boot/grub/grub.conf
和/boot/grub/menu.lst
,这两个配置文件是软链接,所以修改哪一个都可以。
我们已经知道Linux系统分区的设备文件名的命名是有严格规范的,类似于/dev/sda1
代表第一块SCSI硬盘的第一个主分区。但是在GRUB中分区的表示方法却完全不同,采用了类似hd(0,0)的方式来表示分区。其实也很好理解,其中:
也就是说,hd(0,0)
代表的是第一块硬盘的第一个分区,和Linux系统中/dev/sda1
的含义类似,只是不再区分是SCSI硬盘还是IDE硬盘。我们用表11-3来说明一下Linux系统对分区的描述和GRUB中对硬盘的描述。
硬盘 | 分区 | Linux中的设备文件名 | GRUB中的设备文件名 |
---|---|---|---|
第一块SCSI硬盘 | 第一个主分区 | /dev/sda1 | hd(0,0) |
第二个主分区 | /dev/sda2 | hd(0,1) | |
扩展分区 | /dev/sda3 | hd(0,2) | |
第一个逻辑分区 | /dev/sda5 | hd(0,4) | |
第二块SCSI硬盘 | 第一个主分区 | /dev/sdb1 | hd(1,0) |
第二个主分区 | /dev/sdb2 | hd(1,1) | |
扩展分区 | /dev/sdb3 | hd(1,2) | |
第一个逻辑分区 | /dev/sdb5 | hd(1,4) |
在这张表中要注意,逻辑分区不能占用主分区与扩展分区的分区号,所以第一个逻辑分区在Linux系统中应该用/dev/sda5
表示,在GRUB中应该用hd(0,4)表示。还要注意GRUB的表示方式只在GRUB的配置文件中生效,一旦离开了GRUB的配置文件,就要使用Linux中的设备文件名来表示分区了。
接下来我们就来看看GRUB的配置文件/boot/grub/grub.conf
中到底写了什么。命令如下:
# vim /boot/grub/grub.conf
这个文件的内容可以分成两部分:前4行为GRUB的整体设置;title以下4行为要启动的CentOS系统的具体配置。这里只安装了一个系统,如果多系统并存,那么每个系统都会有类似的title行存在(不一定都是4行) 。我们先看整体设置。
default=0
:默认启动第一个系统。也就是说,如果在等待时间结束后,用户没有选择进入哪个系统,那么系统会默认进入第一个系统。如果有多系统并存,那么每个系统都会有自己的title字段,如果想要默认进入第二个系统,这里就可以设为default=1
。timeout=5
:等待时间,默认是5秒。也就是在进入系统时,如果5秒内用户没有按下任意键,那么系统会进入default字段定义的系统。当然,也可以手工修改这个等待时间,如果timeout=0
, 则不会等待直接进入系统;如果timeout=-1
, 则会一直等待用户输入,而不会自动进入系统。splashimage=(hd0,0)/grub/splash.xpm.gz
:用来指定GRUB启动时的背景图像的保存位置。记得CentOS 6.x启动时后台的蓝色图像吧,就是这个文件的作用。不过这个文件具体在哪里呢?我们已经说过,hd(0,0)
代表第一块硬盘的第一个分区,而我的系统在安装时/boot
分区就是第一个分区,所以这个背景图像的实际位置就是/boot/grub/splash.xpm.gz
。hiddenmenu
:隐藏菜单。启动时默认只能看到读秒,而不能看到菜单。如果想要看到菜单,则需要按任意键。如果注释了这句话,那么启动时就能直接看到菜单了。再来绍CentOS系统的具体配置。
title CentOS(2.6.32-279.el6.i686)
:title就是标题的意思,也就是说,在title后面写入的是什么,系统启动时在GRUB的启动菜单中看到的就是什么。
root (hd0,0):是指启动程序的保存分区。这里要注意,这个root并不是管理员。在我的系统中,/boot分区是独立划分的,而且设备文件名为/dev/sda1
,所以在GRUB中就被描述为hd(0,0)。
kernel /vmlinuz-2.6.32-279.e16.i686 ro root=UUID=b9a7a1a8-767f- 4a87-8a2b-a535edb362c9 rd_ NO_ LUKS KEYBOARDTYPE=pC KEYTABLE=uS rd_ NO_ _MD crashkernel=auto CN.UTF-8rd_ NO_ _LVM rd_ NO_ _DM rhgb quiet
。
# cat /etc/fstab |grep "/"
可以看到/
分区的UUID和kernel行中的UUID是匹配的。注意一下grep后的/
,在/
后是有空格的。
以上禁用都只是在启动过程中禁用,是为了加速系统启动的。
KEYBOARDTYPE=pc KEYTABLE=us
:键盘类型;crashkernel=auto
:自动为crashkernel预留内存;LANG=zh_CN.UTF-8
:语言环境;Rhgb
:(redhat graphics boot)用图片来代替启动过程中的文字信息。启动完成之后可以使用dmesg命令来查看这些文字信息;Quiet
:隐藏启动信息,只显示重要信息。rd_NO_LUKS
:禁用LUKS。LUKS用于给磁盘加密;rd_NO_MD
:禁用软RAID;rd_NO_DM
:禁用硬RAID;rd_NO_LVM
:禁用LVM;/vmlinuz-2.6.32-279.el6.i686
:指定了内核文件的位置,这里的/是指/boot分区。ro
:启动时以只读方式挂载根文件系统,这是为了不让启动过程影响磁盘内的文件系统。root=UUlD=b9a7a1a8-767f-4a87-8a2b-a535edb362c9
:指定根文件系统的所在位置。这里和以前的Linux版本不太一样了,不再通过分区的设备文件名或卷标号来指定,而是通过分区的UUID来指定的。那么,如何查询分区的UUID呢?方法有很多种,最简单的办法就是查询/etc/fstab
文件。命令如下:Initrd /initramfs-2.6.32-279.el6.i686.img
:指定了initramfs虛拟文件系统镜像文件的所在位置。
GRUB的配置文件的内容就是这样的,主要是kernel行较为复杂。不过,在这个/boot/grub/grub.conf
配置文件中,只启动了一个Linux系统。如果在服务器中既安装了Linux系统,又安装了Windows系统,那么GRUB的配置文件又是什么样子的呢?
其实每个系统都是用title字段来表示的,如果在服务器中又多了一个Windows系统,那么在GRUB的配置文件中只不过就是多了一个title字段而已。不过要注意,我们一般建议先安装Windows系统,后安装Linux系统。原因是Windows系统的启动引导程序无法把启动过程转交到Linux系统的GRUB中,自然就不能启动Linux系统了。如果我们后安装Linux系统,GRUB就会安装到MBR中,覆盖Windows系统的启动引导程序。而GRUB是可以把启动过程转交到Windows系统的启动引导程序中的,所以Windows系统和Linux系统都可以顺利启动(当然,如果真的是后安装Windows系统,则也可以通过手工再安装一次GRUB来覆盖MBR中的Windows系统的启动引导程序,具体方法见11.2.4节)。
那么我们就来看看Windows和Linux双系统并存的GRUB的配置文件是什么样子的。命令如下:
# vi /boot/grub/grub.conf
配置文件的变化主要是多了WinXP这一段。rootnoverify(hd0,0)字段说明这个分区不检测,同时标称了Windows系统的启动分区在第一块硬盘的第一个分区中。也就是Windows系统的C:盘在第一块硬盘的第一个分区中。Chainloader +1的意思是,GRUB会把启动过程转交到位于这个分区的第一个扇区(启动扇区)中的引导程序中。我们已经知道,为了实现多系统启动,除MBR中可以安装启动引导程序外,每个分区的第一个扇区也可以安装启动引导程序。在这个例子中,Windows系统的启动引导程序就被安装到了C:盘所在分区的启动扇区中,chainloader +1就是GRUB把启动过程交给了Windows系统的启动引导程序,所以可以启动Windows系统。
需要手工安装GRUB主要有两种情况:一是Linux系统原先不是使用GRUB作为引导程序,而现在想要使用GRUB来作为引导程序;二是MBR中的引导程序被覆盖,需要在MBR中重新安装GRUB,如先安装了Linux系统,后安装了Windows系统。我们分别介绍这两种情况如何手工安装GRUB引导程序。
我们先来讲第一种情况,就是Linux系统中没有安装GRUB,我们需要重新安装GRUB;或者打算把不是启动分区的某个分区变成启动分区。比如我的系统中新建了一个分区/dev/sdb1
,并挂载到了/tdisk/
目录上(写入fstab文件),我们查看一下新建立的分区,命令如下:
# df -Th
这个分区是我手工建立的,当然不是系统的默认启动分区(系统默认启动分区是/boot分区)。我们用这个分区模拟一个不是采用GRUB作为默认弓|导程序的Linux硬盘,在这个分区中手工安装GRUB引导程序。也就是说,这个实验成功后,/boot分区可以启动系统,/tdisk分区也可以启动系统,具体安装步骤如下:
Step1:使用grub-install
命令在要启动的分区中安装GRUB相关文件。
在/boot分区中有一个/boo/grub/
目录,这个目录中保存的就是GRUB的相关文件(如文件系统的Stage 1.5文件)。我们查看一下/boot分区中的这个目录,如下:
# ls /boot/grub/
但是在/tdisk目录中并不存在这些文件,所以第一步就是要在/tdisk目录中安装这些GRUB相关文件,具体采用grub-install命令。 这个命令的格式如下:
# grub-install [选项] 设备文件名
选项 | 说明 |
---|---|
--root-directory=DIR | DIR为实际目录,也就是手工指定GRUB相关文件的安装目录 |
例子:命令标准格式(举例而已,这里的实验不需要执行)
# grub-install /dev/sda
查看一下/tdisk/boot/grub
目录下文件是否安装上了,命令如下:
# ll /tdisk/boot/grub/
GRUB的相关文件已经安装到/tdisk/boot/grub/
目录中。当然,这些文件还是需要GRUB的配置文件来读取的。大家注意到了吗?/tdisk/boot/grub/
目录中没有grub.conf
或menu.lst
配置文件,这些配文件还是需要依赖/boot/grub/
目录的。
注意:如果系统中没有
grub-install
命令,则说明没有GRUB软件,这时可以源码包安装,也可以YUM包安装。
Step2:修改GRUB的配置文件。
在我们的实验中,GRUB是已经安装好的,所以可以直接修改/boot/grub/grub.conf
配置文件。但如果是没有安装过GRUB的Linux系统手工安装GURB,就需要自己建立GRUB配置文件了。那么我们修改/boot/grub/grub.conf
配置文件如下:
# vim /boot/grub/grub.conf
在title CentOS tdisk
段中不能指定内核镜像和initramfs虚拟文件系统,因为在/tdisk/boot/
目录中只有grub目录,而没有内核镜像文件和initramfs虚拟文件系统的镜像文件,所以需要通过chainloader来调用启动扇区。
Step3:安装GRUB到/dev/sdb1
分区的启动扇区中。
刚刚通过GRUB配置文件中的chainloader来调用启动扇区,但是/dev/sdb1
这个分区是新建立的,它的启动扇区中并没有GRUB程序。所以最后一步就是要在/dev/sdb1
分区的启动扇区中安装GRUB。这时就要利用GRUB交互模式了,如下:
# grub
这时GRUB安装完成了,可以重新启动试验一下了。重启后可以看到如图11-5所示的界面。
图11-5 GRUB界面当然/tdisk
分区中并没有真正的内核,所以最终还是要靠/boot
分区启动。如果是多内核并存的,就可以真正启动了。总结一下,在Linux系统中安装GRUB,或者在新分区中安装GRUB的步骤如下:
grub-install
命令实现的。/boot/grub/grub.conf
。这种情况最常见的就是先安装了Linux系统,后安装了Windows系统,导致MBR中的GRUB被覆盖。而Windows系统的启动引导程序又不能识别Linux系统,从而导致Linux系统不能正常启动。其实这种情况解决起来比第一种情况要简单得多,因为不需要安装GRUB的相关文件和修改GRUB的配置文件,也就是第一种情况的第一步和第二步不需要再执行,因为这是已经安装和修改好的。只需要执行第三步,覆盖MBR中的启动引导程序即可。
但是这里的问题是,应该在什么地方启动GRUB的交互模式呢?第一种情况是,我们是在Linux的命令行中执行grub命令,来启动GRUB交互模式的。第二种情况是已经不能正常启动Linux系统了,当然也就没有Linux的命令行了。在这种情况下,我们需要先利用Linux的光盘修复模式,使用光盘来启动Linux,进入Linux的命令行,再指定grub命令。Linux的光盘修复模式将在11.4节中介绍。我们先假设已经进入了光盘修复模式中的Linux命令行,那么只需执行如下命令即可:
#grub
重启系统之后,就可以发现熟悉的GRUB界面又回来了。这种安装GRUB的方式要比第一种情况简单,因为这并不是全新安装,而仅仅是覆盖安装而已。
Linux在启动时,在GRUB管理界面中是可以通过按e
键进入编辑模式,修改启动选项的。如图11-5所示,每个启动选项都支持按e
键进入编辑模式。在编辑模式中可以修改启动模式,比如进入单用户模式(单用户模式主要用于破解密码,我们将在11.4节中讲解)。有时候,我们不想让用户进入编辑模式,就需要给GRUB菜单加密了。那么,如何生成加密的密码串呢?可以通过命令grub-md5-crypt
来实现。命令如下:
# grub-md5-crypt
这样就可以生成加密的密码串,这个字符串是采用MD5加密的,我们会利用这个加密的密码串来加密GRUB配置文件。
GRUB的加密有两种模式:第一种是给每个启动菜单加密,如果不输入正确的密码,则系统不能正常启动;第二种是给GRUB菜单整体加密,如果想进入编辑模式,则必须输入正确的密码。
如果给每个启动菜单加密,那么系统在启动时进入相应的启动菜单,必须输入正确的密码,否则系统不能启动。具体的方法如下:
# vim /boot/grub/grub.conf
这样就能加密CentOS启动菜单了,在启动时如果不输入正确的密码,否则是不能启动系统的。需要注意的是,password选项一定要在title下面第一行。
如果只是加密单个启动菜单,那么GRUB的编辑模式是不能被锁定的,仍然可以按e
键进入编辑模式。而且在进入编辑模式后,是可以删除password
字段的,再按b
(boot 启动)键就可以不用密码直接进入系统。这时就需要给GRUB菜单整体加密了。在整体加密后,如果想进入GRUB编辑界面,则必须输入正确的密码。加密方法其实只是把password字段换一个位置而已,具体方法如下:
# vim /boot/grub/grub.conf
这样就会把GRUB界面整体加密,想要进入GRUB的编辑界面,必须先输入正确的密码,如题11-6所示。
图11-6 GRUB整体加密注意到了吗?在GRUB界面中已经看不到e
键了,必须输入p
键,并输入正确的密码才能进入编辑界面。但是这样加密,在启动CentOS时,是不需要密码就能正常启动的。如果既需要GRUB的整体加密,又需要系统启动时输入正确的密码,那应该怎么做呢?很简单,方法如下:
# vim /boot/grub/grub.conf
只要在GRUB整体配置中加入password选项,在title中加入lock选项,就可以既加密GRUB编辑界面,又加密系统启动过程了。是不是很简单?
如果安装了Linux的图形界面,则使用图形界面修改分辨率非常方便也很简单。但是如果只安装了字符界面,难道就不能修改分辨率了吗?当然是可以的,只要利用GRUB的配置文件就可以完成。当然需要确定内核是否支持CONFIG_FRAMEBUFFER_CONSOLE
功能,如果没有开启这项功能,则需要重新编译内核。查询方法如下:
# grep "CONFIG_FRAMEBUFFER_CONSOLE" /boot/config-2.6.32-642.el6.x86_64
在字符界面下支持的分辨率列表如表11-4所示。
色深 | 640x480像素 | 800x600像素 | 1024x768像素 | 1280x1024像素 |
---|---|---|---|---|
8位 | 769 | 771 | 773 | 775 |
15位 | 784 | 787 | 790 | 793 |
16位 | 785 | 788 | 791 | 794 |
32位 | 786 | 789 | 792 | 795 |
如果想把字符界面的分辨率设置为1024像素x768像素,色深为16位,则只需要修改GRUB的配置文件,在kernel行最后加入下面的内容:
# vim /boot/grub/grub.conf
然后重新启动系统,就会发现分辨率已经改变了。有些Linux的版本需要将vga的值写成十六进制的,可以先试试表11-4中的数字,如果不行则可以尝试十六进制数。