开机不是只要单击电源钮而关机只要关掉电源钮就可以了吗?有何大学问?话是这样没错啦,但是由于
Linux 是一套多人多任务的操作系统,你难保你在关机时没有人在在线,如果你关机的时候碰巧一大群人在在线工作,
那会让当时在在线工作的人马上断线的!那不是害死人了!一些数据可是无价之宝哩!
另外,与 DOS 环境不同的是, Linux 在执行的时候,虽然你在画面上只会看到黑压压的一片,完全没有任何画面,
但其实他是有很多的程序在背景底下执行的,例如登录文件管控程序、前面两章提到的例行性命令,
当然还有一大堆网络服务,如邮件服务器、WWW服务器等等。你如果随便关机的话,
是很容易伤害硬盘及数据传输的动作的!所以在 Linux 下关机可是一门大学问喔。
既然开机是很严肃的一件事,呵呵,那我们来了解一下整个开机的过程吧!
好让大家比较容易发现开机过程里面发生错误的地方,与解决之道!不过,由于开机的过程中,那个开机管理程序
( Boot Loader ) 使用的软件可能不一样,例如目前各大 Linux distributions 的主流为 grub,
但早期 Linux 预设是使用 LILO ,台湾地区则很多朋友喜欢使用
spfdisk 。
但无论如何,我们总是得要了解整个 boot loader 的工作情况,才能了解为何进行多重引导的设定时,
为何老是听人家讲要先安装 Windows 再安装 Linux 的原因~
我们先来想一想, Linux 整个开机的程序是怎样呢?还记得我们提过,开机时要载入核心,
让核心来驱动整个硬件,这样才能算是一个最阳春、最基础的操作系统吧?然后才能够执行各种程序的运作。
同样的,开机的流程也是需要先加载核心的。不过,加载核心前,却需要一些前置作业,才能够正确无误的加载核心嘛!
所以,整个开机的程序是这样的:
- 加载 BIOS 的硬件信息,并取得第一个开机装置的代号;
- 读取第一个开机装置的 MBR 的 boot Loader (亦即是 lilo, grub, spfdisk 等等) 的开机信息;
- 加载 Kernel 操作系统核心信息, Kernel 开始解压缩,并且尝试驱动所有硬件装置;
- Kernel 执行 init 程序并取得 run-level 信息;
- init 执行 /etc/rc.d/rc.sysinit 档案;
- 启动核心的外挂模块 (/etc/modprobe.conf);
- init 执行 run-level 的各个批处理文件( Scripts );
- init 执行 /etc/rc.d/rc.local 档案;
- 执行 /bin/login 程序,并等待用户登入;
- 登入之后开始以 Shell 控管主机。
大概的流程就是上面写的那个样子啦,而每一个程序的内容主要是在干嘛呢?底下就分别来谈一谈吧!
boot loader 与 kernel 载入
由第一篇里面谈到的一些基础的主机硬件概念当中,我们知道整个主机在开机的时候,第一个被读取的地方,
就是 BIOS ( Basic Input Output System ) 啦,这个 BIOS 里面记录了主板的芯片组与相关的设定,
例如 CPU 与接口设备的沟通频率啊、开机装置的搜寻顺序啊、硬盘的大小与类型啊、
系统时间啊、各周边总线的是否启动 Plug and Play (PnP, 即插即用装置) 啊、
各接口设备的 I/O 地址啊、以及与 CPU 沟通的 IRQ 岔断等等的信息都记录在此,
所以啰,系统要顺利的开机,首先就是要去读取 BIOS 的相关设定值了。
读取了 BIOS 设定值之后,系统会根据 BIOS 的数据,进行开机自我测试 (power on self test, POST),
然后开始执行硬件侦测的初始化,并设定 PnP 装置,之后再定义出可开机的装置,
之后就会开始进行开机装置的数据读取了 (MBR 相关的任务开始)。
读完了 BIOS 并且了解了主要的主机硬件相关信息后,主机便会开始尝试由储存媒体加载操作系统了。
我们刚刚提到 BIOS 会记录『可用来开机的装置搜寻顺序』对吧!所以,系统会开始去第一个开机装置上面进行开机程序。
我们在第二篇的
磁盘文件系统(filesystem) 当中提到过整个储存装置的特性,
如果以硬盘来看,那么开机流程读到硬盘的过程中,第一个要读取的就是该硬盘的主要启动扇区 (Master Boot
Record, MBR) 了,而系统可以由主要开机区所安装的开机管理程序 (boot loader) 开始执行核心辨识的工作。
Tips: 我们知道每颗硬盘的第一个扇区称为 MBR ,那么如果我的主机上面有两颗硬盘的话,
系统会去哪颗硬盘的 MBR 读取数据呢?这个就得要看 BIOS 的设定了。
基本上,我们常常讲的『系统的 MBR』其实指的是 第一个开机装置的 MBR 才对!
所以,改天如果您要将开机管理程序安装到某颗硬盘的 MBR 时,
要特别注意当时系统的『第一个开机装置』是那个,否则会安装到错误的硬盘上面喔!重要重要!
| |
那么为什么要在 MBR 安装 boot loader 呢?而这个 boot loader 有什么功能呢?
还记得我们在第二篇提到的
磁盘文件系统 吧?
我们的操作系统核心必须要认识磁盘文件系统才能读取里面的数据啊,
但是整个系统才刚刚到开机起头的地方而已,要如何认识磁盘文件格式呢?
那就得要藉由 boot loader 来辅助啦!所以啰,当然必须要有 boot loader 才有办法加载 Linux 的核心
(kernel) 啊!由于 boot loader 的特殊功能,因此,想要加载 Linux 核心时,
当然得使用支持 Linux filesystem 的 boot loader 了,目前主流的 grub 这套开机管理程序,
不但可以支持 Linux ,同时也支持 Windows 相关的核心系统呢!
好了,先再来回忆一下,如果你是以 grub 程序开机的话,那么在开机的时候会显示什么数据呢?呵呵!
会显示蛮多的开机选单,没错~就是『选单』,然后选择了你的选择项目之后,
系统就会跑到该扇区去读取该操作系统的核心啰!呵呵!所以一个好的
boot loader 会具有两个功能,就是:
- 选单功能 (menu)
- 指向功能 (pointer)
再来强调一下,因为 Windows 与 Linux 的文件格式不一样?!
为了加载系统核心,所以必须要安装认识我们操作系统的 loader,
而 Linux 的 loader ( lilo
或 grub ) 是可以认识 windows 的核心档案的,但是 Windows 的 loader 却不认识
Linux 的核心档案,因此,作为一个多重引导的设定 loader ,就无法使用 Windows
所提供的 loader 啰!由于需要让系统认识你的 kernel ,因此,就需要 boot
loader 啦!这样想就对啦!
好了,当我们藉由 boot loader 的管理而开始读取核心档案后,接下来, Linux 就会将核心解压缩到主存储器当中,
并且利用核心的功能,开始测试与驱动各个周边装置,包括储存装置、CPU、网络卡、声卡等等。
那么核心档案在哪里啊?一般来说,他会被放置到 /boot 里面,
并且取名为 /boot/vmlinuz 才对!
在加载核心的过程当中,我们必须要知道的是,系统只会『挂载根目录』而已,而且是以只读的方式挂载的。
此外,有时为了让某些功能可以用档案的方式来读取,因此,有的系统在开机的时候,
会制作所谓的虚拟硬盘 (RAM Disk) 来辅助的,那就是 initrd 以及 linuxrc 的功用了。
利用 boot loader 的功能,可以在加载核心的时候,一起加载 initrd 的映象檔 (/boot/initrd-xxxx.img),
Linux 系统会主动的以 initrd (man 4 initrd) 来进行虚拟硬盘的建置,
并且利用 linuxrc (包含在 initrd 的映象档内) 这个程序的功能来进行加载模块的动作。
linuxrc 主要的特性是:
- 必须是 linuxrc 这个档名;
- 必须放置在 initrd 所建立的虚拟磁盘的最顶层目录;
- 必须要可以被核心所执行。
在核心驱动周边硬件的工作完成之后, initrd 所建立的虚拟磁盘就会被移除了!
不过您要注意的是, initrd 并非必要的,是可有可无的,要看您当初建立该核心的时候,
整个编译的角度与过程。一般来说,各大 Linux distributions 在建立核心时,
都会一起建立出这个 initrd 的映象档,辅助开机的顺利进行。
总之,在这个过程当中, boot loader 可以找到 Linux 的核心档案并且将他加载到主存储器当中,
同时可能可以藉由 initrd 建立起虚拟硬盘 (RAM Disk) 辅助开机的进行,
最后,将读自 BIOS 的主机硬件数据交由 Linux 核心来进行侦测并且加载适当的驱动程序 (driver)
,就让整个主机硬件准备系统的要求了。整个流程有点像这样:
图一、BIOS 与 boot loader 及核心加载流程示意图
在核心完整的加载后,您的主机应该就开始正确的运作了,接下来,就是要开始执行系统的第一支程序: init。
第一支程序 init 及配置文件
/etc/inittab 与 runlevel
在核心加载完毕之后,此时系统应该就已经准备妥当,等待程序的执行了。而整个 Linux
系统当中第一支被执行的程序就是『 /sbin/init 』啰~这也是我们在前一章使用 ps aux |more 时,
看到第一行所显示的程序内容 (PID 为 1 的那行啦) ! init 这支程序所做的工作相当的多,
他除了利用配置文件『
/etc/inittab 』来取得开机的等级
( Run level ) 之外,还会经由这个 run level 的设定值来进行不同的开机服务项目的启动。
那么什么是 run level 呢?他有什么功用啊?其实很简单啦, Linux 就是藉由设定 run level
来规定系统使用不同的服务来启动,让 Linux 的使用环境不同。基本上,依据有无网络与有无 X Window
而将 run level 分为六个等级,分别是:
- 0 - halt (系统直接关机)
- 1 - single user mode (单人维护模式,用在系统出问题时的维护)
- 2 - Multi-user, without NFS (类似底下的 runlevel 3,但无 NFS 服务)
- 3 - Full multi-user mode (完整的含有网络功能的纯文本模式)
- 4 - unused (系统保留功能)
- 5 - X11 (与 runlevel 3 类似,但使用 X Window)
- 6 - reboot (重新启动)
由于 run level 0, 4, 6 不是关机、重新启动就是系统保留的,所以:『
您当然不能将预设的 run level 设定为这三个值 』,
否则系统就会不断的自动关机或自动重新启动....
好了,那么我们开机时,到底是如何取得系统的 run level 的?呵呵!当然是 /etc/inittab 所设定的啰!
那么 /etc/inittab 到底有什么信息呢?我们先来看看这个档案的内容好了:
[root@linux ~]# vi /etc/inittab
# 设定系统开机默认的 run level 设定项目:
id:3:initdefault:
# 开始进行 run level 的服务启动前,使用来侦测与初始化系统环境的配置文件:
si::sysinit:/etc/rc.d/rc.sysinit
# 7 个不同 run level 的,需要启动的服务的 scripts 放置路径:
l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6
# 是否允许按下 [ctrl]+[alt]+[del] 就重新启动的设定项目:
ca::ctrlaltdel:/sbin/shutdown -t3 -r now
# 本机端终端机启动的个数:
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
# 在 X Window (run level 5) 环境下的启动 script 设定项目:
x:5:once:/etc/X11/prefdm -nodaemon
|
这个档案的语法是这样的:
[设定项目]:[run level]:[init 的动作行为]:[指令项目]
1. 设定项目:
最多四个字符,代表 init 的主要工作项目,只是一个简单的代表说明。
2. run level:
该项目在哪些 run level 底下进行的意思。如果是 35 则代表 runlevel 3 与
5 都会执行。
3. init 的动作项目:
主要可以进行的动作项目意义有:
initdefault :代表预设的 run level 设定值;
sysinit :代表系统初始化的动作项目;
ctrlaltdel :代表 [ctrl]+[alt]+[del] 三个按键是否可以重新启动的设定;
wait :代表后面接的指令项目必须要执行完毕才能继续后面的动作;
respawn :代表后面接的, init 仍会主动的『重新』启动。
更多的设定项目请参考 man inittab 的说明。
4. 指令项目:
亦即应该可以进行的指令,通常是一些 script 啰。
|
所以我们可以得到这样的结论:
- 如果不想让使用者利用 [crtl]+[alt]+[del] 来重新启动系统,可以将底下这一行批注掉:
ca::ctrlaltdel:/sbin/shutdown -t3 -r now
- 规定开机的预设 run level 是纯文本 (3) 或者是具有图形接口 (X Window, 5) ,可经由
『 id:3:initdefault: 』那个数字来决定!
以鸟哥自己这个档案为例,我是使用纯文本喔!
所以说,你现在会自行修改登入时的预设 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 来设定好我的系统环境的。』够清楚了吧?
所以,我想要知道到底 FC4 开机的过程当中帮我进行了什么动作,
就得要仔细的分析 /etc/rc.d/rc.sysinit 啰。
Tips: 老实说,这个档案的档名在各不同的 distributions 当中都不相同,
例如 SuSE server 9 就使用 /etc/init.d/boot 与 /etc/init.d/rc 来进行的。
所以,你最好还是自行到该档案去察看一下系统的工作喔! ^_^
| |
/etc/rc.d/rc.sysinit 主要的工作大抵有这几项:
- 取得网络环境与主机类型:
首先读取网络配置文件 /etc/sysconfig/network ,取得主机名与默认通讯闸 (gateway) 等网络环境。
- 测试与挂载内存装置 /proc 及 USB 装置 /sys:
除挂载内存装置 /proc 之外,还会主动侦测系统上是否具有 usb 的装置,
若有则会主动加载 usb 的驱动程序,并且尝试挂载 usb 的文件系统。
- 决定是否启动 SELinux :
近期以来,很多 distributions 都加入了美国国家安全局发展的 Security Enhance Linux 套件,
这个 SELinux 可以更加强化 Linux 操作环境的安全性,不过,由于安全挂帅,
对于新手来说,不是很容易上手。因此,我们才会建议大家先不要启动啊。无论如何,
在这个阶段我们可以分析 SELinux 是否要启动。
- 接口设备的侦测与 Plug and Play (PnP) 参数的测试:
根据核心在开机时侦测的结果 (/proc/sys/kernel/modprobe ) 开始进行 ide / scsi /
网络 / 音效 等接口设备的侦测,以及利用以加载的核心模块进行 PnP 装置的参数测试。
- 用户自定义模块的加载
使用者可以在 /etc/sysconfig/modules/*.modules 加入自定义的模块,
则此时会被加载到系统当中喔!
- 加载核心的相关设定:
系统会主动去读取 /etc/sysctl.conf 这个档案的设定值,使核心功能成为我们想要的样子。
- 设定系统时间 (clock):
- 设定终端机 (console) 字形:
- 设定 RAID 与 LVM 等硬盘功能:
- 以 fsck 检验磁盘文件系统:
- 进行磁盘配额 quota 的转换 (非必要):
- 重新以可读取模式挂载系统磁盘:
- 启动 quota 功能:
- 启动系统随机数装置 (产生随机数功能):
- 清除开机过程当中的临时文件:
- 将开机相关信息加载 /var/log/dmesg 档案中。
如此一来,在 /etc/rc.d/rc.sysinit 就已经将基本的系统设定数据都写好了,也将系统的数据设定完整!
而如果你想要知道到底开机的过程中发生了什么事情呢?那么就使用 dmesg 就可以知道啰。
另外,基本上,在这个档案当中所进行的很多工作的预设配置文件,其实都在 /etc/sysconfig 当中呢!
所以,请记得将 /etc/sysconfig 内的档案好好的瞧一瞧喔! ^_^
在这个过程当中,比较值得注意的是自定义模块的加载!在 FC4 当中,如果我们想要加载核心模块的话,
可以将整个模块写入到 /etc/sysconfig/modules/*.modules 当中,在该目录下,
只要记得档名最后是以 .modules 结尾即可。
这个过程是非必要的,因为我们目前的默认模块实在已经很够用了,除非是您的主机硬件实在太新了,
非要自己加载新的模块不可,否则,在经过 /etc/rc.d/rc.sysinit 的处理后,
你的主机系统应该是已经跑得很顺畅了啦!就等着你将系统相关的服务与网络服务启动啰!
启动系统服务与相关启动配置文件
(/etc/rc.d/rc.n & /etc/sysconfig)
加载核心让整个系统准备接受指令来工作,然后再经过 /etc/rc.d/rc.sysinit
的系统模块与相关硬件信息的初始化后,你的 FC4 系统应该已经顺利工作了。
只是,我们还得要启动系统所需要的各项『服务』啊!这样主机才能提供我们相关的网络或者是主机功能嘛!
这个时候,依据我们在 /etc/inittab 里面提到的 run level 设定值,就可以来决定启动的服务项目了。
举例来说,使用 run level 3 当然就不需要启动 X Window 的相关服务啰,您说是吧?
那么各个不同的 run level 服务启动的各个 shell script 放在哪?还记得 /etc/inittab 里面提到的:
l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6
|
上面提到的就是各不同 run level 放置的目录啦!举例来说, run level 3 的启动目录就是放在
/etc/rc.d/rc3.d 目录当中啰~当然啦,不同的 distributions 这个目录可能会有差异,
所以,您还是得要自行到 /etc/inittab 里面瞧一瞧先!那么在这个目录当中有什么咚咚啊?
我们先以鸟哥自己的宿舍的 FC4 主机里头的 run level 3 的启动目录瞧一瞧:
[root@linux ~]# ls -l /etc/rc.d/rc3.d
lrwxrwxrwx 1 root root 13 Jun 29 01:05 K01yum -> ../init.d/yum
lrwxrwxrwx 1 root root 19 Jun 29 01:05 K02haldaemon -> ../init.d/haldaemon
.....中间省略......
lrwxrwxrwx 1 root root 17 Sep 16 14:09 S01sysstat -> ../init.d/sysstat
lrwxrwxrwx 1 root root 17 Jun 29 01:05 S10network -> ../init.d/network
lrwxrwxrwx 1 root root 16 Jun 29 01:05 S12syslog -> ../init.d/syslog
.....中间省略......
lrwxrwxrwx 1 root root 11 Jun 25 08:27 S99local -> ../rc.local
|
在这个目录下的档案很有趣,全部都是以 S 或者是 K 为开头的档案,而且全部都是连结档,
连结到 /etc/rc.d/init.d 里面的 shell script 呢!而在 /etc/rc.d/init.d 这个目录其实与 /etc/init.d
是一样的,因为这两个目录是链接文件啊!要注意的是,在 /etc/rc.d/init.d/ 底下的 shell scripts
都使用 case.....esac 的语法,而且支持的变量 ($1) 主要有 start 及 stop ,
相关的 shell script 请您回到第三篇去复习。所以,一般来说,如果我们想要启动一些系统服务,例如启动 atd ,
需要使用:
/etc/rc.d/init.d/atd start (也可以用 /etc/init.d/atd start)
如果是关闭该服务,就是使用:
/etc/rc.d/init.d/atd stop
了解鸟哥想要表达的东西了吗?是的~如果我想要在 run level 3 的环境下执行某个服务,
当然就得要将该服务写入 /etc/rc.d/rc3.d 里面去,而既然我们的服务已经在 /etc/rc.d/init.d 里面建立好了,
自然可以使用连结的方式连结到 /etc/rc.d/init.d/ 内的相关的 shell script 啦。不过,为了解决
start 或 stop 这个变量,因此就有了 S 与 K 开头的档名了。
另外,各不同的服务其实还是互有关系的,举例来说,如果要启动 WWW 服务,总是得要有网络吧?
所以啰, /etc/rc.d/init.d/network 就会比较先被启动啦!那么您就会知道在 S 或者是 K
后面接的数字是啥意思了吧?嘿嘿,那就是执行的顺序啦!所以说:
- 在 /etc/rc.d/rc3.d 内的,以 S 为开头的档案,为开机时,需要『启动, start』的服务;
- 在该目录内的 K 为开头的档案,为『关机时需要关闭的服务, stop』的档案连结;
- 在 S 与 K 后面接的数字,代表该档案被执行的顺序。
举例来说,在上表当中, S10network 指向 ../init.d/network ,代表:开机时,执行『
/etc/rc.d/init.d/network start 』的意思,而 S12syslog 则代表开机时执行『
/etc/rc.d/init.d/syslog start 』的意思,且 S10network 要比 S12syslog 还要早执行喔!
所以啰,看到最后一个被执行的项目是啥?呵呵!没错,就是 S99local ,亦即是:
/etc/rc.d/rc.local 这个档案啦!
好了,那么问题来了,我要如何建立 /etc/rc.d/init.d 里面的档案呢?
很简单啊,看一下 /etc/rc.d/init.d/atd 的内容就知道了,而更多的 services
启动与相关说明,我们会在后续的
认识系统服务 详谈。
而将 /etc/rc.d/init.d/ 连结到 /etc/rc.d/rc3.d 的方法,除了手动建立外,
其实我们都是以 chkconfig 这个程序来进行管理的呢!更多的 chkconfig 请参考认识系统服务那一章。
用户自定义开机启动程序
(/etc/rc.d/rc.local)
在完成 run level 3 的服务启动后,如果我还有其他的动作想要完成时,举例来说,
我还想要寄一封 mail 给某个系统管理账号,通知他,系统刚刚重新启动完毕,那么,
是否应该要制作一个 shell script 放置在 /etc/rc.d/init.d/ 里面,然后再以连结方式连结到
/etc/rc.d/rc3.d/ 里面呢?呵呵!当然不需要!还记得上一小节提到的 /etc/rc.d/rc.local 吧?
这个档案就可以执行您自己想要执行的系统指令了。像不像早期 DOS 年代的 autoexec.bat 与 config.sys 呢? ^_^
也就是说,我有任何想要在开机时就进行的工作时,直接将他写入 /etc/rc.d/rc.local ,
那么该工作就会在开机的时候自动被加载喔!而不必等我们登入系统去启动呢!
是否很方便啊!一般来说,鸟哥就很喜欢把自己制作的 shell script 完整档名写入
/etc/rc.d/rc.local ,如此一来,开机就会将我的 shell script 执行过,真是好棒那!
根据 /etc/inittab
之设定,加载终端机或 X-Window 接口。
在完成了系统所有服务的启动后,接下来 Linux 就会启动终端机或者是 X Window 来等待使用者登入啦!
实际参考的项目是 /etc/inittab 内的这一段:
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
# Run xdm in runlevel 5
x:5:once:/etc/X11/prefdm -nodaemon
|
这一段代表,在 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 啦!
其他开机相关事项:
关于模块: /etc/modprobe.conf
还记得我们在
/etc/rc.d/rc.sysinit
当中谈到的加载用户自定义模块的地方吗?嘿嘿!就是在 /etc/sysconfig/modules/ 目录下啊!
不过,虽然核心提供的默认模块已经很足够我们使用了,但是,
某些条件下我们还是得对模块进行一些参数的规划,此时,就得要使用到 /etc/modprobe.conf 啰!
举例来说,鸟哥的 FC4 主机的 modprobe.conf 有点像这样:
[root@linux ~]# vi /etc/modprobe.conf
alias eth0 8139too
alias snd-card-0 snd-via82xx
options snd-card-0 index=0
options snd-via82xx index=0
alias usb-controller uhci-hcd
|
意思是说:『
我的 eth0 这个玩意儿,代表的是使用 8139too 这个核心模块,
至于 snd-card-0 则使用 snd-via82xx 那个模块。此外, snd-card-0 这个模块在使用时,
还使用 index=0 这个参数。』这玩意真的是挺常用的~不过,这个档案通常在安装的时候,
安装程序就会主动的建立这个档案啰~除非您对系统提供的驱动程序模块不满意~~
才会主动的修改这个模块加载的相关档案啦~(早期 2.4.xx 核心版本时,使用的是 /etc/modules.conf 喔!)
更多的相关说明,请 man modprobe.conf 喔!
/etc/sysconfig/*
不说您也知道,整个开机的过程当中,老是读取的一些服务的相关配置文件都是记录在 /etc/sysconfig
目录下的!那么该目录底下有些啥玩意儿?我们先来瞧一瞧!
[root@linux ~]# ls -l /etc/sysconfig
-rw-r--r-- 1 root root 194 Jun 25 08:53 authconfig
-rw-r--r-- 1 root root 726 Apr 25 23:54 autofs
-rw-r--r-- 1 root root 39 Jun 25 16:55 clock
drwxr-xr-x 2 root root 4096 May 26 00:52 console
-rw-r--r-- 1 root root 512 Jul 12 06:21 crond
-rw-r--r-- 1 root root 14 Jun 25 08:53 desktop
-rw-r--r-- 1 root root 31 Aug 23 03:13 diskdump
-rw-r--r-- 1 root root 17 Jun 25 16:56 firstboot
-rw-r--r-- 1 root root 25 Jun 25 08:53 grub
-rw-r--r-- 1 root root 1592 Mar 2 2005 harddisks
-rw-r--r-- 1 root root 112 Jun 25 19:53 i18n
-rw-r--r-- 1 root root 991 Nov 2 2004 init
-rw------- 1 root root 1376 Mar 19 2005 iptables-config
-rw-r--r-- 1 root root 180 Jun 25 08:53 kernel
-rw-r--r-- 1 root root 32 Jun 25 08:53 keyboard
-rw-r--r-- 1 root root 168 May 20 03:54 kudzu
drwxr-xr-x 2 root root 4096 May 26 00:52 modules
-rw-r--r-- 1 root root 115 Jun 25 08:53 mouse
-rw-r--r-- 1 root root 43 Jun 25 08:53 network
drwxr-xr-x 4 root root 4096 Jun 25 08:27 networking
drwxr-xr-x 2 root root 4096 Jun 25 21:53 network-scripts
-rw-r--r-- 1 root root 454 May 20 00:07 syslog
-rw-r--r-- 1 root root 66 Mar 7 2005 sysstat
-rw-r--r-- 1 root root 376 Mar 9 2005 xinetd
|
为了节省篇幅,上表当中我已经省略掉某些档案了,仅列出较重要的几个!
需要注意的是:
- authconfig:
这个档案主要在规范使用者的身份认证,包括加密与否、加密的机制等;
- clock:
此档案在设定 Linux 主机的时区,可以使用格林威治时间(GMT)
,也可以使用台湾的本地时间 ( local )。基本上,在 clock 档案内的设定项目『
ZONE 』所参考的时区位于 /usr/share/zoneinfo 目录下的相对路径中。
而且要修改时区的话,还得将 /usr/share/zoneinfo/Asia/Taipei 这个档案复制成为
/etc/localtime 才行!
- desktop:
这个与默认的 X Window 的窗口管理员 (Window Manager) 有关。
在 FC4 里头预设是以 KDE 为主要的 WM,您也可以自行在这个档案内修订喔!
- i18n:
i18n 在设定一些语系的使用方面,例如最麻烦的文字接口下的日期显示问题!
如果您是以中文安装的,那么预设语系会被选择 big5 ,所以在纯文本接口之下,
你的档案日期显示就会呈现乱码!这个时候就需要更改一下这里啦!更动这个 i18n
的档案,将里面的 LC_TIME 改成 en 即可!
- keyboard & mouse:
keyboard 与 mouse 就是在设定键盘与鼠标的形式;
- network:
network 可以设定主机名,以及 GATEWAY 这两个重要信息呢!
- network-scripts/:
至于 network-scripts 里面的档案,则是主要用在设定网络卡~
这部份我们在服务器架设篇才再次提到!
总而言之一句话,这个目录下的档案很重要的啦!开机过程里面常常会读取到的!
Run level 之变换:
在我们完成上面的所有信息后,其实整个 Linux 主机就已经在等待我们使用者的登入啦!
但是,相信您应该还是会有一点疑问的地方,那就是:『
我该如何切换
run level 呢?』会不会很难啊?不会啦!很简单~
但是依据执行的时间而有不同的方式啊!
事实上,
与 run level 有关的启动其实是在 /etc/rc.d/rc.sysinit
执行完毕之后。也就是说,其实 run level 的不同仅是 /etc/rc.d/rc[0-6].d
里面启动的服务不同而已。不过,依据开机是否自动进入不同 run level 的设定,我们可以说:
- 要每次开机都执行某个预设的 run level ,则需要修改 /etc/inittab 内的设定项目,
亦即是『 id:3:initdefault: 』里头的数字啊;
- 如果仅只是暂时变更系统的 run level 时,则使用 init [0-6] 来进行 run level 的变更。
但下次重新启动时,依旧会是以 /etc/inittab 的设定为准。
假设原本我们是以 run level 5 登入系统的,但是因为某些因素,想要切换成为 run level 3 时,
该怎么办呢?很简单啊,利用 init 3 即可切换。但是 init 3 这个动作到底做了什么呢?
我们不是说了吗?事实上,不同的 run level 只是加载的服务不同罢了,
亦即是 /etc/rc.d/rc5.d/ 还有 /etc/rc.d/rc3.d 内的 Sxxname 与 Kxxname 有差异而已。
所以说,当执行 init 3 时,系统会:
- 先比对 /etc/rc.d/rc3.d/ 及 /etc/rc.d/rc5.d 内的 K 与 S 开头的档案;
- 关闭 /etc/rc.d/rc5.d/ 内不存在于 /etc/rc.d/rc3.d/ 中的服务;
- 启动 /etc/rc.d/rc3.d/ 内不存在于 /etc/rc.d/rc5.d/ 中的服务。
也就是说,两个 run level 都存在的服务就不会被关闭啦!如此一来,就很容易切换 run level 了,
而且还不需要重新启动呢!真方便。那我怎么知道目前的 run level 是多少呢?
直接在 bash 当中输入 runlevel 即可啊!
[root@linux ~]# runlevel
N 3
|
够简单的吧! ^_^
谈完了整个开机的流程,您应该会知道,在整个开机的过程当中,是否能够成功的驱动我们主机的硬件配备,
是核心 (kernel) 的工作!而核心一般都是压缩文件,因此在使用核心之前,就得要将他解压缩后,
才能加载主存储器当中。
另外,为了应付日新月异的硬件,目前的核心都是具有『可读取模块化驱动程序』的功能,
亦即是所谓的『 modules (模块化)』的功能啦!所谓的模块化可以将他想成是一个『插件』,
该插件可能由硬件开发厂商提供,也有可能我们的核心本来就支持~不过,较新的硬件,
通常都需要硬件开发商提供驱动程序模块啦!
那么核心与核心模块放在哪?
- 核心: /boot/vmlinuz 或 /boot/vmlinuz-version;
- 核心解压缩所需 RAM Disk: /boot/initrd (/boot/initrd-version);
- 核心模块: /lib/modules/version/kernel 或 /lib/modules/`uname -r`/kernel;
- 核心原始码: /usr/src/linux (要安装才会有!否则预设不安装的!)
如果该核心被顺利的加载系统当中了,那么就会有几个信息纪录下来:
- 核心版本: /proc/version
- 系统核心功能: /proc/sys/kernel
问题来啦,如果我有个新的硬件,偏偏我的操作系统不支持,该怎么办?很简单啊!
- 重新编译核心,并加入最新的硬件驱动程序原始码;
- 将该硬件的驱动程序编译成为模块,在开机时加载该模块
上面第一点还很好理解,反正就是重新编译核心就是了。不过,核心编译很不容易啊!
我们会在后续章节约略介绍核心编译的整个程序。比较有趣的则是将该硬件的驱动程序编译成为模块啦!
关于编译的方法,可以参考后续的
原始码与 tarball 那一章的介绍。
我们这个章节仅是说明一下,如果想要加载一个已经存在的模块时,该如何是好?
核心模块与相依性:
既然要处理核心模块,自然就得要了解了解我们核心提供的模块之间的相关性啦!
基本上,核心的放置处是在 /lib/modules/`uname -r`/kernel 当中,里面主要还分成几个目录:
arch :与硬件平台有关的项目,例如 CPU 的等级等等;
crypto :核心所支持的加密的技术,例如 md5 或者是 des 等等;
drivers :一些硬件的驱动程序,例如显示适配器、网络卡、PCI 相关硬件等等;
fs :核心所支持的 filesystems ,例如 vfat, reiserfs, nfs 等等;
lib :一些函式库;
net :与网络有关的各项协议数据,还有防火墙模块 (net/ipv4/netfilter/*) 等等;
sound :与音效有关的各项模块;
|
如果要我们一个一个的去检查这些模块的主要信息,然后定义出他们的相依性,
我们可能会疯掉吧!所以说,我们的 Linux 当然会提供一些模块相依性的解决方案啰~
对啦!那就是检查
/lib/modules/`uname -r`/modules.dep
这个档案啦!他记录了在核心支持的模块的各项相依性。
那么这个档案如何建立呢?挺简单!利用 depmod 这个指令就可以达到建立该档案的需求了!
[root@linux ~]# depmod [-Ane]
参数:
-A :不加任何参数时, depmod 会主动的去分析目前核心的模块,并且重新写入
/lib/modules/`uname -r`/modules.dep 当中。若加入 -A 参数时,则 depmod
会去搜寻比 modules.dep 还要新的模块,如果真找到新模块,才会更新。
-n :不写入 modules.dep ,而是将结果输出到屏幕上(standard out);
-e :显示出目前已加载的不可执行的模块名称
范例:
范例一:若我已经做好一个网卡驱动程序,假设档名为 a.ko,该如何更新核心相依性?
[root@linux ~]# cp /full/path/a.ko /lib/modules/`uname -r`/kernel/drivers/net
[root@linux ~]# depmod
|
难就难在将那个新的驱动程序模块编译出来,如果编译出来之后,
依据核心模块放置的目录去放置好,然后输入 depmod 后,去更新好 modules.dep ,
如此一来,核心就能够认识该模块啰!够简单吧! ^_^ (关于核心模块的编译,请参考
核心编译 一文!)
核心模块的观察: lsmod, modinfo
那你到底晓不晓得目前核心加载了多少的模块呢?粉简单啦!利用 lsmod 即可!
[root@linux ~]# lsmod
Module Size Used by
loop 18121 0
ipt_state 1857 2
ipt_MASQUERADE 3265 2
iptable_filter 2881 1
ip_nat_irc 2753 0
ip_conntrack_irc 72401 1 ip_nat_irc
ip_nat_ftp 3393 0
ip_conntrack_ftp 73297 1 ip_nat_ftp
....中间省略.....
8139too 30017 0
mii 5441 1 8139too
floppy 65141 0
ext3 132681 4
jbd 86233 1 ext3
|
使用 lsmod 之后,系统会显示出目前已经存在于核心当中的模块,显示的内容包括有:
- 模块名称(Module);
- 模块的大小(size);
- 此模块是否被其他模块所使用 (Used by)。
举例来说,上面的表格当中,我的 ip_conntrack_ftp 模块其实还被 ip_nat_ftp 模块所使用呢!
也就是说,这两个模块之间应该是有相关性的!所以啰,如果我加载 ip_nat_ftp 势必还得要加载
ip_conntrack_ftp 才行~而这个相依性就是被纪录在上个小节提到的 modules.dep 档案内啰! ^_^
那么除了显示出目前的模块外,我还可以查阅每个模块的信息吗?当然可以啦!就用 modinfo 即可:
[root@linux ~]# modinfo [-adln] [module_name|filename]
参数:
-a :仅列出作者名称;
-d :仅列出该 modules 的说明 (description);
-l :仅列出授权 (license);
-n :仅列出该模块的详细路径。
范例:
范例一:由上个表格当中,请列出 8139too 这个模块的相关信息:
[root@linux ~]# modinfo 8139too
filename: /lib/modules/2.6.12-1.1398_FC4/kernel/drivers/net/8139too.ko
author: Jeff Garzik
description: RealTek RTL-8139 Fast Ethernet driver
license: GPL
version: 0.9.27
parmtype: multicast_filter_limit:int
parmtype: media:array of int
parmtype: full_duplex:array of int
parmtype: debug:int
parm: debug:8139too bitmapped message enable number
parm: media:8139too: Bits 4+9: force full duplex, bit 5: 100Mbps
parm: full_duplex:8139too: Force full duplex for board(s) (1)
vermagic: 2.6.12-1.1398_FC4 686 REGPARM 4KSTACKS gcc-4.0
depends: mii
alias: pci:v000010ECd00008139sv*sd*bc*sc*i*
范例二:我有一个模块名称为 a.ko ,请问该模块的信息为?
[root@linux ~]# modinfo a.ko
.......省略......
|
事实上,这个 modinfo 除了可以『查阅在核心内的模块』之外,还可以检查『某个模块档案』,
因此,如果你想要知道某个档案代表的意义为何,利用 modinfo 加上完整檔名吧!
看看就晓得是啥玩意儿啰! ^_^
核心模块的加载与移除:
insmod, modprobe, rmmod
好了,如果我想要自行手动加载模块,又该如何是好?
有很多方法啦,最简单而且建议的,是使用 modprobe 这个指令来加载模块,
这是因为 modprobe 会主动的去搜寻 modules.dep 的内容,先克服了模块的相依性后,
才决定需要加载的模块有哪些,很方便。至于 insmod 则完全由使用者自行加载一个完整文件名的模块,
并不会主动的分析模块相依性啊!
[root@linux ~]# insmod [/full/path/module_name] [parameters]
范例一:请尝试载入 /lib/modules/`uname -r`/kernel/fs/smbfs/smbfs.ko
[root@linux ~]# insmod /lib/modules/`uname -r`/kernel/fs/smbfs/smbfs.ko
[root@linux ~]# lsmod | grep smbfs
smbfs 67897 0
|
对吧!他立刻就将该模块加载啰~这个需要加入完整档名啦!那如何移除这个模块呢?
[root@linux ~]# rmmod [-fw] module_name
参数:
-f :强制将该模块移除掉,不论是否正被使用;
-w :若该模块正被使用,则 rmmod 会等待该模块被使用完毕后,才移除他!
范例:
范例一:将刚刚加载的 smbfs 模块移除!
[root@linux ~]# rmmod smbfs
|
帅吧!移除掉了。不过,如前所述的, insmod 实在不怎么人性化,近年来,
我们都建议直接使用 modprobe 来处理模块加载的问题,这个指令的用法是:
[root@linux ~]# modprobe [-lcf] module_name
参数:
-c :列出目前系统所有的模块!(更详细的代号对应表)
-l :列出目前在 /lib/modules/`uname -r`/kernel 当中的所有模块完整文件名;
-f :强制加载该模块;
-r :类似 rmmod ,就是移除某个模块啰~
范例:
范例一:加载 smbfs 模块
[root@linux ~]# modprobe smbfs
# 很方便吧!不需要知道完整的模块文件名,这是因为该完整文件名已经记录到
# /lib/modules/`uname -r`/modules.dep 当中的缘故啊!如果要移除的话:
[root@linux ~]# modprobe -r smbfs
|
使用 modprobe 真的是要比 insmod 方便很多!因为他是直接去搜寻 modules.dep 的纪录,
所以啰,当然可以克服模块的相依性问题,而且还不需要知道该模块的详细路径呢!
好方便! ^_^
核心模块的额外参数设定:
/etc/modprobe.conf
这个档案我们之前已经谈过了,这里只是再强调一下而已,如果您想要修改某些模块的额外参数设定,
就在这个档案内设定吧!我们假设一个案例好了,假设我的网络卡 eth0 是使用 ne ,
但是 eth1 同样也使用 ne ,为了避免同一个模块会导致网络卡的错乱,
因此,我可以先找到 eth0 与 eth1 的 I/O 与 IRQ ,假设:
- eth0 : I/O (0x300) 且 IRQ=5
- eth1 : I/O (0x320) 且 IRQ=7
则:
[root@linux ~]# vi /etc/modprobe.conf
alias eth0 ne
alias eth1 ne
options eth0 io=0x300 irq=5
options eth1 io=0x320 irq=7
|
嘿嘿!如此一来,我的 Linux 就不会捉错网络卡的对应啰!因为被我强制指定某个 I/O 咯嘛! ^_^
在看完了前面的整个开机流程,以及核心模块的整理之后,你应该会发现到一件事情,
那就是『 boot loader 是载入核心的重要工具』啊!没有 boot loader 的话,那么
kernel 根本就没有办法被系统加载的呢!所以,底下我们会先谈一谈 boot loader 的功能,
然后再讲一讲现阶段 Linux 里头最主流的 grub 这个 boot loader 吧!
boot loader 的功能与意义:
我们在第一小节的地方,曾经讲过,在 BIOS 读完信息后,接下来就是会到第一个开机装置的 MBR
去读取 boot loader 了,这个 boot loader 可以具有选单功能,而且『还能辨识硬盘的 filesystem ,
并且指向核心档案,以将他读入主存储器当中』呢!所以啰,特点是:
我们系统能够使用的 boot loader 必须要能够认识我们系统的 filesystem 才行。
目前台湾常见的有 grub, lilo 以及 spfdisk 这几个 loader 啦!
但是我们都知道, MBR 是整个硬盘的第一个 sector,充其量整个大小不可能超过 512 bytes 的,那么,
我们的 loader 功能这么强,不可能只占不到 512 bytes 的容量吧?
而且某些情况下,配置文件还会占用掉不少的容量呢!怎么办?
为了解决这个问题,我们将 boot loader 分成两个阶段来执行 (stage):
- Stage 1:第一阶段为 boot loader 的主程序,这个主程序必须要被安装在开机区,
亦即是 MBR 或者是 Super block (first sector)。但如前所述,因为 MBR 实在太小了,
所以,这个 stage 1 通常仅安装 boot loader 的最小主程序,
并没有安装 loader 的相关配置文件;
- Stage 2:第二阶段为载入 boot loader 的所有配置文件与相关的环境参数档案。
一般来说,配置文件都在 /boot 底下。
另外,不知道你有没有觉得很奇怪,既然我们可以将 boot loader 安装在 super block (
可以想成是每个 partition 的第一个扇区 "first sector" ,更多相关信息,请参考
磁盘文件系统 那个章节。 ),然后开机时,主要的 loader
又是加载自 MBR ,那么 Super block 的 boot loader 什么时候会被使用到啊?
果然是好问题~如果这个地方搞懂了,你的主机多重引导就可以搞定啰~不过,最难懂得却也是这个地方。
其实针对开机的项目, boot loader 可以做到:
- boot loader 可以直接指定并取用 kernel 档案,来加载到主存储器当中;
- 也可以将 loader 的控制权移交给下一个 loader !
换句话说, boot loader 除了可以直接指定核心档案来开机之外,也可以指定某个 super block
当中的 boot loader 接管开机的核心加载流程啊!我们来假设几个条件好了。
假设我在 MBR 安装了 grub 这个同时认识 Windows 与 Linux 的文件系统的 boot loader ,
同时假设我的 /dev/hda2 当中的 super block 也安装了 Linux 的 grub ,
且 /dev/hda1 的 super block 则是安装 Windows 的 boot loader 。此外,我的 Linux 的核心档案放置在
/dev/hda2 里面的 /boot/vmlinuz ,那么我的 MBR 的 grub 至少可以做到这样:
- 直接指定核心 (在 /dev/hda2 的 /boot/vmlinux ) 来进行开机;
- 将控制权交给 /dev/hda2 super block 当中的 grub 进行管理;
- 将控制权交给 /dev/hda1 super block 当中的 Windows 的 loader 来管理。
这样说,瞭了吗?而值得注意的是,我们的 Linux 可以选择将 boot loader 安装在 MBR 或者是
super block 当中,但是 Windows 系统则几乎默认强制会同时安装在 MBR 与 Super block 当中,
这也是为什么『
我们说要安装多重操作系统时,最好先安装 Windows
再安装 Linux ,因为若先安装 Linux ,则后续安装 Windows 时,会强制将 MBR 的 boot loader
覆盖掉,如此一来,我们将无法以 windows 的 boot loader 进入 Linux 了。』
但如果我真的是忘记了,先安装 Linux 后才安装 Windows 呢?怎么办?
没关系啊!只要你安装类似 spfdisk 的软件在 MBR 里面,因为他同时认识 Linux 与 Windows ,
所以就可以用他来进入 Linux 啦!或者使用类似 KNOPPIX 的 Live CD 以光盘开机进入 Linux 之后,
再以 chroot 软件切换根目录 (/) ,然后重新安装 grub 等 boot loader ,
同样也可以重新让两个操作系统存在啦!总之,
只要你知道 MBR / Super block / boot loader 之间的相关性,怎么切换都可能啊! ^_^
grub 的配置文件
/boot/grub/menu.lst 与安装型态
grub 是较新的 boot loader ,他的优点很多,包括:
- 认识与支持较多的 filesystem ,并且可以使用 grub 的主程序直接在 filesystem 当中搜寻核心;
- 开机的时候,可以『自行编辑与修改开机设定项目』,类似 bash 的指令模式;
- 可以动态搜寻配置文件,而不需要在修改配置文件后重新安装 grub 。亦即是我们只要修改完
/boot/grub/menu.lst 里头的设定后,下次开机就生效了!
上面第三点其实就是 Stage 1, Stage 2 分别安装在 MBR 与 filesystem 当中的原因啦!
好了,接下来,让我们好好了解一下 grub 的配置文件: /boot/grub/menu.lst 这玩意儿吧!
要注意喔,那个 lst 是 LST 的小写,不要搞错啰!
与硬盘的关系:
既然 grub 主程序是安装在 MBR ( super block ) 当中,并且动态去搜寻配置文件的信息,
所以啰,他必须要认识硬盘才行啊!那么 grub 到底是如何认识硬盘的呢?
嘿嘿! grub 对硬盘的代号设定与传统的 Linux 磁盘代号可完全是不同的!
他的代号有点像:
够神了吧?跟 /dev/hda1 风马牛不相干~怎么办啊?其实只要注意几个东西即可,
那就是:
- 硬盘代号以小括号 ( ) 包起来;
- 硬盘以 hd 表示,后面会接一组数字;
- 以『搜寻顺序』做为硬盘的编号,而不是依照硬盘扁平电缆的排序!(这个重要!)
- 第一个搜寻到的硬盘为 0 号,第二个为 1 号,以此类推;
- 每颗硬盘的第一个 partition 代号为 0 ,依序类推。
所以说,第一颗『搜寻到的硬盘』代号为:『(hd0)』,而该颗硬盘的第一号 partition 为
『(hd0,0)』这样说,容易了解了吧!?
在传统的主板上面,
通常第一颗硬盘就会是 /dev/hda,所以常常我们可能会误会 /dev/hda 就是 (hd0) ,
其实不是喔!要看您 BIOS 的设定值才行!
有的主板 BIOS 可以调整开机的硬盘搜寻顺序,那么就要注意了,因为 grub
的硬盘代号可能会跟着改变吶!留意留意!
所以说,整个硬盘代号为:
硬盘搜寻顺序 | 在 Grub 当中的代号 |
第一颗 | (hd0) (hd0,0) (hd0,1) (hd0,4).... |
第二颗 | (hd1) (hd1,0) (hd1,1) (hd1,4).... |
第三颗 | (hd2) (hd2,0) (hd2,1) (hd2,4).... |
这样应该比较好看出来了吧?第一颗硬盘的 MBR 安装处的硬盘代号就是『(hd0)』,
而第一颗硬盘的第一个 partition 的 Super block 代号就是『(hd0,0)』第一颗硬盘的第一个
logical partition 的 super block 代号为『(hd0,4)』瞭了吧!
/boot/grub/menu.lst 配置文件:
了解了 grub 当中最麻烦的硬盘代号后,接下来,我们就可以瞧一瞧配置文件的内容了。
先看一下鸟哥的 FC4 内的 /boot/grub/menu.lst 好了:
[root@linux ~]# vi /boot/grub/menu.lst
default=0
timeout=5
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
hiddenmenu
title Fedora Core (2.6.12-1.1456_FC4)
root (hd0,0)
kernel /boot/vmlinuz-2.6.12-1.1456_FC4 ro root=/dev/hda1 quiet vga=787
initrd /boot/initrd-2.6.12-1.1456_FC4.img
title Fedora Core (2.6.11-1.1369_FC4)
root (hd0,0)
kernel /boot/vmlinuz-2.6.11-1.1369_FC4 ro root=/dev/hda1 quiet vga=787
initrd /boot/initrd-2.6.11-1.1369_FC4.img
|
在 title 以前的前四行,都是属于 grub 的整体设定,包括预设的等待时间与默认的开机项目,
还有显示的画面特性等等的项目。至于 title 后面才是指定开机的核心档案或者是 boot loader 控制权。
在整体设定方面的项目主要常见的有:
- default=0
这个必须要与 title 作为对照。以上表为例,我们不是有两个 title 吗?按照前后顺序来排列,
第一个 title 代表的是 0 ,第二个 title 代表的是 1 ,以此类推~
这个 default 说的是,如果开机过程当中,您并没有选择其他的项目,
那么就会用默认值 (第 1 个 title) 来开机啦!
- timeout=5
这个是开机时,不是会显示选单吗?如果你在几秒内(单位就是秒!)没有按下任何按键,
那就会用 default 那个设定值来进行开机!
- splashimage=(hd0,0)/boot/grub/splash.xpm.gz
这个 splashimage 是在选单上面显示的一些图片或者是相关的影像数据啦!
这个设定有个地方比较有趣!因为在开机的过程当中并没有硬盘,
所以我们必须要明确的指出某个档案在那个 partition 内的那个目录;
因此,上面的设定说的是:在 (hd0,0) 那个 partition 内的 /boot/grub/splash.xpm.gz
该档案为开机时显示的画面啦!更多 splash 可以参考:
http://ruslug.rutgers.edu/~mcgrof/grub-images/
- hiddenmenu
这个说的是,开机时,是否要显示选单?目前 FC4 默认是不要显示选单,
如果您想要显示选单,那就将这个设定值批注掉!
整体设定的地方大概是这样,而底下那个 title 则是显示开机的设定项目。
如同前一小节提到的,开机时,可以选择(1)直接指定核心档案开机或 (2)将 boot loader
控制权转移到下个 loader (此过程称为 chain-loader)。每个 title 后面接的是
『该开机项目名称的显示』,亦即是在选单出现时,选单上面的名称而已。
那么这两种方式的设定有啥不同呢?
1. 直接指定核心开机
既然要指定核心开机,所以当然要找到核心档案啦!此外,有可能还需要用到 initrd 的
RAM Disk 配置文件案 (通常是放置在 /boot 底下啊!)。但是如前说的,
尚未开机完成,所以我们必须要以 grub 的硬盘认识方式找出完整的 kernel 与 initrd 檔名才行。
因此,我们可能需要有底下的方式来设定才行!
1. 先指定核心档案放置的 partition,再读取档案 (目录树),
最后才加入档案的实际文件名与路径 (kernel 与 initrd);
假设仅有一颗硬盘,且仅划分出 /dev/hda1 (亦即根目录为 /dev/hda1)而已:
root (hd0,0) <==代表核心档案放在那个 partition 当中?
kernel /boot/vmlinuz ro root=/dev/hda1 vga=771
initrd /boot/initrd
# root :代表的是『核心档案放置的那个 partition 而不是根目录』喔!不要搞错了!
# kernel :至于 kernel 后面接的则是核心的档名,而在档名后面接的则是核心的参数,
# 在 kernel 后面接的 root 才是『根目录所在的 partition 』,
# 另外,核心还可以外加很多的参数喔,例如 vga 即是一个分辨率参数!
# initrd :就是前面提到的 initrd 制作出 RAM Disk 的档案档名啦!
2. 直接指定 partition 与档名,不需要外接 root !
kernel (hd0,0)/boot/vmlinuz ro root=/dev/hda1 vga=771
initrd (hd0,0)/boot/initrd
|
注意到:
kernel 后面其实只要接 『核心档案档名』与
『根目录 (/) 的所在磁盘代号 (用一般 Linux 磁盘代号) 就可以了。
老实说,以第二个方式来书写你的 title 的内容会比较好一点~
不会造成两个 root 是啥意思的紊乱!上面的案例还很好理解,如果是底下的案例呢?
思考看看:
例题: 我的 Linux 主机仅有一颗硬盘,但为了制作多重引导,所以我将 /boot 独立出来成为一个 partition,
partition 的对应是『 /boot → /dev/hda2 』 『 / → /dev/hda1 』,而且我仅有 kernel file,
档名为 /boot/vmlinuz-2.6.11-1.1369_FC4 请问 grub 当中的 title 要如何写?
答:
|
因为 vmlinuz-2.6.11-1.1369_FC4 这个档案其实是在 /boot 所在的 partition 上,
而 /boot 是 (hd0,1) ,因此,整个档名就成为 (hd0,1)/vmlinuz-2.6.11-1.1369_FC4 了!
只要你能够了解这个档名的来源,那么 grub 对你而言,已经没有什么大问题了! ^_^
2. 利用 chain loader 的方式:
所谓的 chain loader 仅是在将控制权交给下一个 boot loader 而已,
所以 grub 并不需要认识与找出 kernel file ,『
他只是将 boot
的控制权交给下一个 super block 或者是 MBR 内的 boot loader 而已 』
所以通常他也不需要去查验下一个 boot loader 的启动扇区啊!
一般来说, chain loader 的设定只要两个就够了,一个是指定开机区的 root partition,另一个则是设定
chainloader 在那个扇区上!所以说,假设我的 Windows 扇区在 /dev/hda1 ,且我又只有一颗硬盘,
那么要 grub 将控制权交给 windows 的 loader 只要这样就够了:
[root@linux ~]# vi /boot/grub/menu.lst
....前略....
title Windows partition
root (hd0,0)
chainloader +1
|
那个 root 代表的就是 Windows 的 C 槽啦!而 chainloader 则是加载 boot loader 的定义值,
那个 +1 代表的是『第一个 sector 』也可以说成 Super block 啊!这样说,理解吗?!
但其实我们的 grub 功能是很强大的!他还可以隐藏某些 partition 呢!
让您的 Windows 不会去读取 Linux 的 partition 啊!举例来说,以上面的例子在延伸,
假设我的 /dev/hda5 是 Linux 的磁盘系统,我想将他隐藏,并且把原先隐藏的
/dev/hda2 开启,并且不去检查 /dev/hda1 的开机区,所以,会变成:
[root@linux ~]# vi /boot/grub/menu.lst
....前略....
title Windows partition
unhide (hd0,1)
hide (hd0,4)
rootnoverify (hd0,0)
chainloader +1
makeactive
|
最后那个 makeactive 是让开机区的 boot 项目 (记得用 fdisk -l 的显示结果吗? ^_^)
具有 active 的标志而已啦!有没有加都可以!很简单吧!
这样一来,您对于 grub 的硬盘以及 menu.lst 的设定应该有一定程度的认识了吧?好~
接下来,让我们实际的依据您的环境来安装啰~
在下一小节,我们会以鸟哥自己宿舍的计算机来做解释呢! ^_^
initrd 的重要性
我们在本章稍早之前『
boot loader 与 kernel 加载』的地方有稍微讲过这个 initrd 的咚咚,
这玩意儿可以被称为 Initial RAM Disk (初始化虚拟磁盘)。前面也提到过 initrd 可以帮助提供核心模块,
让 Linux 核心在『开机的过程』当中不需要挂载根目录就能够加载所需要的模块,最后得以顺利进入 Linux 系统。
那妳会问啊,啥时后需要 initrd 呢?这就得要从开机的流程谈起了。
我们知道核心解压缩之后会开始侦测并且驱动所有硬件,但是核心档案并没有包含所有的硬件驱动程序,
而是一堆驱动程序以模块的方式存放在 /lib/modules/`uname -r`/kernel/.... 当中。
也就是说,在开机的过程当中我们还需要挂载根目录以方便让核心读取 /lib/modules/.... 内的核心模块,
这样才能够开机完成。简单的流程如下所示:
- 读取 BIOS 设定,取得开机装置与主板芯片等信息;
- 读取 MBR 内的开机加载器 (loader),并透过主机的 INT 13 硬件功能读取核心档案
- 核心解压缩并且侦测硬件
- 挂载根目录,视需要加载 /lib/modules/`uname -r`/... 内的核心模块
- 开始执行 init 这支程序的后续流程等......
在上面的流程当中不知道你有没有发现一个问题,那就是第 3, 4 步骤之间,如果核心本身不认识文件系统格式时,
那如何挂载根目录啊?当然无法挂载对吧!此时就会造成无法开机的问题了!因为连根目录都无法挂载,
如何进入 Linux 系统啊?您说是吧!那么可能会出现这个问题吗?当然可能的!
如果妳的 filesystem 是 LVM, RAID时,或者硬盘是 SCSI 接口时 (包括 SATA 或 USB 接口的磁盘),
那么预设的 Linux 核心档案将无法认识而无法挂载的啦!
果真如上所示,那么妳除了重新编译核心将这些模块直接包在核心档案内之外,还有什么选择?有的,那就是 initrd 啦!
initrd 可以将 /lib/modules/.... 内的『开机过程当中一定需要的模块』包成一个档案 (檔名就是 initrd),
然后在开机时透过主机的 INT 13 硬件功能将该档案读出来解压缩,此时核心就不需要挂载根目录,
因为核心所需要的模块都在 initrd 内了!其实所有的核心模块都在 /lib/modules/ 内,
因此只要能够挂载根目录,其他的模块读取都没有问题的,所以说:『
initrd
内所包含的模块大多是与开机过程有关,而主要以文件系统及硬盘模块 (如 usb, SCSI 等) 为主』的啦!
一般来说,需要 initrd 的时刻为:
- 根目录所在磁盘为 SATA、USB 或 SCSI 等连接接口;
- 根目录所在文件系统为 LVM, RAID 等特殊格式;
- 根目录所在文件系统为非传统 Linux 认识的文件系统时。
之前鸟哥非常容易忽略 initrd 这个档案的重要性,是因为鸟哥很穷... ^_^,因为鸟哥的 Linux 主机都是较早期的硬件,
使用的是 IDE 接口的硬盘,而且并没有使用 LVM 等特殊格式的文件系统,而 Linux 预设核心本身就认识 IDE 接口的磁盘,
因此不需要 initrd 也可以顺利开机完成的。自从 SATA 硬盘流行起来后,没有 initrd 就没办法开机了!
因为 SATA 硬盘使用的是 SCSI 模块来驱动的,而 Linux 默认核心并没有包含 SCSI 模块....
一般来说,各 distribution 提供的核心都会附上 initrd 档案,但如果妳有特殊需要所以想重制 initrd 档案的话,
可以使用 mkinitrd 来处理的。这个档案的处理方式很简单, man mkinitrd 就知道了! ^_^。
我们还是简单的介绍一下去!
[root@linux ~]# mkinitrd [--with=模块名称] initrd文件名 核心版本
参数:
--with=模块名称:模块名称指的是模块的名字而已,不需要填写档名。举例来说,
目前核心版本的 ext3 文件系统模块为底下的文件名:
/lib/modules/`uname -r`/kernel/fs/ext3/ext3.ko
那妳应该要写成: --with=ext3 就好了 (省略 .ko)
initrd檔名:妳所要建立的 initrd 档名,尽量取有意义又好记的名字。
核心版本 :某一个核心的版本,如果是目前的核心则是『 `uname -r` 』
范例一:以 mkinitrd 的默认功能建立一个 initrd 虚拟磁盘档案
[root@linux ~]# mkinitrd initrd_`uname -r` `uname -r`
[root@linux ~]# ll
-rw-r--r-- 1 root root 589106 Jun 27 11:39 initrd_2.6.9-55.EL
# 由于目前的核心版本可使用 uname -r 取得,因此鸟哥使用较简单的指令来处理啰~
# 此时 initrd_2.6.9-55.EL 会被建立起来,妳可以将他移动到 /boot 等待使用。
范例二:使用旧版核心建立含有 8139too 这个模块的 initrd 档案
[root@linux ~]# ll /lib/modules
drwxr-xr-x 3 root root 4096 Feb 28 23:59 2.6.9-42.0.10.EL
drwxr-xr-x 3 root root 4096 Feb 1 05:17 2.6.9-42.0.8.EL
drwxr-xr-x 3 root root 4096 Oct 15 2006 2.6.9-42.EL
drwxr-xr-x 3 root root 4096 May 20 16:53 2.6.9-55.EL
# 这个指令可以看出有多少核心版本,鸟哥想要用 2.6.9-42.EL 来玩的!
[root@linux ~]# mkinitrd --with=8139too initrd_2.6.9-44.EL 2.6.9-42.EL
[root@linux ~]# ll
-rw-r--r-- 1 root root 603934 Jun 27 11:45 initrd_2.6.9-44.EL
# 如果与范例一比较,有没有发现这个档案比较大一点,因为多含了一个模块之故。
|
initrd 建立完成之后,同时核心也处理完毕后,我们就可以使用 grub 来建立选单了!
底下继续瞧一瞧吧!
测试与安装 grub
如果你的 Linux 主机本来就是 grub 的话,那么你就不需要重新安装 grub 了,
因为 grub 本来就会主动去读取配置文件啊!您说是吧!但如果你的 Linux 原来使用的并非 grub ,
那么就需要来安装啦!如何安装呢?首先,你必须要使用 grub-install 将一些必要的档案复制到
/boot/grub 里面去,你应该这样做的:
[root@linux ~]# grub-install [--root-directory=DIR] INSTALL_DEVICE
参数:
--root-directory=DIR 那个 DIR 为实际的目录,使用 grub-install 默认会将
grub 所有的档案都复制到 /boot/grub/* 当中,但如果
想要复制到其他目录与装置去,就得要用这个参数。
INSTALL_DEVICE 安装的装置代号啦!
范例一:将 grub 安装在目前系统的 / 底下,我的系统为 /dev/hda:
[root@linux ~]# grub-install /dev/hda
Installation finished. No error reported.
This is the contents of the device map /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'.
# this device map was generated by anaconda
(fd0) /dev/fd0
(hd0) /dev/hda
# 如果去查阅一下 /boot/grub 的内容,会发现所有的档案都更新了,
# 没错啊!因为我们重新安装了嘛!
范例二:我的 /dev/hdb 挂载到 /disk2 下,如何安装 grub 到 /dev/hdb ?
[root@linux ~]# grub-install --root-directory=/disk2 /dev/hdb
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 /disk2/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/hda
(hd1) /dev/hdb
[root@linux ~]# ll /disk2/boot/grub/
-rw-r--r-- 1 root root 45 Sep 27 22:10 device.map
-rw-r--r-- 1 root root 7476 Sep 27 22:10 e2fs_stage1_5
-rw-r--r-- 1 root root 7300 Sep 27 22:10 fat_stage1_5
-rw-r--r-- 1 root root 6612 Sep 27 22:10 ffs_stage1_5
-rw-r--r-- 1 root root 6612 Sep 27 22:10 iso9660_stage1_5
-rw-r--r-- 1 root root 8096 Sep 27 22:10 jfs_stage1_5
-rw-r--r-- 1 root root 6772 Sep 27 22:10 minix_stage1_5
-rw-r--r-- 1 root root 8980 Sep 27 22:10 reiserfs_stage1_5
-rw-r--r-- 1 root root 512 Sep 27 22:10 stage1
-rw-r--r-- 1 root root 101704 Sep 27 22:10 stage2
-rw-r--r-- 1 root root 6952 Sep 27 22:10 ufs2_stage1_5
-rw-r--r-- 1 root root 6228 Sep 27 22:10 vstafs_stage1_5
-rw-r--r-- 1 root root 8764 Sep 27 22:10 xfs_stage1_5
# 看!档案都安装进来了!但是注意到,我们并没有配置文件喔!那要自己建立!
|
所以说, grub-install 是安装 grub 到你的装置上面,但是,还需要设定好配置文件 (menu.lst) 后,
再以 grub shell 来安装 grub 到 MBR 或者是 Super block 里面去喔!好了,那我们来思考一下想要安装的数据。
鸟哥的 Linux 主机上面,其实仅有一个 Linux 系统,但我的 FC4 已经升级过很多次,所以我的 Linux
有『很多核心』,我想让每个核心都能够使用来开机,而且,还想要将 grub 同时安装在 MBR 与 Super block 当中,
并且 MBR 的 grub 可以将 loader 的控制权转交给 super block ,那么该如何安装呢?
基于这样的想法,我的配置文件应该是这样的:
[root@linux ~]# vi /boot/grub/menu.lst
default=0
timeout=5
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
hiddenmenu
title Fedora Core (2.6.12-1.1456_FC4)
root (hd0,0)
kernel /boot/vmlinuz-2.6.12-1.1456_FC4 ro root=LABEL=/ vga=787
initrd /boot/initrd-2.6.12-1.1456_FC4.img
title Fedora Core (2.6.11-1.1369_FC4)
root (hd0,0)
kernel /boot/vmlinuz-2.6.11-1.1369_FC4 ro root=LABEL=/ vga=787
initrd /boot/initrd-2.6.11-1.1369_FC4.img
title Fedora Super block loader
root (hd0,0)
chainloader +1
|
然后再开始以 grub shell 来进行安装!整个安装与 grub shell 的动作其实很简单,
如果您有兴趣研究的话,可以使用 info grub 去查阅~鸟哥这里仅介绍几个有用的指令而已。
- 用『 root (hdx,x) 』选择含有 /boot 目录的那个 partition 代号;
- 用『 find /boot/grub/stage1 』看看能否找到安装信息档案;
- 用『 find /boot/vmlinuz 』看看能否找到 kernel file (不一定要成功!);
- 用『 setup (hdx,x) 』或『 setup (hdx) 』将 grub 安装在 super block 或 MBR;
- 用『 quit 』来离开 grub shell !
所以,请用 grub 来进入 grub shell 吧!进入 grub 后,会出现一个『 grub> 』的提示字符啊!
[root@linux ~]# grub
1. 先设定一下含有 /boot 目录的那个 partition 啊!
grub> root (hd0,0)
Filesystem type is ext2fs, partition type 0x83
# 瞧!找到啦!有这个 partition 的存在,且 grub 认识他为 ext2 的 filesystem。
2. 搜寻一下,是否存在 stage1 这个信息档案?
grub> find /boot/grub/stage1
(hd0,0)
(hd1,0)
# 呵呵!竟然找到两个?因为刚刚我们也安装一个在 /dev/hdb1 嘛!
3. 搜寻一下是否可以找到核心? /boot/vmlinuz ?
grub> find /boot/vmlinuz
Error 15: File not found
grub> find /boot/vmlinuz-2.6.12-1.1456_FC4
(hd0,0)
# 没办法,FC4 没有连结档,所以需要填写完整的 kernel 文件名!
4. 给他安装上去吧!安装到 MBR 看看!
grub> setup (hd0)
Checking if "/boot/grub/stage1" exists... yes
Checking if "/boot/grub/stage2" exists... yes
Checking if "/boot/grub/e2fs_stage1_5" exists... yes
Running "embed /boot/grub/e2fs_stage1_5 (hd0)"... 15 sectors are embedded.
succeeded
Running "install /boot/grub/stage1 (hd0) (hd0)1+15 p (hd0,0)/boot/grub/stage2
/boot/grub/grub.conf"... succeeded
Done.
# 很好!确实有装起来~这样 grub 就在 MBR 当中了!
5. 那么重复安装到我的 /dev/hda1 呢?亦即是 super block 当中?
grub> setup (hd0,0)
Checking if "/boot/grub/stage1" exists... yes
Checking if "/boot/grub/stage2" exists... yes
Checking if "/boot/grub/e2fs_stage1_5" exists... yes
Running "embed /boot/grub/e2fs_stage1_5 (hd0,0)"... failed (this is not fatal)
Running "embed /boot/grub/e2fs_stage1_5 (hd0,0)"... failed (this is not fatal)
Running "install /boot/grub/stage1 (hd0,0) /boot/grub/stage2 p
/boot/grub/grub.conf "... succeeded
Done.
# 虽然无法将 stage1_5 安装到 super block 去,不过,还不会有问题,
# 重点是最后面那个 stage1 要安装后,显示 succeeded 字样就可以了!
grub> quit
|
如此一来,就已经将 grub 安装到 MBR 及 super block 里面去了!
而且读取的是 (hd0,0) 里面的 /boot/grub/menu.lst 那个档案喔!
真是很重要啊!重要到不行!
开机前的额外功能修改
事实上,上一个小节设定好之后,您的 grub 就已经在你的 Linux 系统上面了,而且同时存在于
MBR 与 Super block 当中呢!所以,我们已经可以进行重新启动来查阅查阅看看啦!
另外,如果你正在进行开机,那么请注意,我们可以在预设选单 (鸟哥的范例当中是 5 秒) 按下任意键,
还可以进行 grub 的「在线编修」 功能喔!真是棒啊!先来看看开机画面吧!
图二、 grub 的开机图示
帅吧!鸟哥的主机上面竟然有七个可开机的选单呢!当然啦!要看到这样的选单,你必须要在开机的过程中,
五秒内就得要按下任意键,否则就会进入到正常的开机程序当中了。
这个时候,注意看到上图当中的最底下的一些文字说明,其实,我们可以进行在线编修喔!
在图二当中,如果我在第一个开机选单当中按下『 e 』这个按键,就会进入 grub shell 的修改,
有点像底下这样:
图三、 grub 的编修画面
这个时候,我可以使用上下键移动光标到想要修改的那一行,然后注意看到图三画面最底下的一些说明文字,
可以使用:
- e:进入 grub shell 的编辑画面;
- o:在游标所在行底下再新增一行;
- d:将游标所在行删除。
我们说过, grub 是可以直接使用核心档案来开机的,所以,如果您很清楚的知道你的根目录 (/)
在那个 partition ,而且知道你的核心档案档名 (通常都会有个 /boot/vmlinuz 连结到正确的档名),
那么直接在图三的画面当中,以上述的 o, d, e 三个按键来编修,成为类似底下这样:
grub edit> kernel (hd0,0)/boot/vmlinuz root=/dev/hda1
|
按下 [Enter] 按键后,然后输入 b 来 boot ,就可以开机啦!所以说,
万一你的 /boot/grub/menu.lst 设定错误,或者是因为安装的缘故,
或者是因为核心档案的缘故,导致无法顺利开机时,记得啊,可以在 grub 的选单部分,
使用 grub shell 的方式去查询 (find) 或者是直接指定核心档案,就能够开机啦! ^_^
另外,我们刚刚图二画面当中的最后一个选项不是指定到 Super block 吗?
如果你选择那个项目开机会怎样?哈哈!立刻又进入 grub 的画面当中!
因为此时 grub 是 super block 当中的,而不是 MBR 当中的!
如此一来,您就应该会了解到 loader 控制权的转移了吧?也能够知道如何制作多重引导了吧?
呼呼!加油的啦!
另外,很多时候我们的 grub 可能会发生错误,导致『连 grub 都无法启动』,那么根本就无法使用
grub 的在线编修功能嘛!怎么办?没关系啊!我们可以利用具有 grub 开机的 CD 来开机,
然后再以 CD 的 grub 的在线编修,嘿嘿!同样可以使用硬盘上面的核心档案来开机啦!
很好玩吧! ^_^
关于核心功能当中的 vga 设定:
或许刚刚我们在前几个小节提到 menu.lst 内的 kernel 设定当中,你就看到这样的一行:『
kernel /boot/vmlinuz ro root=/dev/hda1 vga=771 』怪怪~那个 771 是啥玩意儿?
没有他可不可以啊?当然可以啊!只是这个 vga 的设定项目主要功能用来:『
设定终端机 tty1~tty6 的分辨率与色彩度 』啦!
他的十进制代码与相对应的分辨率与彩度为:
彩度\分辨率 | 640x480 | 800x600 | 1024x768 | 1280x1024 | bit |
256 | 769 | 771 | 773 | 775 | 8 bit |
32768 | 784 | 787 | 790 | 793 | 15 bit |
65536 | 785 | 788 | 791 | 794 | 16 bit |
16.8M | 786 | 789 | 792 | 795 | 32 bit |
不过,某些操作系统支持的是 16 进位制,所以还需要修改一下格式呢!一般使用上表当中的值应该就可以了。
鸟哥我的屏幕是 17 吋的,所以我是将终端机分辨率调整成 800x600 ,使用 vga=787 就绰绰有余啰~^_^
不过,由于不同的操作系统与硬件可能会有不一样的情况,因此,
上面的值不见得一定可以在您的机器上面测试成功,
建议您可以分别设定看看哩~以找出可以使用的值! ^_^
关于大硬盘的问题
虽然我们前面讲过 grub 已经克服了核心放置在 1024 磁柱以后的问题,
不过,如果主板还是不支持大硬盘装置,那么,嘿嘿嘿嘿!
可能还是会无法启动 Linux 喔!他会一直告诉你,有 error 18 产生~
实际的代号可以到底下查询:
解决的方法则如同底下两篇讲的:
由于 Linux 核心只要能够被加载到内存当中,那么他就可以自行侦测硬件,
而不以 BIOS 侦测的硬件结果来执行 Linux 的。所以啰,只要能够加载 Linux kernel ,那就万事 OK 了~
所以,虽然你的主板不认识大于 120GB 以上的硬盘,但是 Linux 依旧可以使用他。
可惜的是,这个大前提是『 Linux kernel 可以被加载到系统当中』才行~
但是, BIOS 都读不到核心档案了,该如何载入啊!因此,如果你的 / 切的太大,
偏偏又没有制作 /boot 的 partition ,同时主板又不支持大硬盘,哈哈哈哈!
那么首次安装完成之后,就会直接跑到 grub> 的画面当中,
是没有办法进入 Linux 的啦!
在这样的情况下,你可以有一个最简单的做法,就是,直接重灌,
并且制作出 /boot 挂载的 partition ,同时确认该 partition 是在 1024 cylinder 之前才行。
如果实在不想重灌,没有关系,利用我们刚刚上头提到的 grub 功能,
额外建立一个可开机软盘,或者是直接以光驱开机,然后以 grub
的编写能力进入 Linux 。
当然,最好的办法其实是骗过 BIOS ,直接将硬盘的 cylinder, head, sector 等等信息直接写到
BIOS 当中去,如此一来,嘿嘿嘿嘿!你的 BIOS 可能就可以读得到与支持的到你的大硬盘了。
不过,鸟哥还是建议您可以重新安装,并且制作出 /boot 这个 partition 啦! ^_^
说实在的,整个开机以 grub 来作为 boot loader 就很棒了~没有什么需要玩 LILO 的啦!
不过, grub 还是有点小缺点的,那就是,当你的 partition 变了,或者是 Windows 存在,
但 Linux 死掉时,因为在 Linux 的配置文件 (/boot/grub/menu.lst) 挂点,
将会导致无法启动 Windows 的困境,除非您很清楚的知道如何使用 grub shell ,否则,
还真糗~
在这个部分, LILO 则使用与 grub 不同的机制,他将 boot loader 的 stage1 与 stage2 通通写入 MBR 或者是
super block 开机区当中,所以,配置文件当然就不需要一定要存在于 Linux 的 filesystem 上啰!您说对吧! ^_^。
但还是各有利弊得失啦~没有说那个比较好就是了。但也因为如此,所以:
当 LILO 配置文件被改过后,一定需要重新安装 LILO 一次。 这一点与 grub 是完全不同的呢。
其实,LILO (LInux LOader) 看名称就知道是 Linux 最早的 boot loader ,
他主要利用 /etc/lilo.conf 这个配置文件,然后再以 lilo 主程序将该设定内容写入开机区当中。
接下来我们就来玩一玩 LILO ,不过需要留意的是, FC4 似乎没有提供 Lilo 给我们呢!
所以使用 FC4 的朋友应该就没有办法玩这个咚咚了~不过没关系吧~知道 boot loader 即可啊! ^_^
LILO 的配置文件 /etc/lilo.conf:
LILO 的配置文件 /etc/lilo.conf 同样的分为两部分,分别是 LILO 整体环境设定部分,
与每个开机项目核心文件名规范部分。有点像这样啦:
[root@linux ~]# vi /etc/lilo.conf
# 第一部份,整体的设定部分
prompt <==强制出现 boot 的开机讯息啰!
Compact <==可以整合一些读取的扇区,可以保持 map 较小,适合软盘开机时使用
timeout=50 <==如果有多重引导的话,可以设定这个延迟时间,单位0.1秒
default=linux-2.4.18 <==默认的开机项目,与底下的 label 对应!
boot=/dev/hda <==Lilo 的开机信息写入到 /dev/hda 这颗硬盘的 MBR 当中。
map=/boot/map <==用来说明 local 主机的地图信息啰!
install=/boot/boot.b <==关于开机区的讯息(boot sector),不用理他没关系!
Linear <==在较大容量的硬盘使用时,可以加入这一个参数试试看!
lba32 <==这个东西也是在大容量的硬盘使用时候会需要的参数!
password=1234567 <==设定密码!如果为了安全起见,可以设定您的 lilo 密码哩!
message=/boot/message <==那个 LILO 的讯息就是在里面出现的啦!
# 第二部分,个别的开机设定部分,一个 image 或 other 均代表一个开机设定!
image=/boot/vmlinuz-2.4.7-10 <==核心档案啦!
label=linux-2.4.7 <==请注意!label 前面以 [tab] 按键来作为分隔!
initrd=/boot/initrd-2.4.7-10.img
read-only <==启动扇区挂载为只读!
root=/dev/hda1 <==挂载成 / 这个 root 目录的磁盘!
other=/dev/hdb1 <==如果是『非 Linux 核心』就以 other 来设定
label=Windows2k <==同样的要有 label 来表示这个启动扇区的名称!
|
注意上面的几个项目,在整体环境设定项目当中,要注意:
- timeout=50
timeout 的设定是 0.1 秒,所以 delay=50 表示延迟时间为 5 秒!
- linear 与 lba32
linear 与 lba32 通常用在 SCSI 或者是较大的硬盘,例如磁柱(cylinder)总数超过 1024
磁柱的硬盘,可以使用这个项目来除错!不过,如果是小于 8GB 的硬盘,
这两个东西有没有设定就没有什么影响了!早期的硬盘容量不大,所以 cylinder 不会超过
1024 ,但较新的硬盘容量太大了,如果核心档案 (/boot/vmlinuz) 放置在 1024
磁柱以后,则可能会发生无法读取的问题,因此需要设定这个 lba32 啊!
这也是为何很多 distribution 预设都会将 /boot 独立出来的缘故!
- default
default 需要设定成底下几个 image 或者是 other 的 label 才成!
这个地方最常被忘记!因为常常会记得修改 label ,但是忘记跟着改变 default
的内容!此外,如果你想要修正开机默认的操作系统选项,在这里改啦!
- password
password 的用途在于安全防护方面,不过有个困扰,就是『
如果你的计算机因为不正常关机 (如断电后重开)
而在电源恢复的时候重新启动时,则会卡在这个阶段无法直接进入 Linux 系统』,
因为你必须提供 password 才能继续的工作呀!
- boot
boot 显示的是开机的扇区选择! 这里也蛮重要的,如果你想要安装在 MBR
里面的话,如同上面的书写模式,就是写入 /dev/hda ,后面不要加上每个 partition
的代码!但是,如果你是想写入 Super Block ,例如我想要写入的是 hda5 这个 Logical
的 partition 时,那么这里就必需要改写为 /dev/hda5 啰!所以,您应该只要一看到这个
boot 后面接的内容,就会知道那个安装的扇区是 MBR 还是 Super Block 啰!
至于每个开机选单项目的内容,主要分为:
- image=kernel_file
image 后面就是接核心档案的档名就是了!这主要是针对 Linux 来作的设定啦!
在 image 底下还有很多的设定项目,每个项目都以 <tab> 按键来缩排,主要的项目有:
- label:项目名称!出现选单时可以选择的项目;
- initrd:后面就是接 RAM Disk 的 initrd 档案档名啊!
- root:这个重要!就是根目录 (/) 的装置代号啊!
- append:核心额外的功能增加的地方!与 grub 的 kernel
后面接的参数意思很相近!
- other=device
其实这个就是 chain loader 啦!移交 boot loader 控制权的设定项目。
在 other 后面接的就是磁盘的装置代号,不论是 MBR 或 super block
都可以啊!里面只要有 label 即可啊!
大致就是这样啊~如果还有什么疑问,详情请参考 man lilo.conf 即可呦!
测试与安装 LILO 开机管理程序:
好啦!为了测试一下您是否已经知道了 lilo.conf 的设定方式,所以我们来做个实验吧!
请在您的『实验主机』上面,不要在提供服务的主机上面完呦!否则死掉了不要怪我没警告您…
我们先试图安装在 super block 上面好了!以下面为例,特殊字体的部分是经过我的修改之后的结果,
您的 /etc/lilo.conf 应该会长的跟我的差不多才是!
[root@linux ~]# vi /etc/lilo.conf
boot=/dev/hda1
map=/boot/map
vga=normal
default=linux
keytable=/boot/us.klt
prompt
nowarn
timeout=100
message=/boot/message
menu-scheme=wb:bw:wb:bw
image=/boot/vmlinuz
label=linux
root=/dev/hda1
initrd=/boot/initrd.img
append="devfs=mount"
read-only
image=/boot/vmlinuz
label=failsafe
root=/dev/hda1
initrd=/boot/initrd.img
append="devfs=nomount failsafe"
read-only
image=/boot/vmlinuz <==就给他新增加一个 label ,但是内容不变!
label=linux-test
root=/dev/hda1
initrd=/boot/initrd.img
append="devfs=mount"
read-only
|
这样就设定好了!接着下来看一下怎么安装他吧!安装真是简单到不行~直接输入 lilo 即可!
[root@linux ~]# lilo
Added linux * <==有打星号的是『预设的开机配置文件!』
Added failsafe
Added linux-test
|
看到没有!要像上面这样才是安装成功呦!如果出现了错误的讯息,那么肯定是有地方没有安装好!
这个时候请特别的再重新设定一次 /etc/lilo.conf 呢!有打星号的是『预设的开机配置文件!』
而如果您还要看看更多的讯息,那么就需要这样:
[root@linux ~]# lilo -v
LILO version 22.3.2, Copyright (C) 1992-1998 Werner Almesberger
Development beyond version 21 Copyright (C) 1999-2002 John Coffman
Released 11-Jul-2002 and compiled at 21:48:42 on Aug 13 2002.
Reading boot sector from /dev/hda1
Using MENU secondary loader
Calling map_insert_data
Mapping message file /boot/message -> message-text
Calling map_insert_file
Boot image: /boot/vmlinuz -> vmlinuz-2.4.19-16mdk
Mapping RAM disk /boot/initrd.img -> initrd-2.4.19-16mdk.img
Added linux *
Boot image: /boot/vmlinuz -> vmlinuz-2.4.19-16mdk
Mapping RAM disk /boot/initrd.img -> initrd-2.4.19-16mdk.img
Added failsafe
Boot image: /boot/vmlinuz -> vmlinuz-2.4.19-16mdk
Mapping RAM disk /boot/initrd.img -> initrd-2.4.19-16mdk.img
Added linux-test
/boot/boot.0301 exists - no backup copy made.
Writing boot sector.
|
如果你需要更多的讯息,那么就使用『 lilo -v -v -v 』多几个 -v 就对了! ^_^
一些问题的解决之道:
好了! lilo 安装完成之后,总是会有一些问题会发生吧!那么如何来解决问题呢?嗯!
可以看一下底下的一些解决之道:
- 我要如何选择不同的开机配置文件?开机的时候我只看的到 boot: 而已?
开机之后,如果是以 lilo 来启动 kernel 时,那么他会出现 boot: 的字样,出现这个字样之后,
马上按下 <tab> 按键,那么就会出现目前 lilo 所记忆的开机配置文件啰!然后在 boot
后面输入想要的启动文件,就可以啰!
- 安装好了 Linux 之后,在开机的过程中却只出现『 LI
』就停止了!该如何是好?
这个问题可能发生的原因是 Lilo 没有设定好,或者是由于 Linux 安装在非
/dev/hda ( MBR )的硬盘之中,解决的方法可以如下:
- 用 Linux 光盘开机,然后在出现 boot: 处输入『
linux root=/dev/hda1
(这个与你的 Linux 安装的 partition 有关)』
顺利开机之后,以 vi 修改 /etc/lilo.conf 将『linear』
这一行取消(如果没有这一行的话,那就在 lilo.conf 中加入吧!)然后执行
『lilo』重新安装 Lilo,
再取出光盘并重新启动试试看;
- 进入 BIOS ,将硬盘的 mode 改成 LBA 试看看;
- 将Linux往前面一点的扇区安装,例如你可能安装在 /etc/hdc1 ,那你可以重新安装
Linux 在 /dev/hda2 试看看
- 安装Linux完成之后,却是出现 010101... 等数字在屏幕上,无法进入
Linux ...
这个问题的发生很有可能是硬盘出了问题了!这个时候可以使用 fsck 来扫瞄啰!
- 用软盘或者是光盘开机后,使用fsck这个硬盘修正软件扫瞄一下您的 root partition
,例如:fsck /dev/hda1
- 进入 BIOS ,将硬盘的 mode 改成 LBA 试看看;
- 我们知道 DOS 需要在第一颗硬盘的第一个扇区才能正常开机使用!
那要是他并非在第一个扇区呢?例如当 DOS 系统在 /dev/hdb1 (第一条扁平电缆的 slave )?
解决知道就是以 lilo 修正磁盘的配置啦!如下所示来修改 /etc/lilo.conf
other=/dev/hdb1
label=DOS
map_drive=0x80
to=0x81
map_drive=0x81
to=0x80
然后再执行 lilo 写入 MBR 当中!
- 我不要玩 Linux 了,如何移除 lilo ?
只要以 Windows 的开机片开机,然后以 Windows 系统的 fdisk 下达:
『fdisk /mbr』
就可以将 Lilo 自 MBR 当中移除啰!
- 无法正常的进入 Lilo 怎么办?
这的时候开机片就很重要啦!使用开机片,在出现 boot: 的时候,输入
『linux -s』
就可以进入啦!这里请特别留意!那个 linux 指的是 label 呢!就像刚刚我们有三个
label ,分别是 linux, linux-test 与 failsafe ,那么如果我要以 linux-test
这个开机配置文件的单人维护模式登入,就必需要改写成
linux-test -s
linux-test single
请特别留意!!
很多时候,我们可能因为做了某些设定,或者是因为不正常关机 (例如未经通知的停电等等) 而导致系统的
filesystem 错乱,此时,Linux 可能无法顺利开机成功,那怎么办呢?难道要重灌?当然不需要啦!
进入 run level 1 (单人维护模式) 去处理处理,应该就 OK 的啦!底下我们就来谈一谈如何处理几个常见的问题!
忘记 root 密码的解决之道:
大家都知道鸟哥的记忆力不佳,容易忘东忘西的,那如果连 root 的密码都忘记了,怎么办?
其实在 FC4 上面,root 密码忘记的情况下,应该是不难解决啦!只要能够进入并且挂载 / ,
然后修改一下 /etc/shadow 内的 root 密码栏 (第二栏啊,参考
账号管理)
重新启动后, root 就不需要密码即可登入啊!因为在 FC4 上面进入 run level 1 是不需要密码的。
整个动作有点像这样:
- 在开机的时候,到达选单时,我们以较常见的 grub 作为介绍。出现选单后,
将光棒移动到要开机的那个项目上面,然后按下『 e 』进入细项设定,选择『 kernel 』那一项,
再按『 e 』进入编修画面,在最后面加上一个单一的『 1 』(数字 1, 2, 3 的 1 啊!),
按下 [Esc] 按键,然后按下『 b 』,就能够以该 kernel 进入 run level 1 了。
- 进入 Linux 后,不需要输入密码,直接就会是 root 的身份,立刻 vi /etc/shadow ,
将 root 所在那一行的第二个字段给他全部抹除,储存后离开,然后『 reboot 』重新启动。
- 由于 root 没有密码了,最好在重新启动前就将网络线拔掉,然后以 root 登入,然后立即设定 root
新密码,这样 root 的密码就算是救回来了。
那如果你的 Linux distribution 算是比较严谨的,所以登入 run level 1 时,还是得要输入 root 密码,
怎么办?很简单啊!可以:
- 使用 Live CD ,例如 KNOPPIX (可以在台南县网中心,小三老师发起的,阿里巴巴兄负责维护的这个网站:
http://knoppix.tnc.edu.tw/ 下载),
将 KNOPPIX 的映象档下载,然后刻录成为光盘,并以此片光盘开机,
就能够进入 Linux 系统啦!之后,再挂载 / ,然后按照上面的密码修改一下,
嘿嘿!成功!
- 在开机的选单上,将原本 kernel 项目最后方加上『 init=/bin/bash 』修改一下登入的 shell ,
不使用 init ,就能够不使用 init ,而直接丢一个 shell 给使用者。不过,
除非很严重的错误,否则不要用这个方法!
因设定错误而无法开机:
如果因为设定错误导致无法开机时,要怎么办啊?这就更简单了!
最容易出错的设定而导致无法顺利开机的步骤,通常就是 /etc/fstab 这个档案了,
尤其是使用者在
实作 Quota 时,最容易写错参数,
又没有经过 mount -a 来测试挂载,就立刻直接重新启动,真要命,无法开机成功怎么办?
不要紧啦!利用上个小节提到的以 run level 1 的方法进入 Linux 系统,然后:
- 利用『 mount -n -o remount,rw / 』重新挂载根目录,
之后将刚刚设定错误的地方修改一下,就可以重新启动啦!
但万一是因为不正常关机,导致开机时进行 fsck 无法成功,而出现类似这样的几行字:
/home contains a file system with errors,check blocks.
/home:Group 81's inode table at 2654219 conflicts with some other fs blocks.
/home: UNEXPECTED INCONSISTENCY ; RUN fsck MANUSLLY
(i.e. , without –a or –p options)
*** An error occurred during the file system check.
*** Dropping you to a shrll ; the system will reboot
*** when you to leave shell....
Give root password for maintenance(or type Control-D for normal startup):
|
这表示你的 filesystem 可能有扇区错乱的情况,一般来说,这样的扇区错乱应该不是实体硬盘错误,
比较可能是由于不正成关机造成 filesystem 的不一致 (Inconsistent) 所造成的。
造成这个问题之后,我们必须要输入 root 的密码,进入 run level 1 ,
然后以 fsck /dev/hd[a-d][1-16] 来修复磁盘。例如,假设上面的案例中, /home 挂载在
/dev/hda6 上面,那我就『 fsck /dev/hda6 』,不要加上任何参数。
等到系统发现错误,并且出现『clear [Y/N]』时,输入『 y 』吧!
这个过程可能会很长,而且如果你的 partition 上面的 filesystem 有过多的数据损毁时,
即使 fsck 完成后,可能因为伤到系统槽,导致某些关键系统档案数据的损毁,那么依旧是无法进入 Linux
的。此时,就好就是将系统当中的重要数据复制出来,然后重新安装,并且检验一下,
是否实体硬盘有损伤的现象才好!不过一般来说,不太可能会这样啦~
通常都是 fsck 处理完毕后,就能够顺利再次进入 Linux 了。
利用 chroot
切换到另一颗硬盘工作
仔细检查一下,你的 Linux 里面应该会有一个名为 chroot 的指令才对!这是啥?
这是『 change root directory 』的意思啦!意思就是说,可以暂时将根目录移动到某个目录下,
然后去处理某个问题,最后再离开该 root 而回到原本的系统当中。
举例来说,补习班中心最容易有两三个 Linux 系统在同一个主机上面,假设我的第一个 Linux
无法进入了,那么我可以使用第二个 Linux 开机,然后在第二个 Linux 系统下将第一个 Linux 挂载起来,
最后用 chroot 变换到第一个 Linux ,就能够进入到第一个 Linux 的环境当中去处理工作了。
你同样也可以将你的 Linux 硬盘拔到另一个 Linux 主机上面去,然后用这个 chroot 来切换,
以处理你的硬盘问题啊!那怎么做啊?粉简单啦!
- 用尽任何方法,进入一个完整的 Linux 系统 ( run level 3 或 5 );
- 假设有问题的 Linux 磁盘在 /dev/hdb1 上面,且他整个系统的排列是:
/ → /dev/hdb1
/var → /dev/hdb2
/home → /dev/hdb3
/usr → /dev/hdb5
若如此的话,那么在我目前的这个 Linux 底下,我可以建立一个目录,
然后可以这样做:
/chroot/ → /dev/hdb1
/chroot/var/ → /dev/hdb2
/chroot/home/ → /dev/hdb3
/chroot/usr/ → /dev/hdb5
全部挂载完毕后,再输入『 chroot /chroot 』嘿嘿!你就会发现,怎么根目录 (/)
变成那个 /dev/hdb1 的环境啦!这样说明,瞭了吗? ^_^