第二十章、开机流程、模组管理与 Loader
最近更新日期:2009/09/14
1. Linux 的开机流程分析
1.1 开机流程一览 1.2 BIOS, boot loader 与 kernel 载入 1.3 第一支程序 init 及设定档 /etc/inittab 与 runlevel 1.4 init 处理系统初始化流程 (/etc/rc.d/rc.sysinit) 1.5 启动系统服务与相关启动设定档 (/etc/rc.d/rc N & /etc/sysconfig) 1.6 使用者自订开机启动程序 (/etc/rc.d/rc.local) 1.7 根据 /etc/inittab 之设定,载入终端机或 X-Window 介面 1.8 开机过程会用到的主要设定档: /etc/modprobe.conf, /etc/sysconfig/* 1.9 Run level 的切换: runlevel, init 2. 核心与核心模组 2.1 核心模组与相依性: depmod 2.2 核心模组的观察: lsmod, modinfo 2.3 核心模组的载入与移除:insmod, modprobe, rmmod 2.4 核心模组的额外参数设定:/etc/modprobe.conf 3. Boot loader: Grub 3.1 boot loader 的两个 stage 3.2 grub 的设定档 /boot/grub/menu.lst 与选单类型: 磁碟代号, menu.lst 3.3 initrd 的重要性与建立新 initrd 文件: mkinitrd 3.4 测试与安装 grub: grub-install, grub shell 3.5 开机前的额外功能修改 3.6 关于核心功能当中的 vga 设定 3.7 BIOS 无法读取大硬碟的问题 3.8 为个别选单加上密码: grub-md5-crypt 4. 开机过程的问题解决 4.1 忘记 root 密码的解决之道 4.2 init 设定档错误 4.3 BIOS 磁碟对应的问题 (device.map) 4.4 因文件系统错误而无法开机 4.5 利用 chroot 切换到另一颗硬碟工作 5. 重点回顾 6. 本章习题 7. 参考资料与延伸阅读 8. 针对本文的建议:http://phorum.vbird.org/viewtopic.php?t=23891 Linux 的开机流程分析 开机不是只要按一下电源钮而关机只要关掉电源钮就可以了吗?有何大学问?话是这样没错啦,但是由于 Linux 是一套多人多工的作业系统,你难保你在关机时没有人在线上,如果你关机的时候碰巧一大群人在线上工作, 那会让当时在线上工作的人马上断线的!那不是害死人了!一些资料可是无价之宝哩! 另外 Linux 在执行的时候,虽然你在画面上只会看到黑压压的一片,完全没有任何画面,
但其实他是有很多的程序在背景底下执行的,例如登录档管控程序、前面提到的例行性工作排程等,
当然还有一大堆网络服务,如邮件服务器、WWW 服务器等等。你如果随便关机的话,
是很容易伤害硬碟及资料传输的动作的!所以在 Linux 下关机可是一门大学问喔。 开机流程一览 既然开机是很严肃的一件事,那我们就来了解一下整个开机的过程吧! 好让大家比较容易发现开机过程里面可能会发生问题的地方,以及出现问题后的解决之道! 不过,由于开机的过程中,那个开机管理程序 (Boot Loader) 使用的软件可能不一样,例如目前各大 Linux distributions 的主流为 grub,但早期 Linux 预设是使用 LILO ,台湾地区则很多朋友喜欢使用 spfdisk 。 但无论如何,我们总是得要了解整个 boot loader 的工作情况,才能了解为何进行多重开机的设定时, 老是听人家讲要先安装 Windows 再安装 Linux 的原因~ 假设以个人电脑搭建的 Linux 主机为例 (先回到第零章计算机概论看看相关的硬体常识喔), 当你按下电源按键后电脑硬体会主动的读取 BIOS 来载入硬体资讯及进行硬体系统的自我测试, 之后系统会主动的去读取第一个可开机的装置 (由 BIOS 设定的) ,此时就可以读入开机管理程序了。 开机管理程序可以指定使用哪个核心文件来开机,并实际载入核心到记忆体当中解压缩与执行, 此时核心就能够开始在记忆体内活动,并探测所有硬体资讯与载入适当的驱动程序来使整部主机开始运作, 等到核心探测硬体与载入驱动程序完毕后,一个最阳春的作业系统就开始在你的 PC 上面跑了。 主机系统开始运作后,此时 Linux 才会呼叫外部程序开始准备软件执行的环境, 并且实际的载入所有系统运作所需要的软件程序哩!最后系统就会开始等待你的登入与操作啦! 简单来说,系统开机的经过可以汇整成底下的流程的:
大概的流程就是上面写的那个样子啦,你会发现 init 这个家伙占的比重非常重! 所以我们才会在第十七章的 pstree 指令中谈到这家伙。 那每一个程序的内容主要是在干嘛呢?底下就分别来谈一谈吧! BIOS, boot loader 与 kernel 载入 我们在第三章曾经谈过简单的开机流程与 MBR 的功能,
当时为了多重开机而进行的简短的介绍。现在你已经有足够的 Linux 基础了,所以底下让我们来加强说明啦!
我们在第零章的计算机概论就曾谈过电脑主机架构, 在个人电脑架构下,你想要启动整部系统首先就得要让系统去载入 BIOS (Basic Input Output System),并透过 BIOS 程序去载入 CMOS 的资讯,并且藉由 CMOS 内的设定值取得主机的各项硬体设定, 例如 CPU 与周边设备的沟通时脉啊、开机装置的搜寻顺序啊、硬碟的大小与类型啊、 系统时间啊、各周边汇流排的是否启动 Plug and Play (PnP, 随插即用装置) 啊、 各周边设备的 I/O 位址啊、以及与 CPU 沟通的 IRQ 岔断等等的资讯。 在取得这些资讯后,BIOS 还会进行开机自我测试 (Power-on Self Test, POST) (注1)。 然后开始执行硬体探测的初始化,并设定 PnP 装置,之后再定义出可开机的装置顺序, 接下来就会开始进行开机装置的资料读取了 (MBR 相关的任务开始)。 由于我们的系统软件大多放置到硬碟中嘛!所以 BIOS 会指定开机的装置好让我们可以读取磁碟中的作业系统核心文件。 但由于不同的作业系统他的文件系统格式不相同,因此我们必须要以一个开机管理程序来处理核心文件载入 (load) 的问题, 因此这个开机管理程序就被称为 Boot Loader 了。那这个 Boot Loader 程序安装在哪里呢?就在开机装置的第一个磁区 (sector) 内,也就是我们一直谈到的 MBR (Master Boot Record, 主要开机记录区)。 那你会不会觉得很奇怪啊?既然核心文件需要 loader 来读取,那每个作业系统的 loader 都不相同, 这样的话 BIOS 又是如何读取 MBR 内的 loader 呢?很有趣的问题吧!其实 BIOS 是透过硬体的 INT 13 中断功能来读取 MBR 的,也就是说,只要 BIOS 能够探测的到你的磁碟 (不论该磁碟是 SATA 还是 IDE 介面),那他就有办法透过 INT 13 这条通道来读取该磁碟的第一个磁区内的 MBR 啦!(注2) 这样 boot loader 也就能够被执行啰!
刚刚说到 Loader 的最主要功能是要认识作业系统的文件格式并据以载入核心到主记忆体中去执行。 由于不同作业系统的文件格式不一致,因此每种作业系统都有自己的 boot loader 啦!用自己的 loader 才有办法载入核心文件嘛!那问题就来啦,你应该有听说过多重作业系统吧?也就是在一台主机上面安装多种不同的作业系统。 既然你 (1)必须要使用自己的 loader 才能够载入属于自己的作业系统核心,而 (2)系统的 MBR 只有一个,那你怎么会有办法同时在一台主机上面安装 Windows 与 Linux 呢? 这就得要回到第八章的磁碟文件系统去回忆一下文件系统功能了。 其实每个文件系统 (filesystem, 或者是 partition) 都会保留一块开机磁区 (boot sector) 提供作业系统安装 boot loader , 而通常作业系统预设都会安装一份 loader 到他根目录所在的文件系统的 boot sector 上。如果我们在一台主机上面安装 Windows 与 Linux 后,该 boot sector, boot loader 与 MBR 的相关性会有点像下图: 图 1.2.1、 boot loader 安装在 MBR, boot sector 与作业系统的关系 如上图所示,每个作业系统预设是会安装一套 boot loader 到他自己的文件系统中 (就是每个 filesystem 左下角的方框),而在 Linux 系统安装时,你可以选择将 boot loader 安装到 MBR 去,也可以选择不安装。 如果选择安装到 MBR 的话,那理论上你在 MBR 与 boot sector 都会保有一份 boot loader 程序的。 至于 Windows 安装时,他预设会主动的将 MBR 与 boot sector 都装上一份 boot loader!所以啦, 你会发现安装多重作业系统时,你的 MBR 常常会被不同的作业系统的 boot loader 所覆盖啦! ^_^ 我们刚刚提到的两个问题还是没有解决啊!虽然各个作业系统都可以安装一份 boot loader 到他们的 boot sector 中, 这样作业系统可以透过自己的 boot loader 来载入核心了。问题是系统的 MBR 只有一个哩! 你要怎么执行 boot sector 里面的 loader 啊?这个我们得要回忆一下第三章约略提过的 boot loader 的功能了。boot loader 主要的功能如下:
由于具有选单功能,因此我们可以选择不同的核心来开机。而由于具有控制权转交的功能,因此我们可以载入其他 boot sector 内的 loader 啦!不过 Windows 的 loader 预设不具有控制权转交的功能,因此你不能使用 Windows 的 loader 来载入 Linux 的 loader 喔!这也是为啥第三章谈到 MBR 与多重开机时,会特别强调先装 Windows 再装 Linux 的缘故。 我们将上述的三个功能以底下的图示来解释你就看的懂了!(与第三章的图示也非常类似啦!) 图 1.2.2、 开机管理程序的选单功能与控制权转交功能示意图 如上图所示,我的 MBR 使用 Linux 的 grub 这个开机管理程序,并且里面假设已经有了三个选单, 第一个选单可以直接指向 Linux 的核心文件并且直接载入核心来开机;第二个选单可以将开机管理程序控制权交给 Windows 来管理,此时 Windows 的 loader 会接管开机流程,这个时候他就能够启动 windows 了。第三个选单则是使用 Linux 在 boot sector 内的开机管理程序,此时就会跳出另一个 grub 的选单啦!了解了吗? 而最终 boot loader 的功能就是‘载入 kernel 文件’啦!
当我们藉由 boot loader 的管理而开始读取核心文件后,接下来, Linux 就会将核心解压缩到主记忆体当中, 并且利用核心的功能,开始测试与驱动各个周边装置,包括储存装置、CPU、网络卡、音效卡等等。 此时 Linux 核心会以自己的功能重新探测一次硬体,而不一定会使用 BIOS 探测到的硬体资讯喔!也就是说,核心此时才开始接管 BIOS 后的工作了。 那么核心文件在哪里啊?一般来说,他会被放置到 /boot 里面,并且取名为 /boot/vmlinuz 才对!
从上表我们也可以知道此版本的 Linux 核心为 2.6.18-92.el5 这个版本!为了硬体开发商与其他核心功能开发者的便利, 因此 Linux 核心是可以透过动态载入核心模组的 (就请想成驱动程序即可),这些核心模组就放置在 /lib/modules/ 目录内。 由于模组放置到磁碟根目录内 (要记得 /lib 不可以与 / 分别放在不同的 partition !), 因此在开机的过程中核心必须要挂载根目录,这样才能够读取核心模组提供载入驱动程序的功能。 而且为了担心影响到磁碟内的文件系统,因此开机过程中根目录是以唯读的方式来挂载的喔。 一般来说,非必要的功能且可以编译成为模组的核心功能,目前的 Linux distributions 都会将他编译成为模组。 因此 USB, SATA, SCSI... 等磁碟装置的驱动程序通常都是以模组的方式来存在的。 现在来思考一种情况,假设你的 linux 是安装在 SATA 磁碟上面的,你可以透过 BIOS 的 INT 13 取得 boot loader 与 kernel 文件来开机,然后 kernel 会开始接管系统并且探测硬体及尝试挂载根目录来取得额外的驱动程序。 问题是,核心根本不认识 SATA 磁碟,所以需要载入 SATA 磁碟的驱动程序, 否则根本就无法挂载根目录。但是 SATA 的驱动程序在 /lib/modules 内,你根本无法挂载根目录又怎么读取到 /lib/modules/ 内的驱动程序?是吧!非常的两难吧!在这个情况之下,你的 Linux 是无法顺利开机的! 那怎办?没关系,我们可以透过虚拟文件系统来处理这个问题。 虚拟文件系统 (Initial RAM Disk) 一般使用的档名为 /boot/initrd ,这个文件的特色是,他也能够透过 boot loader 来载入到记忆体中, 然后这个文件会被解压缩并且在记忆体当中模拟成一个根目录, 且此模拟在记忆体当中的文件系统能够提供一支可执行的程序,透过该程序来载入开机过程中所最需要的核心模组, 通常这些模组就是 USB, RAID, LVM, SCSI 等文件系统与磁碟介面的驱动程序啦!等载入完成后, 会帮助核心重新呼叫 /sbin/init 来开始后续的正常开机流程。 图 1.2.3、 BIOS 与 boot loader 及核心载入流程示意图 如上图所示,boot loader 可以载入 kernel 与 initrd ,然后在记忆体中让 initrd 解压缩成为根目录, kernel 就能够藉此载入适当的驱动程序,最终释放虚拟文件系统,并挂载实际的根目录文件系统, 就能够开始后续的正常开机流程。更详细的 initrd 说明,你可以自行使用 man initrd 去查阅看看。 底下让我们来了解一下 CentOS 5.x 的 initrd 文件内容有什么吧! ^_^
嘿嘿!透过上述执行档的内容,我们可以知道 initrd 有载入模组并且尝试挂载了虚拟文件系统。 接下来就能够顺利的运作啦!那么是否一定需要 initrd 呢?
在核心完整的载入后,您的主机应该就开始正确的运作了,接下来,就是要开始执行系统的第一支程序: /sbin/init。 第一支程序 init 及设定档 /etc/inittab 与 runlevel 在核心载入完毕、进行完硬体探测与驱动程序载入后,此时你的主机硬体应该已经准备就绪了 (ready) ,
此时核心会主动的呼叫第一支程序,那就是 /sbin/init 啰。这也是为啥第十七章的 pstree 指令介绍时,你会发现 init 的 PID 号码是一号啦。
/sbin/init 最主要的功能就是准备软件执行的环境,包括系统的主机名称、网络设定、语系处理、文件系统格式及其他服务的启动等。
而所有的动作都会透过 init 的设定档,亦即是 /etc/inittab 来规划,而
inittab 内还有一个很重要的设定项目,那就是预设的 runlevel (开机执行等级) 啦!
那么什么是 run level 呢?他有什么功用啊?其实很简单啦, Linux 就是藉由设定 run level 来规定系统使用不同的服务来启动,让 Linux 的使用环境不同。基本上,依据有无网络与有无 X Window 而将 run level 分为 7 个等级,分别是:
由于 run level 0, 4, 6 不是关机、重新开机就是系统保留的,所以:‘
您当然不能将预设的 run level 设定为这三个值 ’,
否则系统就会不断的自动关机或自动重新开机....
好了,那么我们开机时,到底是如何取得系统的 run level 的?当然是 /etc/inittab 所设定的啰!
那么 /etc/inittab 到底有什么资讯呢?我们先来看看这个文件的内容好了:
让我们解析一下这个文件吧!首先,这个文件的语法是利用冒号 (:) 将设定分隔成为四个栏位,每个栏位的意义与说明如下:
事实上 /etc/inittab 的设定也有点类似 shell script 啦,因为该文件内容的设定也是一行一行的从上往下处理的, 因此我们可以知道 CentOS 的 init 依据 inittab 设定的处理流程会是:
现在你可以知道为啥 [ctrl]+[alt]+[del] 可以重新开机而我们预设提供 6 个虚拟终端机 (tty1~tty6) 给你使用了吧!由于整个设定都是依据 /etc/inittab 来决定的,因此如果你想要修改任何细节的话, 可以这样做喔:
所以说,你现在会自行修改登入时的预设 run level 设定值了吗?够简单的吧? 一般来说,我们预设都是 3 或者是 5 来作为预设的 run level 的。但有时后可能需要进入 run level 1, 也就是单人维护模式的环境当中。这个 run level 1 有点像是 Windows 系统当中的‘安全模式’啦, 专门用来处理当系统有问题时的操作环境。此外,当系统发现有问题时,举例来说,不正常关机造成 filesystem 的不一致现象时,系统会主动的进入单人维护模式呢! 好了, init 在取得 run level 之后,接下来要干嘛? 上面 /etc/inittab 文件内容不是有提到 sysinit 吗?准备初始化系统了吧! init 处理系统初始化流程 (/etc/rc.d/rc.sysinit) 还记得上面提到 /etc/inittab 里头有这一句‘ si::sysinit:/etc/rc.d/rc.sysinit ’吧? 这表示:‘我开始载入各项系统服务之前,得先做好整个系统环境,我主要利用 /etc/rc.d/rc.sysinit 这个 shell script 来设定好我的系统环境的。’够清楚了吧? 所以,我想要知道到底 CentOS 开机的过程当中帮我进行了什么动作,就得要仔细的分析 /etc/rc.d/rc.sysinit 啰。
如果你使用 vim 去查阅过 /etc/rc.d/rc.sysinit 的话,那么可以发现他主要的工作大抵有这几项:
在 /etc/rc.d/rc.sysinit 将基本的系统设定资料都写好了,也将系统的资料设定完整! 而如果你想要知道到底开机的过程中发生了什么事情呢?那么就执行‘ dmesg ’吧。 另外,基本上,在这个文件当中所进行的很多工作的预设设定档,其实都在 /etc/sysconfig/ 当中呢! 所以,请记得将 /etc/sysconfig/ 内的文件好好的瞧一瞧喔! ^_^ 在这个过程当中,比较值得注意的是自订模组的载入!在 CentOS 当中,如果我们想要载入核心模组的话, 可以将整个模组写入到 /etc/sysconfig/modules/*.modules 当中,在该目录下, 只要记得档名最后是以 .modules 结尾即可。 这个过程是非必要的,因为我们目前的预设模组实在已经很够用了,除非是您的主机硬体实在太新了, 非要自己载入新的模组不可,否则,在经过 /etc/rc.d/rc.sysinit 的处理后, 你的主机系统应该是已经跑得很顺畅了啦!就等着你将系统相关的服务与网络服务启动啰! 启动系统服务与相关启动设定档 (/etc/rc.d/rc N & /etc/sysconfig) 载入核心让整个系统准备接受指令来工作,再经过 /etc/rc.d/rc.sysinit 的系统模组与相关硬体资讯的初始化后,你的 CentOS 系统应该已经顺利工作了。 只是,我们还得要启动系统所需要的各项‘服务’啊!这样主机才能提供我们相关的网络或者是主机功能嘛! 这个时候,依据我们在 /etc/inittab 里面提到的 run level 设定值,就可以来决定启动的服务项目了。 举例来说,使用 run level 3 当然就不需要启动 X Window 的相关服务啰,您说是吧? 那么各个不同的 run level 服务启动的各个 shell script 放在哪?还记得 /etc/inittab 里面提到的:
上面提到的就是各个 run level 要执行的各项脚本放置处啦!主要是透过 /etc/rc.d/rc 这个指令来处理相关任务! 由于鸟哥使用预设的 runlevel 5 ,因此我们主要针对上述特殊字体那行来解释好了: /etc/rc.d/rc 5 的意义是这样的 (建议您自行使用 vim 去观察一下 /etc/rc.d/rc 这个文件,你会更有概念!):
透过上面的说明我们可以知道所有的项目都与 /etc/rc5.d/ 有关,那么我们就来瞧瞧这个目录下有些什么玩意儿吧!
在这个目录下的文件很有趣,主要具有几个特点:
我们在第十八章谈过服务的启动主要是以‘/etc/init.d/服务档名 {start,stop}’来启动与关闭的,那么透过刚刚 /etc/rc.d/rc 程序的解说,我们可以清楚的了解到了 /etc/rc5.d/[SK]xx 其实就是跑到 /etc/init.d/ 去找到相对应的服务脚本, 然后分别进行 start (Sxx) 或 stop (Kxx) 的动作而已啦!举例来说,以上述的表格内的 K91capi 及 S10network 为例好了, 透过 /etc/rc.d/rc 5 的执行,这两个文件会这样进行:
所以说,你有想要启动该 runlevel 时就执行的服务,那么利用 Sxx 并指向 /etc/init.d/ 的特定服务启动脚本后, 该服务就能够在开机时启动啦!就这么简单!问题是,你需要自行处理这个 K, S 开头的连结档吗? 并不需要的,第十八章谈到的 chkconfig 就是在负责处理这个连结档啦!这样有没有跟第十八章的观念串在一起了呢? ^_^ 那么为什么 K 与 S 后面要有数字呢?因为各不同的服务其实还是互有关系的。举例来说,如果要启动 WWW 服务,总是得要有网络吧?所以 /etc/init.d/network 就会比较先被启动啦!那么您就会知道在 S 或者是 K 后面接的数字是啥意思了吧?嘿嘿,那就是执行的顺序啦!那么哪个文件被最后执行呢? 看到最后一个被执行的项目是啥?没错,就是 S99local ,亦即是: /etc/rc.d/rc.local 这个文件啦! 使用者自订开机启动程序 (/etc/rc.d/rc.local) 在完成预设 runlevel 指定的各项服务的启动后,如果我还有其他的动作想要完成时,举例来说, 我还想要寄一封 mail 给某个系统管理帐号,通知他,系统刚刚重新开机完毕,那么是否应该要制作一个 shell script 放置在 /etc/init.d/ 里面,然后再以连结方式连结到 /etc/rc5.d/ 里面呢?呵呵!当然不需要!还记得上一小节提到的 /etc/rc.d/rc.local 吧? 这个文件就可以执行您自己想要执行的系统指令了。 也就是说,我有任何想要在开机时就进行的工作时,直接将他写入 /etc/rc.d/rc.local , 那么该工作就会在开机的时候自动被载入喔!而不必等我们登入系统去启动呢! 是否很方便啊!一般来说,鸟哥就很喜欢把自己制作的 shell script 完整档名写入 /etc/rc.d/rc.local ,如此一来,开机就会将我的 shell script 执行过,真是好棒那! 根据 /etc/inittab 之设定,载入终端机或 X-Window 介面 在完成了系统所有服务的启动后,接下来 Linux 就会启动终端机或者是 X Window 来等待使用者登入啦! 实际参考的项目是 /etc/inittab 内的这一段:
这一段代表,在 run level 2, 3, 4, 5 时,都会执行 /sbin/mingetty 这个咚咚, 而且执行六个,这也是为何我们 Linux 会提供‘六个纯文字终端机’的设定所在啊! 因为 mingetty 就是在启动终端机的指令说。 要注意的是那个 respawn 的 init 动作项目,他代表‘当后面的指令被终止 (terminal) 时, init 会主动的重新启动该项目。’这也是为何我们登入 tty1 终端机介面后,以 exit 离开后, 系统还是会重新显示等待使用者输入的画面的原因啊! 如果改天您不想要有六个终端机时,可以取消某些终端机介面吗?当然可以啊! 就将上面表格当中的某些项目注解掉即可!例如不想要 tty5 与 tty6 ,就将那两行注解, 则下次重新开机后,您的 Linux 就只剩下‘ F1 ~ F4 ’有效而已,这样说,可以了解吧!!^_^ 至于如果我们使用的是 run level 5 呢?那么除了这六个终端机之外, init 还会执行 /etc/X11/prefdm -nodaemon 那个指令喔!该指令我们会在第二十四章、X Window 再来详谈! 他主要的功能就是在启动 X Window 啦! 开机过程会用到的主要设定档 我们在 /sbin/init 的运作过程中有谈到许多执行脚本,包括 /etc/rc.d/rc.sysinit 以及 /etc/rc.d/rc 等等,
其实这些脚本都会使用到相当多的系统设定档,这些开机过程会用到的设定档则大多放置在 /etc/sysconfig/ 目录下。
同时,由于核心还是需要载入一些驱动程序 (核心模组),此时系统自订的装置与模组对应档 (/etc/modprobe.conf)
就显的挺重要了喔!
还记得我们在 /etc/rc.d/rc.sysinit 当中谈到的载入使用者自订模组的地方吗?就是在 /etc/sysconfig/modules/ 目录下啊! 虽然核心提供的预设模组已经很足够我们使用了,但是,某些条件下我们还是得对模组进行一些参数的规划, 此时就得要使用到 /etc/modprobe.conf 啰!举例来说,鸟哥的 CentOS 主机的 modprobe.conf 有点像这样:
这个文件大多在指定系统内的硬体所使用的模组啦!这个文件通常系统是可以自行产生的,所以你不必手动去订正他! 不过,如果系统捉到错误的驱动程序,或者是你想要使用更新的驱动程序来对应相关的硬体配备时, 你就得要自行手动的处理一下这个文件了。 以上表的第一行为例,鸟哥使用螃蟹卡 (Realtek 的晶片组) 来作为我的网络卡,那螃蟹卡使用的模组就是 8139too
啦!这样看的懂了吧?当我要启动网络卡时,系统会跑到这个文件来查阅一下,然后载入 8139too
驱动程序来驱动网络卡啰!更多的相关说明,请 man modprobe.conf 喔!
不说您也知道,整个开机的过程当中,老是读取的一些服务的相关设定档都是记录在 /etc/sysconfig 目录下的!那么该目录底下有些啥玩意儿?我们找几个重要的文件来谈谈:
总而言之一句话,这个目录下的文件很重要的啦!开机过程里面常常会读取到的! Run level 的切换 在我们完成上面的所有资讯后,其实整个 Linux 主机就已经在等待我们使用者的登入啦! 但是,相信您应该还是会有一点疑问的地方,那就是:‘我该如何切换 run level 呢?’会不会很难啊?不会啦!很简单~但是依据执行的时间而有不同的方式啊! 事实上,与 run level 有关的启动其实是在 /etc/rc.d/rc.sysinit 执行完毕之后。也就是说,其实 run level 的不同仅是 /etc/rc[0-6].d 里面启动的服务不同而已。不过,依据开机是否自动进入不同 run level 的设定,我们可以说:
假设原本我们是以 run level 5 登入系统的,但是因为某些因素,想要切换成为 run level 3 时, 该怎么办呢?很简单啊,执行‘ init 3 ’即可切换。但是 init 3 这个动作到底做了什么呢? 我们不是说了吗?事实上,不同的 run level 只是载入的服务不同罢了, 亦即是 /etc/rc5.d/ 还有 /etc/rc3.d 内的 Sxxname 与 Kxxname 有差异而已。 所以说,当执行 init 3 时,系统会:
也就是说,两个 run level 都存在的服务就不会被关闭啦!如此一来,就很容易切换 run level 了, 而且还不需要重新开机呢!真方便。那我怎么知道目前的 run level 是多少呢? 直接在 bash 当中输入 runlevel 即可啊!
那么你能不能利用 init 来进行关机与重新开机呢?可以的啦!利用‘ init 0 ’就能够关机, 而‘ init 6 ’就能够重新开机!为什么?往前翻一下 runlevel 的定义即可了解吧! 核心与核心模组 谈完了整个开机的流程,您应该会知道,在整个开机的过程当中,是否能够成功的驱动我们主机的硬体配备, 是核心 (kernel) 的工作!而核心一般都是压缩档,因此在使用核心之前,就得要将他解压缩后, 才能载入主记忆体当中。 另外,为了应付日新月异的硬体,目前的核心都是具有‘可读取模组化驱动程序’的功能, 亦即是所谓的‘ modules (模组化)’的功能啦!所谓的模组化可以将他想成是一个‘外挂程序’, 该外挂程序可能由硬体开发厂商提供,也有可能我们的核心本来就支援~不过,较新的硬体, 通常都需要硬体开发商提供驱动程序模组啦! 那么核心与核心模组放在哪?
如果该核心被顺利的载入系统当中了,那么就会有几个资讯纪录下来:
问题来啦,如果我有个新的硬体,偏偏我的作业系统不支援,该怎么办?很简单啊!
上面第一点还很好理解,反正就是重新编译核心就是了。不过,核心编译很不容易啊!
我们会在后续章节约略介绍核心编译的整个程序。比较有趣的则是将该硬体的驱动程序编译成为模组啦!
关于编译的方法,可以参考后续的第二十二章、原始码与 tarball的介绍。
我们这个章节仅是说明一下,如果想要载入一个已经存在的模组时,该如何是好? 核心模组与相依性 既然要处理核心模组,自然就得要了解了解我们核心提供的模组之间的相关性啦! 基本上,核心模组的放置处是在 /lib/modules/$(uname -r)/kernel 当中,里面主要还分成几个目录:
如果要我们一个一个的去检查这些模组的主要资讯,然后定义出他们的相依性, 我们可能会疯掉吧!所以说,我们的 Linux 当然会提供一些模组相依性的解决方案啰~ 对啦!那就是检查 /lib/modules/$(uname -r)/modules.dep 这个文件啦!他记录了在核心支援的模组的各项相依性。 那么这个文件如何建立呢?挺简单!利用 depmod 这个指令就可以达到建立该文件的需求了!
以上面的范例一为例,我们的 Linux kernel 2.6.x 版本的核心模组副档名一定是 .ko 结尾的, 当你使用 depmod 之后,该程序会跑到模组标准放置目录 /lib/modules/$(uname -r)/kernel , 并依据相关目录的定义将全部的模组捉出来分析,最终才将分析的结果写入 modules.dep 文件中的呐! 这个文件很重要喔!因为他会影响到本章稍后会介绍的 modprobe 指令的应用! 核心模组的观察 那你到底晓不晓得目前核心载入了多少的模组呢?粉简单啦!利用 lsmod 即可!
使用 lsmod 之后,系统会显示出目前已经存在于核心当中的模组,显示的内容包括有:
也就是说,模组其实真的有相依性喔!举上表为例, mii 这个模组会被 8139too 所使用。 简单的说,就是‘当你要载入 8139too 时,需要先载入 mii 这个模组才可以顺利的载入 8139too’的意思。 那么除了显示出目前的模组外,我还可以查阅每个模组的资讯吗?举例来说,我们知道 8139too 是螃蟹卡的驱动程序,那么 mii 是什么咚咚?就用 modinfo 来观察吧!
事实上,这个 modinfo 除了可以‘查阅在核心内的模组’之外,还可以检查‘某个模组文件’, 因此,如果你想要知道某个文件代表的意义为何,利用 modinfo 加上完整档名吧! 看看就晓得是啥玩意儿啰! ^_^ 核心模组的载入与移除 好了,如果我想要自行手动载入模组,又该如何是好?有很多方法啦,最简单而且建议的,是使用 modprobe 这个指令来载入模组, 这是因为 modprobe 会主动的去搜寻 modules.dep 的内容,先克服了模组的相依性后, 才决定需要载入的模组有哪些,很方便。至于 insmod 则完全由使用者自行载入一个完整档名的模组, 并不会主动的分析模组相依性啊!
他立刻就将该模组载入啰~但是 insmod 后面接的模组必须要是完整的‘档名’才行!那如何移除这个模组呢?
使用 insmod 与 rmmod 的问题就是,你必须要自行找到模组的完整档名才行,而且如同上述范例二的结果, 万一模组有相依属性的问题时,你将无法直接载入或移除该模组呢!所以近年来我们都建议直接使用 modprobe 来处理模组载入的问题,这个指令的用法是:
使用 modprobe 真的是要比 insmod 方便很多!因为他是直接去搜寻 modules.dep 的纪录, 所以啰,当然可以克服模组的相依性问题,而且还不需要知道该模组的详细路径呢! 好方便! ^_^
核心模组的额外参数设定: /etc/modprobe.conf 这个文件我们之前已经谈过了,这里只是再强调一下而已,如果您想要修改某些模组的额外参数设定, 就在这个文件内设定吧!我们假设一个案例好了,假设我的网络卡 eth0 是使用 ne , 但是 eth1 同样也使用 ne ,为了避免同一个模组会导致网络卡的错乱, 因此,我可以先找到 eth0 与 eth1 的 I/O 与 IRQ ,假设:
则:
嘿嘿!如此一来,我的 Linux 就不会捉错网络卡的对应啰!因为被我强制指定某个 I/O 咯嘛! ^_^ Boot Loader: Grub 在看完了前面的整个开机流程,以及核心模组的整理之后,你应该会发现到一件事情,
那就是‘ boot loader 是载入核心的重要工具’啊!没有 boot loader 的话,那么
kernel 根本就没有办法被系统载入的呢!所以,底下我们会先谈一谈 boot loader 的功能,
然后再讲一讲现阶段 Linux 里头最主流的 grub 这个 boot loader 吧! boot loader 的两个 stage 我们在第一小节开机流程的地方曾经讲过,在 BIOS 读完资讯后,接下来就是会到第一个开机装置的 MBR 去读取 boot loader 了。这个 boot loader 可以具有选单功能、直接载入核心文件以及控制权移交的功能等, 系统必须要有 loader 才有办法载入该作业系统的核心就是了。但是我们都知道, MBR 是整个硬碟的第一个 sector 内的一个区块,充其量整个大小也才 446 bytes 而已。 我们的 loader 功能这么强,光是程序码与设定资料不可能只占不到 446 bytes 的容量吧?那如何安装? 为了解决这个问题,所以 Linux 将 boot loader 的程序码执行与设定值载入分成两个阶段 (stage) 来执行:
那么这些设定档是放在哪里啊?这些与 grub 有关的文件都放置到 /boot/grub 中,那我们就来看看有哪些文件吧!
从上面的说明你可以知道 /boot/grub/ 目录下最重要的就是设定档 (menu.lst) 以及各种文件系统的定义! 我们的 loader 读取了这种文件系统定义资料后,就能够认识文件系统并读取在该文件系统内的核心文件啰。 至于 grub 的设定档档名,其实应该是 menu.lst 的,只是在 Red Hat 里面被定义成为 /boot/grub.conf 而已。 鸟哥建议您还是记忆 menu.lst 比较好喔! 所以从上面的文件来看, grub 认识的文件系统真的非常多喔!正因为如此,所以 grub 才会取代 Lilo 这个老牌的 boot loader 嘛!好了,接下来就来瞧瞧设定档内有啥设定值吧! grub 的设定档 /boot/grub/menu.lst 与选单类型 grub 是目前使用最广泛的 Linux 开机管理程序,旧的 Lilo 这个开机管理程序现在已经很少见了, 所以本章才会将 Lilo 的介绍舍弃的说。grub 的优点挺多的,包括有:
上面第三点其实就是 Stage 1, Stage 2 分别安装在 MBR (主程序) 与文件系统当中 (设定档与定义档) 的原因啦!
好了,接下来,让我们好好了解一下 grub 的设定档: /boot/grub/menu.lst 这玩意儿吧!
要注意喔,那个 lst 是 LST 的小写,不要搞错啰!
安装在 MBR 的 grub 主程序,最重要的任务之一就是从磁碟当中载入核心文件, 以让核心能够顺利的驱动整个系统的硬体。所以啰, grub 必须要认识硬碟才行啊!那么 grub 到底是如何认识硬碟的呢? 嘿嘿! grub 对硬碟的代号设定与传统的 Linux 磁碟代号可完全是不同的!grub 对硬碟的识别使用的是如下的代号: (hd0,0) 够神了吧?跟 /dev/hda1 风马牛不相干~怎么办啊?其实只要注意几个东西即可,那就是:
所以说,第一颗‘搜寻到的硬碟’代号为:‘(hd0)’,而该颗硬碟的第一号分割槽为‘(hd0,0)’,这样说了解了吧? 反正你要记得,在 grub 里面,他开始的数字是 0 而不是 1 就是了!
所以说,整个硬碟代号为:
这样应该比较好看出来了吧?第一颗硬碟的 MBR 安装处的硬碟代号就是‘(hd0)’, 而第一颗硬碟的第一个分割槽的 boot sector 代号就是‘(hd0,0)’第一颗硬碟的第一个逻辑分割槽的 boot sector 代号为‘(hd0,4)’了了吧!
了解了 grub 当中最麻烦的硬碟代号后,接下来,我们就可以瞧一瞧设定档的内容了。先看一下鸟哥的 CentOS 内的 /boot/grub/menu.lst 好了:
在 title 以前的四行,都是属于 grub 的整体设定,包括预设的等待时间与预设的开机项目, 还有显示的画面特性等等。至于 title 后面才是指定开机的核心文件或者是 boot loader 控制权。 在整体设定方面的项目主要常见的有:
整体设定的地方大概是这样,而底下那个 title 则是显示开机的设定项目。如同前一小节提到的,开机时可以选择 (1)直接指定核心文件开机或 (2)将 boot loader 控制权转移到下个 loader (此过程称为 chain-loader)。每个 title 后面接的是‘该开机项目名称的显示’,亦即是在选单出现时,选单上面的名称而已。 那么这两种方式的设定有啥不同呢?
initrd 的重要性与建立新 initrd 文件 我们在本章稍早之前‘ boot loader 与 kernel 载入’的地方已经提到过 initrd 这玩意儿,他的目的在于提供开机过程中所需要的最重要核心模组,以让系统开机过程可以顺利完成。 会需要 initrd 的原因,是因为核心模组放置于 /lib/modules/$(uname -r)/kernel/ 当中, 这些模组必须要根目录 (/) 被挂载时才能够被读取。但是如果核心本身不具备磁碟的驱动程序时, 当然无法挂载根目录,也就没有办法取得驱动程序,因此造成两难的地步。 initrd 可以将 /lib/modules/.... 内的‘开机过程当中一定需要的模组’包成一个文件 (档名就是 initrd), 然后在开机时透过主机的 INT 13 硬体功能将该文件读出来解压缩,并且 initrd 在记忆体内会模拟成为根目录, 由于此虚拟文件系统 (Initial RAM Disk) 主要包含磁碟与文件系统的模组,因此我们的核心最后就能够认识实际的磁碟, 那就能够进行实际根目录的挂载啦!所以说:‘initrd 内所包含的模组大多是与开机过程有关,而主要以文件系统及硬碟模组 (如 usb, SCSI 等) 为主’的啦! 一般来说,需要 initrd 的时刻为:
一般来说,各 distribution 提供的核心都会附上 initrd 文件,但如果你有特殊需要所以想重制 initrd 文件的话, 可以使用 mkinitrd 来处理的。这个文件的处理方式很简单, man mkinitrd 就知道了! ^_^。 我们还是简单的介绍一下去!
initrd 建立完成之后,同时核心也处理完毕后,我们就可以使用 grub 来建立选单了!底下继续瞧一瞧吧! 测试与安装 grub 如果你的 Linux 主机本来就是使用 grub 作为 loader 的话,那么你就不需要重新安装 grub 了, 因为 grub 本来就会主动去读取设定档啊!您说是吧!但如果你的 Linux 原来使用的并非 grub , 那么就需要来安装啦!如何安装呢?首先,你必须要使用 grub-install 将一些必要的文件复制到 /boot/grub 里面去,你应该这样做的:
所以说, grub-install 是安装 grub 相关的文件 (例如文件系统定义档) 到你的装置上面去等待在开机时被读取,但还需要设定好设定档 (menu.lst) 后,再以 grub shell 来安装 grub 主程序到 MBR 或者是 boot sector 上面去喔!好了,那我们来思考一下想要安装的资料。
我们已经将设定档处理完毕,但是你要知道的是,我们并不知道 /dev/hda1 到底有没有包含 grub 的主程序, 因此我们想要将 grub 主程序再次的安装到 /dev/hda1 的 boot sector ,也想要重新安装 grub 到 MBR 上面去。 此时我们就得要使用 grub shell 啰!整个安装与 grub shell 的动作其实很简单, 如果您有兴趣研究的话,可以使用 info grub 去查阅~鸟哥这里仅介绍几个有用的指令而已。
由于我们最需要安装的就是那个 stage1 啦!那才是 grub 的主程序嘛!而且设定档通常与主程序摆在同一个目录下。 因此我们需要使用 root (hd0,0) 去找到 /boot/grub/stage1 喔!接下来,请用 grub 来进入 grub shell 吧!进入 grub 后,会出现一个‘ grub> ’的提示字元啊!
如此一来,就已经将 grub 安装到 MBR 及 /dev/hda1 的 boot sector 里面去了! 而且读取的是 (hd0,0) 里面的 /grub/menu.lst 那个文件喔!真是很重要啊!重要到不行! 最后总结一下:
开机前的额外功能修改 事实上,上一个小节设定好之后,你的 grub 就已经在你的 Linux 系统上面了,而且同时存在于 MBR 与 boot sector 当中呢!所以,我们已经可以重新开机来查阅看看啦! 另外,如果你正在进行开机,那么请注意,我们可以在预设选单 (鸟哥的范例当中是 30 秒) 按下任意键, 还可以进行 grub 的‘线上编修’功能喔!真是棒啊!先来看看开机画面吧! 图 3.5.1、grub 开机画面示意图 由于鸟哥将隐藏选单的功能取消了,因此你会直接看到这四个选单,同时会有读秒的咚咚在倒数。 选单部分的画面其实就是 title 后面的文字啦!你现在知道如何修改 title 后面的文字了吧! ^_^。 如果你使用上下键去选择第二 (/dev/hda1 boot sector) 或第三 (MBR loader) 时,会发现同样的画面重复出现! 这是因为那两个是 loader 移交而已嘛!而我们都使用相同的 grub 与相同的 menu.lst 设定档! 因此这个画面就会重复出现了!这样了解乎? 另外,如果你再仔细看的话,会发现到上图中底部还有一些细部的选项,似乎有个 'e' edit 的样子! 没错~ grub 支援线上编修指令喔!这是个很有用的功能!假如刚刚你将 menu.lst 的内容写错了,导致出现无法开机的问题时, 我们可以查阅该 title 选单的内容并加以修改喔!举例来说,我想要知道第一个选单的实际内容时,将反白光棒移动到第一个选单, 再按下 'e' 会进入如下画面: 图 3.5.2、grub 单一选单内容 哈哈!这不就是我们在 menu.lst 里面设定的东西吗?没错!此时你还可以继续进一步修改喔! 注意看到上图最底下的说明,你还可以使用:
我们说过, grub 是可以直接使用核心文件来开机的,所以,如果您很清楚的知道你的根目录 (/) 在那个 partition ,而且知道你的核心文件档名 (通常都会有个 /boot/vmlinuz 连结到正确的档名), 那么直接在图三的画面当中,以上述的 o, d, e 三个按键来编修,成为类似底下这样: 图 3.5.3、grub edit 的线上编修功能 按下 [Enter] 按键后,然后输入 b 来 boot ,就可以开机啦!所以说,万一你的 /boot/grub/menu.lst 设定错误,或者是因为安装的缘故,或者是因为核心文件的缘故,导致无法顺利开机时,记得啊,可以在 grub 的选单部分, 使用 grub shell 的方式去查询 (find) 或者是直接指定核心文件,就能够开机啦! ^_^ 另外,很多时候我们的 grub 可能会发生错误,导致‘连 grub 都无法启动’,那么根本就无法使用 grub 的线上编修功能嘛!怎么办?没关系啊!我们可以利用具有 grub 开机的 CD 来开机, 然后再以 CD 的 grub 的线上编修,嘿嘿!同样可以使用硬碟上面的核心文件来开机啦!很好玩吧! ^_^ 关于核心功能当中的 vga 设定 事实上,你的 tty1~tty6 除了 80x24 的解析度外,还能够有其他解析度的支援喔!但前提之下是你的核心必须支援 FRAMEBUFFER_CONSOLE 这个核心功能选项才行。如何确定有没有支援呢?你可以查阅 /boot/config-2.6.18-92.el5 这个文件,然后这样搜寻:
那么如何调整 tty1 ~ tty6 终端机的解析度呢?先参考底下的表格再说 (此为十进位数值):
假设你想要将你的终端机荧幕解析度调整到 1024x768 ,且色彩深度为 15bit 色的时候,就得要指定 vga=790 那个数字! 举例来说,鸟哥的 tty1 就想要这样的解析度时,你可以这样做:
重新开机并选择此选单进入 Linux,你跑到 tty1 去看看,嘿嘿!就已经是 1024x768 的解析度啰! 只是字会变的很小,但是画面的范围会加大就是了。不过,某些版本支援的是 16 进位制,所以还需要修改一下格式呢! 一般使用上表当中的值应该就可以了。不过,由于不同的作业系统与硬体可能会有不一样的情况,因此, 上面的值不见得一定可以在您的机器上面测试成功,建议您可以分别设定看看哩~以找出可以使用的值! ^_^ BIOS 无法读取大硬碟的问题 现今的硬碟容量越来越大,如果你使用旧的主机板来安插大容量硬碟时,可能由于系统 BIOS 或者是其他问题, 导致 BIOS 无法判断该硬碟的容量,此时你的系统读取可能会有问题。为什么呢? 我们在本章一开始的开机流程讲过,当进入 Linux 核心功能后,他会主动的再去探测一下整个系统, 因此 BIOS 捉不到的硬体在 Linux 核心反而可能会可以捉到而正常使用。举例来说,过去很多朋友常常会发现, ‘我的系统使用 DVD 开机安装时,可以顺利的安装好 Linux ,但是第一次开机时, 荧幕只出现黑压压的一片,且出现 grub> 的字样,而无法进入 Linux 系统中’,这又是怎么一回事?
更多 grub 错误的代码查询可以到底下的连结查阅: 现在你知道问题所在啦!那就是 BIOS 无法读取大容量磁碟内的 kernel 与 initrd 文件。 那如何解决呢?很简单啦!就让 kernel 与 initrd 文件放置在大硬碟的最前头,由于 BIOS 至少可以读到大磁碟的 1024 磁柱内的资料,因此就能够读取核心与虚拟文件系统的文件啰。那如何让 kernel 与 initrd 放置到整颗硬碟的最前面呢?简单的要命吧!就建立 /boot 独立分割槽,并将 /boot 放置到最前面即可!更多其他的解决方案可参考文后的延伸阅读(注4) 万一你已经安装了 Linux 且发生了上述的问题,那该怎办?你可以这样作的:
不过,鸟哥还是建议您可以重新安装,并且制作出 /boot 这个 partition 啦! ^_^!这也是为啥这次更版中, 鸟哥特别强调要分割出 /boot 这个分割槽的原因啊! 为个别选单加上密码 想像一个环境,如果你管理的是一间电脑教室,这间电脑教室因为可对外开放,但是你又担心某些 partition 被学生不小心的弄乱,因此你可能会想要将某些开机选单作个保护。这个时候,为每个选单作个加密的密码就是个可行的方案啦! 那如何在开机的过程里面提供密码保护呢?首先,你必须要建立密码,而且还需要是加密过后的喔! 否则人家跑到 /boot/grub/menu.lst 不就可以探查到你的开机密码了?那如何建立加密的密码呢? 我们可以透过 grub 提供的 md5 编码来处理的,如下所示:
上面产生的最后一行,由 $ 开始到 . 结束的那行,就是你的密码经过 md5 编码过后的咚咚! 将这个密码复制下来吧!假设我们要将第一个选项加入这个密码,而第四个选项加入另外的密码, 那你应该要这样做:
上表的案例中,我们两个选单进入的密码并不相同,可以进行同学的分类啦!不过这样也造成一个问题, 那就是一定要输入密码才能够进入开机流程,如果你在远端使用 reboot 重新开机,并且主机前面并没有任何人的话.... 你的主机并不会主动进入开机程序喔! ^_^ 你必须要注意的是:password 这个项目一定要在 title 底下的第一行。 不过,此项功能还是可能被破解的,因为使用者可以透过编辑模式 (e) 进入选单,并删除密码栏位并按下 b 就能够进行开机流程了!真糟糕!那怎办?只好透过整体的 password (放在所有的 title 之前) , 然后在 title 底下的第一行设定 lock ,那使用者想要编辑时,也得要输入密码才行啊!设定有点像这样:
那么重新开机后,画面会像这样: 图 3.8.1、 grub 加密的示意图 你可以看到最下方仅出现 p 的功能,由于 2, 3, 4 选单并没有使用 lock ,因此这三个选单使用者还是可以执行开机程序, 但是第一个选单由于有 lock 项目,因此除非你输入正确的密码,否则第一个选单是无法被载入执行的。 另外,这个项目也能够避免你的 menu.lst 在开机的过程中被乱改,是具有保密 menu.lst 的功能啦! 与刚刚的选单密码功能不同。 开机过程的问题解决 很多时候,我们可能因为做了某些设定,或者是因为不正常关机 (例如未经通知的停电等等) 而导致系统的
filesystem 错乱,此时,Linux 可能无法顺利开机成功,那怎么办呢?难道要重装?当然不需要啦!
进入 run level 1 (单人维护模式) 去处理处理,应该就 OK 的啦!底下我们就来谈一谈如何处理几个常见的问题! 忘记 root 密码的解决之道 大家都知道鸟哥的记忆力不佳,容易忘东忘西的,那如果连 root 的密码都忘记了,怎么办? 其实在 Linux 环境中 root 密码忘记时还是可以救回来的!只要能够进入并且挂载 / , 然后重新设定一下 root 的密码,就救回来啦!这是因为开机流程中,若强制核心进入 runlevel 1 时, 预设是不需要密码即可取得一个 root 的 shell 来救援的。整个动作有点像这样:
init 设定档错误 前一个 root 密码挽救的方法其实可以用在很多地方,唯一一个无法挽救的情况,那就是 /etc/inittab 这个文件设定错误导致的无法开机!根据开机流程,我们知道 runlevel 0~6 都会读取 /etc/inittab 设定档, 因此你使用 single mode (runlevel 1) 当然也是要读取 /etc/inittab 来进行开机的。那既然无法进入单人维护模式, 就表示这题无解啰?非也非也,既然预设的 init 无法执行,那我们就告诉核心不要执行 init ,改呼叫 bash 啊! 可以略过 init 吗?可以的,同样在开机进入 grub 后,同样在 grub edit 的情况下这样做:
因为我们指定了核心呼叫的第一支程序 (init) 变成 /bin/bash,因此 /sbin/init 就不会被执行。 又根据开机流程的说明,我们知道此时虽然可以利用 root 取得 bash 来工作,但此时 (1)除了根目录外,其他的目录都没有被挂载; (2)根目录被挂载成为唯读状态。因此我们还需要进行一些动作才行!如下所示: 图 4.2.1、 略过 init 的程序,直接进入 bash shell 鸟哥仅下达两个指令,‘ mount -o remount,rw / ’用途是将根目录重新挂载成为可读写,至于‘ mount -a ’则是参考 /etc/fstab 的内容重新挂载文件系统! 此时你又可以开机进行救援的工作了!只是救援完毕后,你得要使用‘ reboot ’重新开机一次才行! BIOS 磁碟对应的问题 (device.map) 由于目前硬碟很便宜啊,所以很多朋友就想说:‘那我能不能将 Windows 安装在 /dev/hda 而 Linux 安装在 /dev/hdb , 然后调整 BIOS 的开机装置顺序,如此则两套系统各有各的 loader 安装在个别硬碟的 MBR 当中了!’。 这个想法非常好,如此一来两者就不会互相干扰,因为每颗磁碟的 MBR 个别有不同作业系统的 loader 嘛! 问题是,grub 对磁碟的装置代号使用的是探测到的顺序啊! 也就是说,你调整了 BIOS 磁碟开机顺序后,你的 menu.lst 内的装置代号就可能会对应到错误的磁碟上了!啊!真想哭! 没关系的,我们可以透过 /boot/grub/device.map 这个文件来写死每个装置对 grub 磁碟代号的对应喔! 举例来说,鸟哥的这个文件内容如下:
如果你不清楚如何处理的话,也可以利用 grub-install 的功能喔!例如:
这样 device.map 就会主动的被更新了!这样了解乎? 因文件系统错误而无法开机 如果因为设定错误导致无法开机时,要怎么办啊?这就更简单了!最容易出错的设定而导致无法顺利开机的步骤,通常就是 /etc/fstab 这个文件了,尤其是使用者在实作 Quota 时,最容易写错参数, 又没有经过 mount -a 来测试挂载,就立刻直接重新开机,真要命!无法开机成功怎么办? 这种情况的问题大多如下面的画面所示: 图 4.4.1、 文件系统错误的示意图 看到最后两行,他说可以输入 root 的密码继续加以救援喔!那请输入 root 的密码来取得 bash 并以 mount -o remount,rw / 将根目录挂载成可读写后,继续处理吧!其实会造成上述画面可能的原因除了 /etc/fstab 编辑错误之外,如果你曾经不正常关机后,也可能导致文件系统不一致 (Inconsistent) 的情况, 也有可能会出现相同的问题啊!如果是磁区错乱的情况,请看到上图中的第二行处, fsck 告知其实是 /dev/md0 出错, 此时你就应该要利用 fsck 去检测 /dev/md0 才是!等到系统发现错误,并且出现‘clear [Y/N]’时,输入‘ y ’吧! 这个 fsck 的过程可能会很长,而且如果你的 partition 上面的 filesystem 有过多的资料损毁时, 即使 fsck 完成后,可能因为伤到系统槽,导致某些关键系统文件资料的损毁,那么依旧是无法进入 Linux 的。此时,就好就是将系统当中的重要资料复制出来,然后重新安装,并且检验一下, 是否实体硬碟有损伤的现象才好!不过一般来说,不太可能会这样啦~ 通常都是 fsck 处理完毕后,就能够顺利再次进入 Linux 了。 利用 chroot 切换到另一颗硬碟工作 仔细检查一下,你的 Linux 里面应该会有一个名为 chroot 的指令才对!这是啥? 这是‘ change root directory ’的意思啦!意思就是说,可以暂时将根目录移动到某个目录下, 然后去处理某个问题,最后再离开该 root 而回到原本的系统当中。 举例来说,补习班中心最容易有两三个 Linux 系统在同一个主机上面,假设我的第一个 Linux 无法进入了,那么我可以使用第二个 Linux 开机,然后在第二个 Linux 系统下将第一个 Linux 挂载起来, 最后用 chroot 变换到第一个 Linux ,就能够进入到第一个 Linux 的环境当中去处理工作了。 你同样也可以将你的 Linux 硬碟拔到另一个 Linux 主机上面去,然后用这个 chroot 来切换, 以处理你的硬碟问题啊!那怎么做啊?粉简单啦!
重点回顾
本章习题 ( 要看答案请将滑鼠移动到‘答:’底下的空白处,按下左键圈选空白处即可察看 )
简答题部分:
参考资料与延伸阅读
2003/02/10:第一次完成 2005/09/19:将旧的文章移动到 此处 。 2005/09/26:将 核心编译 一文订为进阶篇,不一定要学啦!但是核心模组不可不题,所以,新增一小节! 2005/09/28:终于给他完成去!好累~ 2005/10/09:加上参考文献资料,以及修改一些些 kernel 开机时, grub 的 vga 设定值的解说。 2005/11/09:加上了关于较大硬碟所产生的困扰! 2006/08/21:MBR 应该只有 512 bytes ,结果误植为 512 Kbytes ,抱歉! 2007/06/27:新增 initrd 的说明,请参考这里。 2009/04/09:将旧的基于 FC4 的文章移动到此处。 2009/04/10:取消了 LILO 的 boot loader 说明!毕竟这玩意儿已经退流行!所以不再强调!有需要请查询此处。 2009/04/30:修订完毕,加强 init=/bin/bash 的说明,以及 grub 的密码管理! 2009/09/14:加入情境模拟,并根据讨论区 linuxfans 兄的建议,修改了一些地方!详情请参考讨论区建议! |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||