鸟哥的Linux私房菜(基础篇)- 第二十章、启动流程、模块管理与 Loader
最近升級日期:2009/09/14
| 系統啟動其實是一項非常復雜的程序,因為核心得要偵測硬件并加載適當的驅動程序后,接下來則必須要呼叫程序來準備好系統運行的環境,以讓使用者能夠順利的操作整部主機系統。如果你能夠理解啟動的原理,那么將有助於你在系統出問題時能夠很快速的修復系統喔!而且還能夠順利的配置多重操作系統的多重啟動問題。為了多重啟動的問題,你就不能不學學grub 這個 Linux 底下優秀的啟動管理程序 (boot loader)。而在系統運行期間,你也得要學會管理核心模塊呢! |
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, 啟動自我測試與 MBR
我們在第零章的計算機概論就曾談過計算機主機架構,在個人計算機架構下,你想要啟動整部系統首先就得要讓系統去加載 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 也就能夠被運行羅!
| Tips: 我們知道每顆硬盤的第一個磁區內含有 446 bytes的 MBR 區域,那么如果我的主機上面有兩顆硬盤的話,系統會去哪顆硬盤的 MBR 讀取 boot loader 呢?這個就得要看 BIOS 的配置了。基本上,我們常常講的『系統的 MBR』其實指的是 第一個啟動裝置的 MBR 才對!所以,改天如果你要將啟動管理程序安裝到某顆硬盤的 MBR 時,要特別注意當時系統的『第一個啟動裝置』是哪個,否則會安裝到錯誤的硬盤上面的 MBR 喔!重要重要! |
- 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主要的功能如下:
- 提供菜單:使用者可以選擇不同的啟動項目,這也是多重啟動的重要功能!
- 加載核心文件:直接指向可啟動的程序區段來開始操作系統;
- 轉交其他 loader:將啟動管理功能轉交給其他 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 文件』啦!
- 加載核心偵測硬件與 initrd 的功能
當我們藉由 boot loader 的管理而開始讀取核心文件后,接下來, Linux 就會將核心解壓縮到主內存當中,并且利用核心的功能,開始測試與驅動各個周邊裝置,包括儲存裝置、CPU、網絡卡、聲卡等等。此時 Linux 核心會以自己的功能重新偵測一次硬件,而不一定會使用 BIOS 偵測到的硬件資訊喔!也就是說,核心此時才開始接管 BIOS 后的工作了。那么核心文件在哪里啊?一般來說,他會被放置到 /boot 里面,并且取名為 /boot/vmlinuz 才對!
| [root@www ~]# ls --format=single-column -F /boot config-2.6.18-92.el5 <==此版本核心被編譯時選擇的功能與模塊配置檔 grub/ <==就是啟動管理程序 grub 相關數據目錄 initrd-2.6.18-92.el5.img <==虛擬文件系統檔! System.map-2.6.18-92.el5 <==核心功能放置到內存位址的對應表 vmlinuz-2.6.18-92.el5 <==就是核心文件啦!最重要者! |
從上表我們也可以知道此版本的 Linux 核心為 2.6.18-92.el5 這個版本!為了硬件開發商與其他核心功能開發者的便利,因此 Linux 核心是可以透過動態加載核心模塊的 (就請想成驅動程序即可),這些核心模塊就放置在 /lib/modules/ 目錄內。由於模塊放置到磁碟根目錄內 (要記得 /lib 不可以與 / 分別放在不同的 partition !),因此在啟動的過程中核心必須要掛載根目錄,這樣才能夠讀取核心模塊提供加載驅動程序的功能。而且為了擔心影響到磁碟內的文件系統,因此啟動過程中根目錄是以唯讀的方式來掛載的喔。
一般來說,非必要的功能且可以編譯成為模塊的核心功能,目前的 Linux distributions 都會將他編譯成為模塊。因此 U盤, 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 來加載到內存中,然后這個文件會被解壓縮并且在內存當中模擬成一個根目錄,且此模擬在內存當中的文件系統能夠提供一支可運行的程序,透過該程序來加載啟動過程中所最需要的核心模塊,通常這些模塊就是 U盤, RAID, LVM, SCSI 等文件系統與磁碟介面的驅動程序啦!等加載完成后,會幫助核心重新呼叫 /sbin/init 來開始后續的正常啟動流程。
圖 1.2.3、 BIOS 與 boot loader 及核心加載流程示意圖
如上圖所示,boot loader 可以加載 kernel 與 initrd ,然后在內存中讓 initrd 解壓縮成為根目錄,kernel 就能夠藉此加載適當的驅動程序,最終釋放虛擬文件系統,并掛載實際的根目錄文件系統,就能夠開始后續的正常啟動流程。更詳細的 initrd 說明,你可以自行使用 man initrd 去查閱看看。底下讓我們來了解一下 CentOS 5.x 的 initrd 文件內容有什么吧! ^_^
| # 1. 先將 /boot/initrd 復制到 /tmp/initrd 目錄中,等待解壓縮: [root@www ~]# mkdir /tmp/initrd [root@www ~]# cp /boot/initrd-2.6.18-92.el5.img /tmp/initrd/ [root@www ~]# cd /tmp/initrd [root@www initrd]# file initrd-2.6.18-92.el5.img initrd-2.6.18-92.el5.img: gzip compressed data, ... # 原來是 gzip 的壓縮檔!因為是 gzip ,所以擴展名給他改成 .gz 吧!# 2. 將上述的文件解壓縮: [root@www initrd]# mv initrd-2.6.18-92.el5.img initrd-2.6.18-92.el5.gz [root@www initrd]# gzip -d initrd-2.6.18-92.el5.gz [root@www initrd]# file initrd-2.6.18-92.el5 initrd-2.6.18-92.el5: ASCII cpio archive (SVR4 with no CRC) # 搞了老半天,原來還是 cpio 的命令壓縮成的文件啊!解壓縮看看!# 3. 用 cpio 解壓縮 [root@www initrd]# cpio -ivcdu < initrd-2.6.18-92.el5 [root@www initrd]# ll drwx------ 2 root root 4096 Apr 10 02:05 bin drwx------ 3 root root 4096 Apr 10 02:05 dev drwx------ 2 root root 4096 Apr 10 02:05 etc -rwx------ 1 root root 1888 Apr 10 02:05 init -rw------- 1 root root 5408768 Apr 10 02:00 initrd-2.6.18-92.el5 drwx------ 3 root root 4096 Apr 10 02:05 lib drwx------ 2 root root 4096 Apr 10 02:05 proc lrwxrwxrwx 1 root root 3 Apr 10 02:05 sbin -> bin drwx------ 2 root root 4096 Apr 10 02:05 sys drwx------ 2 root root 4096 Apr 10 02:05 sysroot # 看!是否很像根目錄!尤其也是有 init 這個運行檔!務必看一下權限! # 接下來看看 init 這個文件內有啥咚咚?# 4. 觀察 init 文件內較重要的運行項目 [root@www initrd]# cat init #!/bin/nash <==使用類似 bash 的 shell 來運行 mount -t proc /proc /proc <==掛載內存的虛擬文件系統 ....(中間省略).... echo Creating initial device nodes mknod /dev/null c 1 3 <==創建系統所需要的各項裝置! ....(中間省略).... echo "Loading ehci-hcd.ko module" insmod /lib/ehci-hcd.ko <==加載各項核心模塊,就是驅動程序! ....(中間省略).... echo Creating root device. mkrootdev -t ext3 -o defaults,ro hdc2 <==嘗試掛載根目錄啦! ....(底下省略).... |
嘿嘿!透過上述運行檔的內容,我們可以知道 initrd 有加載模塊并且嘗試掛載了虛擬文件系統。接下來就能夠順利的運行啦!那么是否一定需要 initrd 呢?
| 例題: 是否沒有 initrd 就無法順利啟動? 答: 不見得的!需要 initrd 最重要的原因是,當啟動時無法掛載根目錄的情況下,此時就一定需要 initrd ,例如你的根目錄在特殊的磁碟介面 (U盤, SATA, SCSI) ,或者是你的文件系統較為特殊 (LVM, RAID) 等等,才會需要 initrd。 如果你的 Linux 是安裝在 IDE 介面的磁碟上,并且使用默認的 ext2/ext3 文件系統,那么不需要 initrd 也能夠順利的啟動進入 Linux 的! |
在核心完整的加載后,您的主機應該就開始正確的運行了,接下來,就是要開始運行系統的第一支程序: /sbin/init。
第一支程序 init 及配置檔/etc/inittab 與 runlevel
在核心加載完畢、進行完硬件偵測與驅動程序加載后,此時你的主機硬件應該已經準備就緒了 (ready) ,此時核心會主動的呼叫第一支程序,那就是 /sbin/init 羅。這也是為啥第十七章的 pstree 命令介紹時,你會發現 init 的 PID 號碼是一號啦。/sbin/init 最主要的功能就是準備軟件運行的環境,包括系統的主機名稱、網絡配置、語系處理、文件系統格式及其他服務的啟動等。而所有的動作都會透過 init 的配置檔,亦即是 /etc/inittab 來規劃,而 inittab 內還有一個很重要的配置項目,那就是默認的 runlevel (啟動運行等級) 啦!
- Run level:運行等級有哪些?
那么什么是 run level 呢?他有什么功用啊?其實很簡單啦, Linux 就是藉由配置 run level 來規定系統使用不同的服務來啟動,讓 Linux 的使用環境不同。基本上,依據有無網絡與有無 X Window而將 run level 分為 7 個等級,分別是:
- 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 到底有什么資訊呢?我們先來看看這個文件的內容好了:
- /etc/inittab 的內容與語法
| [root@www ~]# vim /etc/inittab id:5:initdefault: <==默認的 runlevel 配置, 此 runlevel 為 5 si::sysinit:/etc/rc.d/rc.sysinit <==準備系統軟件運行的環境的腳本運行檔# 7 個不同 run level 的,需要啟動的服務的 scripts 放置路徑: l0:0:wait:/etc/rc.d/rc 0 <==runlevel 0 在 /etc/rc.d/rc0.d/ l1:1:wait:/etc/rc.d/rc 1 <==runlevel 1 在 /etc/rc.d/rc1.d/ l2:2:wait:/etc/rc.d/rc 2 <==runlevel 2 在 /etc/rc.d/rc2.d/ l3:3:wait:/etc/rc.d/rc 3 <==runlevel 3 在 /etc/rc.d/rc3.d/ l4:4:wait:/etc/rc.d/rc 4 <==runlevel 4 在 /etc/rc.d/rc4.d/ l5:5:wait:/etc/rc.d/rc 5 <==runlevel 5 在 /etc/rc.d/rc5.d/ l6:6:wait:/etc/rc.d/rc 6 <==runlevel 6 在 /etc/rc.d/rc6.d/# 是否允許按下 [ctrl]+[alt]+[del] 就重新啟動的配置項目: ca::ctrlaltdel:/sbin/shutdown -t3 -r now# 底下兩個配置則是關於不斷電系統的 (UPS),一個是沒電力時的關機,一個是復電的處理 pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down" pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"1:2345:respawn:/sbin/mingetty tty1 <==其實 tty1~tty6 是由底下這六行決定的。 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 tty6x:5:respawn:/etc/X11/prefdm -nodaemon <==X window 則是這行決定的! |
讓我們解析一下這個文件吧!首先,這個文件的語法是利用冒號 (:) 將配置分隔成為四個欄位,每個欄位的意義與說明如下:
| [配置項目]:[run level]:[init 的動作行為]:[命令項目] |
| inittab 配置值 | 意義說明 |
| initdefault | 代表默認的 run level 配置值 |
| sysinit | 代表系統初始化的動作項目 |
| ctrlaltdel | 代表 [ctrl]+[alt]+[del] 三個按鍵是否可以重新啟動的配置 |
| wait | 代表后面欄位配置的命令項目必須要運行完畢才能繼續底下其他的動作 |
| respawn | 代表后面欄位的命令可以無限制的再生 (重新啟動)。舉例來說, tty1 的 mingetty 產生的可登陸畫面,在你注銷而結束后,系統會再開一個新的可登陸畫面等待下一個登陸。 |
- init 的處理流程
事實上 /etc/inittab 的配置也有點類似 shell script 啦,因為該文件內容的配置也是一行一行的從上往下處理的,因此我們可以知道 CentOS 的 init 依據 inittab 配置的處理流程會是:
現在你可以知道為啥 [ctrl]+[alt]+[del] 可以重新啟動而我們默認提供 6 個虛擬終端機 (tty1~tty6) 給你使用了吧!由於整個配置都是依據 /etc/inittab 來決定的,因此如果你想要修改任何細節的話,可以這樣做喔:
- 如果不想讓使用者利用 [crtl]+[alt]+[del] 來重新啟動系統,可以將『ca::ctrlaltdel:/sbin/shutdown -t3 -r now 』加上注解 (#) 來取消該配置
- 規定啟動的默認 run level 是純文字的 3 號或者是具有圖形介面的 5 號 ,可經由『 id:5:initdefault: 』那個數字來決定!以鳥哥自己這個文件為例,我是使用默認的圖形介面。如果你想要關閉圖形介面的話,將該行 5 改成 3 即可。
- 如果不想要啟動六個終端機 (tty1~tty6),那么可以將『6:2345:respawn:/sbin/mingetty tty6』關閉數個。但務必至少啟動一個喔!
所以說,你現在會自行修改登陸時的默認 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 羅。
| Tips: 老實說,這個文件的檔名在各不同的 distributions 當中都不相同,例如 SuSE server 9 就使用 /etc/init.d/boot 與 /etc/init.d/rc 來進行的。所以,你最好還是自行到 /etc/inittab 去察看一下系統的工作喔! ^_^ |
如果你使用 vim 去查閱過 /etc/rc.d/rc.sysinit 的話,那么可以發現他主要的工作大抵有這幾項:
讀取網絡配置檔 /etc/sysconfig/network ,取得主機名稱與默認通訊閘 (gateway) 等網絡環境。
除掛載內存裝置 /proc 之外,還會主動偵測系統上是否具有 usb 的裝置,若有則會主動加載 usb 的驅動程序,并且嘗試掛載 usb 的文件系統。
我們在第十七章談到的 SELinux 在此時進行一些檢測,并且檢測是否需要幫所有的文件重新編寫標準的 SELinux 類型 (auto relabel)。
亂數產生器可以幫助系統進行一些口令加密演算的功能,在此需要啟動兩次亂數產生器。
根據核心在啟動時偵測的結果 (/proc/sys/kernel/modprobe ) 開始進行 ide / scsi /網絡 / 音效 等周邊設備的偵測,以及利用以加載的核心模塊進行 PnP 裝置的參數測試。
使用者可以在 /etc/sysconfig/modules/*.modules 加入自訂的模塊,則此時會被加載到系統當中
系統會主動去讀取 /etc/sysctl.conf 這個文件的配置值,使核心功能成為我們想要的樣子。
在 /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 里面提到的:
| 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 要運行的各項腳本放置處啦!主要是透過 /etc/rc.d/rc 這個命令來處理相關任務!由於鳥哥使用默認的 runlevel 5 ,因此我們主要針對上述特殊字體那行來解釋好了: /etc/rc.d/rc 5 的意義是這樣的(建議您自行使用 vim 去觀察一下 /etc/rc.d/rc 這個文件,你會更有概念!):
- 透過外部第一號參數 ($1) 來取得想要運行的腳本目錄。亦即由 /etc/rc.d/rc 5 可以取得 /etc/rc5.d/ 這個目錄來準備處理相關的腳本程序;
- 找到 /etc/rc5.d/K??* 開頭的文件,并進行『 /etc/rc5.d/K??* stop 』的動作;
- 找到 /etc/rc5.d/S??* 開頭的文件,并進行『 /etc/rc5.d/S??* start 』的動作;
透過上面的說明我們可以知道所有的項目都與 /etc/rc5.d/ 有關,那么我們就來瞧瞧這個目錄下有些什么玩意兒吧!
| [root@www ~]# ll /etc/rc5.d/ lrwxrwxrwx 1 root root 16 Sep 4 2008 K02dhcdbd -> ../init.d/dhcdbd ....(中間省略).... lrwxrwxrwx 1 root root 14 Sep 4 2008 K91capi -> ../init.d/capi lrwxrwxrwx 1 root root 23 Sep 4 2008 S00microcode_ctl -> ../init.d/microcode_ctl lrwxrwxrwx 1 root root 22 Sep 4 2008 S02lvm2-monitor -> ../init.d/lvm2-monitor ....(中間省略).... lrwxrwxrwx 1 root root 17 Sep 4 2008 S10network -> ../init.d/network ....(中間省略).... lrwxrwxrwx 1 root root 11 Sep 4 2008 S99local -> ../rc.local lrwxrwxrwx 1 root root 16 Sep 4 2008 S99smartd -> ../init.d/smartd ....(底下省略).... |
在這個目錄下的文件很有趣,主要具有幾個特點:
- 檔名全部以 Sxx 或 Kxx ,其中 xx 為數字,且這些數字在文件之間是有相關性的!
- 全部是連結檔,連結到 stand alone 服務啟動的目錄 /etc/init.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 的運行,這兩個文件會這樣進行:
- /etc/rc5.d/K91capi stop --> /etc/init.d/capi stop
- /etc/rc5.d/S10network start --> /etc/init.d/network start
所以說,你有想要啟動該 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 內的這一段:
| 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:5:respawn:/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 啦!
啟動過程會用到的主要配置檔
我們在 /sbin/init 的運行過程中有談到許多運行腳本,包括 /etc/rc.d/rc.sysinit 以及 /etc/rc.d/rc 等等,其實這些腳本都會使用到相當多的系統配置檔,這些啟動過程會用到的配置檔則大多放置在 /etc/sysconfig/ 目錄下。同時,由於核心還是需要加載一些驅動程序 (核心模塊),此時系統自訂的裝置與模塊對應檔 (/etc/modprobe.conf) 就顯的挺重要了喔!
- 關於模塊: /etc/modprobe.conf
還記得我們在 /etc/rc.d/rc.sysinit 當中談到的加載使用者自訂模塊的地方嗎?就是在 /etc/sysconfig/modules/ 目錄下啊!雖然核心提供的默認模塊已經很足夠我們使用了,但是,某些條件下我們還是得對模塊進行一些參數的規劃,此時就得要使用到 /etc/modprobe.conf 羅!舉例來說,鳥哥的 CentOS 主機的 modprobe.conf 有點像這樣:
| [root@www ~]# cat /etc/modprobe.conf alias eth0 8139too <==讓 eth0 使用 8139too 的模塊 alias scsi_hostadapter pata_sis alias snd-card-0 snd-trident options snd-card-0 index=0 <==額外指定 snd-card-0 的參數功能 options snd-trident index=0 |
這個文件大多在指定系統內的硬件所使用的模塊啦!這個文件通常系統是可以自行產生的,所以你不必手動去訂正他!不過,如果系統捉到錯誤的驅動程序,或者是你想要使用升級的驅動程序來對應相關的硬件配備時,你就得要自行手動的處理一下這個文件了。
以上表的第一行為例,鳥哥使用螃蟹卡 (Realtek 的芯片組) 來作為我的網絡卡,那螃蟹卡使用的模塊就是 8139too啦!這樣看的懂了吧?當我要啟動網絡卡時,系統會跑到這個文件來查閱一下,然后加載 8139too 驅動程序來驅動網絡卡羅!更多的相關說明,請 man modprobe.conf 喔!
- /etc/sysconfig/*
不說您也知道,整個啟動的過程當中,老是讀取的一些服務的相關配置檔都是記錄在 /etc/sysconfig 目錄下的!那么該目錄底下有些啥玩意兒?我們找幾個重要的文件來談談:
- authconfig:
這個文件主要在規范使用者的身份認證的機制,包括是否使用本機的 /etc/passwd, /etc/shadow 等,以及 /etc/shadow 口令記錄使用何種加密演算法,還有是否使用外部口令服務器提供的帳號驗證 (NIS, LDAP) 等。系統默認使用 MD5 加密演算法,并且不使用外部的身份驗證機制;
- clock:
此文件在配置 Linux 主機的時區,可以使用格林威治時間(GMT),也可以使用臺灣的本地時間 (local)。基本上,在 clock 文件內的配置項目『 ZONE 』所參考的時區位於 /usr/share/zoneinfo 目錄下的相對路徑中。而且要修改時區的話,還得將 /usr/share/zoneinfo/Asia/Taipei 這個文件復制成為 /etc/localtime 才行!
- i18n:
i18n 在配置一些語系的使用方面,例如最麻煩的文字介面下的日期顯示問題!如果你是以中文安裝的,那么默認語系會被選擇 zh_TW.UTF8 ,所以在純文字介面之下,你的文件日期顯示可能就會呈現亂碼!這個時候就需要更改一下這里啦!更動這個 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[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 時,系統會:
- 先比對 /etc/rc3.d/ 及 /etc/rc5.d 內的 K 與 S 開頭的文件;
- 在新的 runlevel 亦即是 /etc/rc3.d/ 內有多的 K 開頭文件,則予以關閉;
- 在新的 runlevel 亦即是 /etc/rc3.d/ 內有多的 S 開頭文件,則予以啟動;
也就是說,兩個 run level 都存在的服務就不會被關閉啦!如此一來,就很容易切換 run level 了,而且還不需要重新啟動呢!真方便。那我怎么知道目前的 run level 是多少呢?直接在 bash 當中輸入 runlevel 即可啊!
| [root@www ~]# runlevel N 5 # 左邊代表前一個 runlevel ,右邊代表目前的 runlevel。 # 由於之前并沒有切換過 runlevel ,因此前一個 runlevel 不存在 (N) |
| # 將目前的 runlevel 切換成為 3 (注意, tty7 的數據會消失!) [root@www ~]# init 3 NIT: Sending processes the TERM signal Applying Intel CPU microcode update: [ OK ] Starting background readahead: [ OK ] Starting irqbalance: [ OK ] Starting httpd: [ OK ] Starting anacron: [ OK ] # 這代表,新的 runlevel 亦即是 runlevel3 比前一個 runlevel 多出了上述 5 個服務[root@www ~]# runlevel 5 3 # 看吧!前一個是 runlevel 5 ,目前的是 runlevel 3 啦! |
那么你能不能利用 init 來進行關機與重新啟動呢?可以的啦!利用『 init 0 』就能夠關機,而『 init 6 』就能夠重新啟動!為什么?往前翻一下 runlevel 的定義即可了解吧!
核心與核心模塊
談完了整個啟動的流程,您應該會知道,在整個啟動的過程當中,是否能夠成功的驅動我們主機的硬件配備,是核心 (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 或 /usr/src/kernels/ (要安裝才會有,默認不安裝)
如果該核心被順利的加載系統當中了,那么就會有幾個資訊紀錄下來:
- 核心版本: /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@www ~]# depmod [-Ane] 選項與參數: -A :不加任何參數時, depmod 會主動的去分析目前核心的模塊,并且重新寫入/lib/modules/$(uname -r)/modules.dep 當中。若加入 -A 參數時,則 depmod會去搜尋比 modules.dep 內還要新的模塊,如果真找到新模塊,才會升級。 -n :不寫入 modules.dep ,而是將結果輸出到螢幕上(standard out); -e :顯示出目前已加載的不可運行的模塊名稱范例一:若我做好一個網絡卡驅動程序,檔名為 a.ko,該如何升級核心相依性? [root@www ~]# cp a.ko /lib/modules/$(uname -r)/kernel/drivers/net [root@www ~]# depmod |
以上面的范例一為例,我們的 Linux kernel 2.6.x 版本的核心模塊擴展名一定是 .ko 結尾的,當你使用 depmod 之后,該程序會跑到模塊標準放置目錄 /lib/modules/$(uname -r)/kernel ,并依據相關目錄的定義將全部的模塊捉出來分析,最終才將分析的結果寫入 modules.dep 文件中的吶!這個文件很重要喔!因為他會影響到本章稍后會介紹的 modprobe 命令的應用!
核心模塊的觀察
那你到底曉不曉得目前核心加載了多少的模塊呢?粉簡單啦!利用 lsmod 即可!
| [root@www ~]# lsmod Module Size Used by autofs4 24517 2 hidp 23105 2 ....(中間省略).... 8139too 28737 0 8139cp 26305 0 mii 9409 2 8139too,8139cp <==mii 還被 8139cp, 8139too 使用 ....(中間省略).... uhci_hcd 25421 0 <==底下三個是 U盤 相關的模塊! ohci_hcd 23261 0 ehci_hcd 33357 0 |
使用 lsmod 之后,系統會顯示出目前已經存在於核心當中的模塊,顯示的內容包括有:
- 模塊名稱(Module);
- 模塊的大小(size);
- 此模塊是否被其他模塊所使用 (Used by)。
也就是說,模塊其實真的有相依性喔!舉上表為例, mii 這個模塊會被 8139too 所使用。簡單的說,就是『當你要加載 8139too 時,需要先加載 mii 這個模塊才可以順利的加載 8139too』的意思。那么除了顯示出目前的模塊外,我還可以查閱每個模塊的資訊嗎?舉例來說,我們知道 8139too是螃蟹卡的驅動程序,那么 mii 是什么咚咚?就用 modinfo 來觀察吧!
| [root@www ~]# modinfo [-adln] [module_name|filename] 選項與參數: -a :僅列出作者名稱; -d :僅列出該 modules 的說明 (description); -l :僅列出授權 (license); -n :僅列出該模塊的詳細路徑。范例一:由上個表格當中,請列出 mii 這個模塊的相關資訊: [root@www ~]# modinfo mii filename: /lib/modules/2.6.18-92.el5/kernel/drivers/net/mii.ko license: GPL description: MII hardware support library author: Jeff Garzik <jgarzik@pobox.com> srcversion: 16DCEDEE4B5629C222C352D depends: vermagic: 2.6.18-92.el5 SMP mod_unload 686 REGPARM 4KSTACKS gcc-4.1 # 可以看到這個模塊的來源,以及該模塊的簡易說明!(是硬件支持函式庫)范例二:我有一個模塊名稱為 a.ko ,請問該模塊的資訊為? [root@www ~]# modinfo a.ko ....(省略).... |
事實上,這個 modinfo 除了可以『查閱在核心內的模塊』之外,還可以檢查『某個模塊文件』,因此,如果你想要知道某個文件代表的意義為何,利用 modinfo 加上完整檔名吧!看看就曉得是啥玩意兒羅! ^_^
核心模塊的加載與移除
好了,如果我想要自行手動加載模塊,又該如何是好?有很多方法啦,最簡單而且建議的,是使用 modprobe 這個命令來加載模塊,這是因為 modprobe 會主動的去搜尋 modules.dep 的內容,先克服了模塊的相依性后,才決定需要加載的模塊有哪些,很方便。至於 insmod 則完全由使用者自行加載一個完整檔名的模塊,并不會主動的分析模塊相依性啊!
| [root@www ~]# insmod [/full/path/module_name] [parameters]范例一:請嘗試加載 cifs.ko 這個『文件系統』模塊 [root@www ~]# insmod /lib/modules/$(uname -r)/kernel/fs/cifs/cifs.ko [root@www ~]# lsmod | grep cifs cifs 212789 0 |
他立刻就將該模塊加載羅~但是 insmod 后面接的模塊必須要是完整的『檔名』才行!那如何移除這個模塊呢?
| [root@www ~]# rmmod [-fw] module_name 選項與參數: -f :強制將該模塊移除掉,不論是否正被使用; -w :若該模塊正被使用,則 rmmod 會等待該模塊被使用完畢后,才移除他!范例一:將剛剛加載的 cifs 模塊移除! [root@www ~]# rmmod cifs范例二:請加載 vfat 這個『文件系統』模塊 [root@www ~]# insmod /lib/modules/$(uname -r)/kernel/fs/vfat/vfat.ko insmod: error inserting '/lib/modules/2.6.18-92.el5/kernel/fs/vfat/vfat.ko': -1 Unknown symbol in module # 無法加載 vfat 這個模塊啊!傷腦筋! |
使用 insmod 與 rmmod 的問題就是,你必須要自行找到模塊的完整檔名才行,而且如同上述范例二的結果,萬一模塊有相依屬性的問題時,你將無法直接加載或移除該模塊呢!所以近年來我們都建議直接使用 modprobe 來處理模塊加載的問題,這個命令的用法是:
| [root@www ~]# modprobe [-lcfr] module_name 選項與參數: -c :列出目前系統所有的模塊!(更詳細的代號對應表) -l :列出目前在 /lib/modules/`uname -r`/kernel 當中的所有模塊完整檔名; -f :強制加載該模塊; -r :類似 rmmod ,就是移除某個模塊羅~范例一:加載 cifs 模塊 [root@www ~]# modprobe cifs # 很方便吧!不需要知道完整的模塊檔名,這是因為該完整檔名已經記錄到 # /lib/modules/`uname -r`/modules.dep 當中的緣故啊!如果要移除的話: [root@www ~]# modprobe -r cifs |
使用 modprobe 真的是要比 insmod 方便很多!因為他是直接去搜尋 modules.dep 的紀錄,所以羅,當然可以克服模塊的相依性問題,而且還不需要知道該模塊的詳細路徑呢!好方便! ^_^
例題: 嘗試使用 modprobe 加載 vfat 這個模塊,并且觀察該模塊的相關模塊是哪個? 答: 我們使用 modprobe 來加載,再以 lsmod 來觀察與 grep 擷取關鍵字看看:
|
核心模塊的額外參數配置:/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@www ~]# 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: 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) 來運行:
- Stage 1:運行 boot loader 主程序:
第一階段為運行 boot loader 的主程序,這個主程序必須要被安裝在啟動區,亦即是 MBR 或者是 boot sector。但如前所述,因為 MBR 實在太小了,所以,MBR 或 boot sector 通常僅安裝 boot loader 的最小主程序,并沒有安裝 loader 的相關配置檔;
- Stage 2:主程序加載配置檔:
第二階段為透過 boot loader 加載所有配置檔與相關的環境參數文件 (包括文件系統定義與主要配置檔 menu.lst),一般來說,配置檔都在 /boot 底下。
那么這些配置檔是放在哪里啊?這些與 grub 有關的文件都放置到 /boot/grub 中,那我們就來看看有哪些文件吧!
| [root@www ~]# ls -l /boot/grub -rw-r--r-- device.map <==grub 的裝置對應檔(底下會談到) -rw-r--r-- e2fs_stage1_5 <==ext2/ext3 文件系統之定義檔 -rw-r--r-- fat_stage1_5 <==FAT 文件系統之定義檔 -rw-r--r-- ffs_stage1_5 <==FFS 文件系統之定義檔 -rw------- grub.conf <==grub 在 Red Hat 的配置檔 -rw-r--r-- iso9660_stage1_5 <==光驅文件系統定義檔 -rw-r--r-- jfs_stage1_5 <==jfs 文件系統定義檔 lrwxrwxrwx menu.lst -> ./grub.conf <==其實 menu.lst 才是配置檔! -rw-r--r-- minix_stage1_5 <==minix 文件系統定義檔 -rw-r--r-- reiserfs_stage1_5 <==reiserfs 文件系統定義檔 -rw-r--r-- splash.xpm.gz <==啟動時在 grub 底下的背景圖示 -rw-r--r-- stage1 <==stage 1 的相關說明 -rw-r--r-- stage2 <==stage 2 的相關說明 -rw-r--r-- ufs2_stage1_5 <==UFS 的文件系統定義檔 -rw-r--r-- vstafs_stage1_5 <==vstafs 文件系統定義檔 -rw-r--r-- xfs_stage1_5 <==xfs 文件系統定義檔 |
從上面的說明你可以知道 /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 的優點挺多的,包括有:
- 認識與支持較多的文件系統,并且可以使用 grub 的主程序直接在文件系統中搜尋核心檔名;
- 啟動的時候,可以『自行編輯與修改啟動配置項目』,類似 bash 的命令模式;
- 可以動態搜尋配置檔,而不需要在修改配置檔后重新安裝 grub 。亦即是我們只要修改完/boot/grub/menu.lst 里頭的配置后,下次啟動就生效了!
上面第三點其實就是 Stage 1, Stage 2 分別安裝在 MBR (主程序) 與文件系統當中 (配置檔與定義檔) 的原因啦!好了,接下來,讓我們好好了解一下 grub 的配置檔: /boot/grub/menu.lst 這玩意兒吧!要注意喔,那個 lst 是 LST 的小寫,不要搞錯羅!
- 硬盤與分割槽在 grub 中的代號
安裝在 MBR 的 grub 主程序,最重要的任務之一就是從磁碟當中加載核心文件,以讓核心能夠順利的驅動整個系統的硬件。所以羅, grub 必須要認識硬盤才行啊!那么 grub 到底是如何認識硬盤的呢?嘿嘿! grub 對硬盤的代號配置與傳統的 Linux 磁碟代號可完全是不同的!grub 對硬盤的識別使用的是如下的代號:
(hd0,0)夠神了吧?跟 /dev/hda1 風馬牛不相干~怎么辦啊?其實只要注意幾個東西即可,那就是:
- 硬盤代號以小括號 ( ) 包起來;
- 硬盤以 hd 表示,后面會接一組數字;
- 以『搜尋順序』做為硬盤的編號,而不是依照硬盤排線的排序!(這個重要!)
- 第一個搜尋到的硬盤為 0 號,第二個為 1 號,以此類推;
- 每顆硬盤的第一個 partition 代號為 0 ,依序類推。
所以說,第一顆『搜尋到的硬盤』代號為:『(hd0)』,而該顆硬盤的第一號分割槽為『(hd0,0)』,這樣說了解了吧?反正你要記得,在 grub 里面,他開始的數字是 0 而不是 1 就是了!
| Tips: 在較舊的主板上面,通常第一顆硬盤會插在 IDE 1 的 master 上,就會是 /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)』,而第一顆硬盤的第一個分割槽的 boot sector 代號就是『(hd0,0)』第一顆硬盤的第一個邏輯分割槽的 boot sector 代號為『(hd0,4)』了了吧!
| 例題: 假設你的系統僅有一顆 SATA 硬盤,請說明該硬盤的第一個邏輯分割槽在 Linux 與 grub 當中的檔名與代號: 答: 因為是 SATA 磁碟,加上使用邏輯分割槽,因此 Linux 當中的檔名為 /dev/sda5 才對 (1~4 保留給 primary 與 extended 使用)。至於 grub 當中的磁碟代號則由於僅有一顆磁碟,因此代號會是『 (hd0,4) 』才對。 |
- /boot/grub/menu.lst 配置檔:
了解了 grub 當中最麻煩的硬盤代號后,接下來,我們就可以瞧一瞧配置檔的內容了。先看一下鳥哥的 CentOS內的 /boot/grub/menu.lst 好了:
| [root@www ~]# vim /boot/grub/menu.lst default=0 <==默認啟動選項,使用第 1 個啟動菜單 (title) timeout=5 <==若 5 秒內未動鍵盤,使用默認菜單啟動 splashimage=(hd0,0)/grub/splash.xpm.gz <==背景圖示所在的文件 hiddenmenu <==讀秒期間是否顯示出完整的菜單畫面(默認隱藏) title CentOS (2.6.18-92.el5) <==第一個菜單的內容root (hd0,0)kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quietinitrd /initrd-2.6.18-92.el5.img |
在 title 以前的四行,都是屬於 grub 的整體配置,包括默認的等待時間與默認的啟動項目,還有顯示的畫面特性等等。至於 title 后面才是指定啟動的核心文件或者是 boot loader 控制權。在整體配置方面的項目主要常見的有:
- default=0
這個必須要與 title 作為對照,在配置檔里面有幾個 title ,啟動的時候就會有幾個菜單可以選擇。由於 grub 啟始號碼為 0 號,因此 default=0 代表使用『第一個 title 項目』來啟動的意思。default 的意思是,如果在讀秒時間結束前都沒有動到鍵盤, grub 默認使用此 title 項目 (在此為 0 號) 來啟動。
- timeout=5
啟動時會進行讀秒,如果在 5 秒鐘內沒有按下任何按鍵,就會使用上面提到的 default 后面接的那個 title 項目來啟動的意思。如果你覺得 5 秒太短,那可以將這個數值調大 (例如 30 秒) 即可。此外,如果 timeout=0 代表直接使用 default 值進行啟動而不讀秒,timeout=-1 則代表直接進入菜單不讀秒了!
- splashimage=(hd0,0)/grub/splash.xpm.gz
有沒有發現你的 CentOS 在啟動的時候背景不是黑白而是有色彩變化的呢?那就是這個文件提供的背景圖示啦(注3)!不過這個文件的實際路徑寫法怎么會是這樣啊?很簡單啊~上述的意思是:在 (hd0,0) 這個分割槽內的最頂層目錄中,底下的 grub/splash.xpm.gz 那個文件的意思。由於鳥哥將 /boot 這個目錄獨立成為 /dev/hda1 ,因此這邊就會寫成『在 /dev/hda1 里面的 grub/splash.xpm.gz 』的意思啦!想一想,如果你的 /boot 目錄并沒有獨立成為一個分割槽,這里會寫成如何?
- hiddenmenu
這個說的是,啟動時是否要顯示菜單?目前 CentOS 默認是不要顯示菜單,如果您想要顯示菜單,那就將這個配置值注解掉!
整體配置的地方大概是這樣,而底下那個 title 則是顯示啟動的配置項目。如同前一小節提到的,啟動時可以選擇(1)直接指定核心文件啟動或 (2)將 boot loader 控制權轉移到下個 loader (此過程稱為 chain-loader)。每個 title 后面接的是『該啟動項目名稱的顯示』,亦即是在菜單出現時,菜單上面的名稱而已。那么這兩種方式的配置有啥不同呢?
既然要指定核心啟動,所以當然要找到核心文件啦!此外,有可能還需要用到 initrd 的 RAM Disk 配置檔。但是如前說的,尚未啟動完成,所以我們必須要以 grub 的硬盤識別方式找出完整的 kernel 與 initrd 檔名才行。因此,我們可能需要有底下的方式來配置才行!
| 1. 先指定核心文件放置的 partition,再讀取文件 (目錄樹),最后才加入文件的實際檔名與路徑 (kernel 與 initrd);鳥哥的 /boot 為 /dev/hda1 ,因此核心文件的配置則成為: root (hd0,0) <==代表核心文件放在那個 partition 當中 kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet initrd /initrd-2.6.18-92.el5.img |
root :代表的是『核心文件放置的那個 partition 而不是根目錄』喔!不要搞錯了!以鳥哥的案例來說,我的根目錄為 /dev/hda2 而 /boot 獨立為 /dev/hda1 ,因為與 /boot 有關,所以磁碟代號就會成為 (hd0,0) 羅。
kernel :至於 kernel 后面接的則是核心的檔名,而在檔名后面接的則是核心的參數。由於啟動過程中需要掛載根目錄,因此 kernel 后面接的那個 root=LABEL=/1 指的是『Linux 的根目錄在哪個 partition 』的意思。還記得第八章談過的 LABEL 掛載功能吧?是的,這里使用 LABEL 來掛載根目錄。至於 rhgb 為色彩顯示而 quiet 則是安靜模式 (螢幕不會輸出核心偵測的資訊)。
initrd :就是前面提到的 initrd 制作出 RAM Disk 的文件檔名啦!
| 2. 直接指定 partition 與檔名,不需要額外指定核心文件所在裝置代號 kernel (hd0,0)/vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet initrd (hd0,0)/initrd-2.6.18-92.el5.img |
| 例題: 我的系統分割是: /dev/hda1 (/), /dev/hda2 (swap) 而已,且我的核心文件為 /boot/vmlinuz,請問 grub 的 menu.lst 內該如何撰寫核心文件位置? 答: 我們使用疊代的方式來了解一下好了。由於核心檔名為 /boot/vmlinuz,轉成裝置檔名與代號會成為如下的過程: 原始文件: /boot/vmlinuz ↓ Linux 裝置:(/dev/hda1)/boot/vmlinuz ↓ grub 裝置:(hd0,0)/boot/vmlinuz 所以最終的 kernel 寫法會變成: kernel (hd0,0)/boot/vmlinuz root=/dev/hda1 ... |
| 例題: 同上,只是我的分割情況變成: /dev/sda1 (/boot), /dev/sda5 (/) 時? 答: 由於 /boot 被獨立出來了,所以情況會不一樣喔!如下所示: 原始文件: /boot/vmlinuz ↓ Linux 裝置:(/dev/sda1)/vmlinuz ↓ grub 裝置:(hd0,0)/vmlinuz 所以最終的 kernel 寫法會變成: kernel (hd0,0)/vmlinuz root=/dev/sda5 ... |
所謂的 chain loader (啟動管理程序的鏈結) 僅是在將控制權交給下一個 boot loader 而已,所以 grub 并不需要認識與找出 kernel 的檔名 ,『 他只是將 boot的控制權交給下一個 boot sector 或 MBR 內的 boot loader 而已 』所以通常他也不需要去查驗下一個 boot loader 的文件系統!
一般來說, chain loader 的配置只要兩個就夠了,一個是預計要前往的 boot sector 所在的分割槽代號,另一個則是配置 chainloader 在那個分割槽的 boot sector (第一個磁區) 上!假設我的 Windows 分割槽在 /dev/hda1 ,且我又只有一顆硬盤,那么要 grub 將控制權交給 windows 的 loader 只要這樣就夠了:
| [root@www ~]# vi /boot/grub/menu.lst ....前略.... title Windows partitionroot (hd0,0) <==配置使用此分割槽chainloader +1 <== +1 可以想成第一個磁區,亦即是 boot sector |
| [root@www ~]# vi /boot/grub/menu.lst ....前略.... title Windows partitionrootnoverify (hd0,0) <==不檢驗此分割槽chainloader +1makeactive <==配置此分割槽為啟動碟(active) |
| [root@www ~]# vi /boot/grub/menu.lst ....前略.... title Windows partitionhide (hd0,4) <==隱藏 (hd0,4) 這個分割槽rootnoverify (hd0,0)chainloader +1makeactive |
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 的時刻為:
- 根目錄所在磁碟為 SATA、U盤 或 SCSI 等連接介面;
- 根目錄所在文件系統為 LVM, RAID 等特殊格式;
- 根目錄所在文件系統為非傳統 Linux 認識的文件系統時;
- 其他必須要在核心加載時提供的模塊。
| Tips: 之前鳥哥忽略 initrd 這個文件的重要性,是因為鳥哥很窮... ^_^。因為鳥哥的 Linux 主機都是較早期的硬件,使用的是 IDE 介面的硬盤,而且并沒有使用 LVM 等特殊格式的文件系統,而 Linux 核心本身就認識 IDE 介面的磁碟,因此不需要 initrd 也可以順利啟動完成的。自從 SATA 硬盤流行起來后,沒有 initrd 就沒辦法啟動了!因為 SATA 硬盤使用的是 SCSI 模塊來驅動的,而 Linux 默認將 SCSI 功能編譯成為模塊.... |
一般來說,各 distribution 提供的核心都會附上 initrd 文件,但如果你有特殊需要所以想重制 initrd 文件的話,可以使用 mkinitrd 來處理的。這個文件的處理方式很簡單, man mkinitrd 就知道了! ^_^。我們還是簡單的介紹一下去!
| [root@www ~]# mkinitrd [-v] [--with=模塊名稱] initrd檔名 核心版本 選項與參數: -v :顯示 mkinitrd 的運行過程 --with=模塊名稱:模塊名稱指的是模塊的名字而已,不需要填寫檔名。舉例來說,目前核心版本的 ext3 文件系統模塊為底下的檔名:/lib/modules/$(uname -r)/kernel/fs/ext3/ext3.ko那你應該要寫成: --with=ext3 就好了 (省略 .ko) initrd檔名:你所要創建的 initrd 檔名,盡量取有意義又好記的名字。 核心版本 :某一個核心的版本,如果是目前的核心則是『 $(uname -r) 』范例一:以 mkinitrd 的默認功能創建一個 initrd 虛擬磁碟文件 [root@www ~]# mkinitrd -v initrd_$(uname -r) $(uname -r) Creating initramfs Looking for deps of module ehci-hcd Looking for deps of module ohci-hcd ....(中間省略).... Adding module ehci-hcd <==最終加入 initrd 的就是底下的模塊 Adding module ohci-hcd Adding module uhci-hcd Adding module jbd Adding module ext3 Adding module scsi_mod Adding module sd_mod Adding module libata Adding module pata_sis[root@www ~]# ll initrd_* -rw------- 1 root root 2406443 Apr 30 02:55 initrd_2.6.18-92.el5 # 由於目前的核心版本可使用 uname -r 取得,因此鳥哥使用較簡單的命令來處理羅~ # 此時 initrd 會被創建起來,你可以將他移動到 /boot 等待使用。范例二:添加 8139too 這個模塊的 initrd 文件 [root@www ~]# mkinitrd -v --with=8139too initrd_vbirdtest $(uname -r) ....(前面省略).... Adding module mii Adding module 8139too <==看到沒!這樣就加入了! |
initrd 創建完成之后,同時核心也處理完畢后,我們就可以使用 grub 來創建菜單了!底下繼續瞧一瞧吧!
測試與安裝 grub
如果你的 Linux 主機本來就是使用 grub 作為 loader 的話,那么你就不需要重新安裝 grub 了,因為 grub 本來就會主動去讀取配置檔啊!您說是吧!但如果你的 Linux 原來使用的并非 grub ,那么就需要來安裝啦!如何安裝呢?首先,你必須要使用 grub-install 將一些必要的文件復制到/boot/grub 里面去,你應該這樣做的:
| Tips: 安裝些什么呢?因為 boot loader 有兩個 stage ,而配置檔得要放置到適當的地方。這個 grub-install 就是在安裝配置檔 (包括文件系統定義檔與 menu.lst 等等) 而已!如果要將 grub 的 stage1 主程序安裝起來,就得要使用 grub shell 的功能喔!本章稍后會介紹。 |
| [root@www ~]# grub-install [--root-directory=DIR] INSTALL_DEVICE 選項與參數: --root-directory=DIR 那個 DIR 為實際的目錄,使用 grub-install 默認會將grub 所有的文件都復制到 /boot/grub/* ,如果想要復制到其他目錄與裝置去,就得要用這個參數。 INSTALL_DEVICE 安裝的裝置代號啦!范例一:將 grub 安裝在目前系統的 MBR 底下,我的系統為 /dev/hda: [root@www ~]# grub-install /dev/hda # 因為原本 /dev/hda 就是使用 grub ,所以似乎不會出現什么特別的信息。 # 如果去查閱一下 /boot/grub 的內容,會發現所有的文件都升級了,因為我們重裝了!范例二:我的 /home 為獨立的 /dev/hda3 ,如何安裝 grub 到 /dev/hda3 (boot sector) [root@www ~]# grub-install --root-directory=/home /dev/hda3 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 /home/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 <==會給予裝置代號的對應表![root@www ~]# ll /home/boot/grub/ -rw-r--r-- 1 root root 30 Apr 30 11:12 device.map -rw-r--r-- 1 root root 7584 Apr 30 11:12 e2fs_stage1_5 ....(底下省略).... # 看!文件都安裝進來了!但是注意到,我們并沒有配置檔喔!那要自己創建! |
所以說, grub-install 是安裝 grub 相關的文件 (例如文件系統定義檔) 到你的裝置上面去等待在啟動時被讀取,但還需要配置好配置檔 (menu.lst) 后,再以 grub shell 來安裝 grub 主程序到 MBR 或者是 boot sector 上面去喔!好了,那我們來思考一下想要安裝的數據。
例題: 我預計啟動時要直接顯示菜單,且菜單倒數為 30 秒。另外,在原本的 menu.lst 當中新增三個啟動菜單,分別如下說明:
|
我們已經將配置檔處理完畢,但是你要知道的是,我們并不知道 /dev/hda1 到底有沒有包含 grub 的主程序,因此我們想要將 grub 主程序再次的安裝到 /dev/hda1 的 boot sector ,也想要重新安裝 grub 到 MBR 上面去。此時我們就得要使用 grub shell 羅!整個安裝與 grub shell 的動作其實很簡單,如果您有興趣研究的話,可以使用 info grub 去查閱~鳥哥這里僅介紹幾個有用的命令而已。
- 用『 root (hdx,x) 』選擇含有 grub 目錄的那個 partition 代號;
- 用『 find /boot/grub/stage1 』看看能否找到安裝資訊文件;
- 用『 find /boot/vmlinuz 』看看能否找到 kernel file (不一定要成功!);
- 用『 setup (hdx,x) 』或『 setup (hdx) 』將 grub 安裝在 boot sector 或 MBR;
- 用『 quit 』來離開 grub shell !
由於我們最需要安裝的就是那個 stage1 啦!那才是 grub 的主程序嘛!而且配置檔通常與主程序擺在同一個目錄下。因此我們需要使用 root (hd0,0) 去找到 /boot/grub/stage1 喔!接下來,請用 grub 來進入 grub shell 吧!進入 grub 后,會出現一個『 grub> 』的提示字節啊!
| [root@www ~]# grub# 1. 先配置一下含有 grub 目錄的那個 partition 啊! grub> root (hd0,0)Filesystem type is ext2fs, partition type 0x83 # 鳥哥主機的分割中,/boot/grub 在 /boot 的分割槽,亦即是 /dev/hda1 內喔! # 另外, grub 也能夠分辨出該分割槽的文件系統 (ext2)。# 2. 搜尋一下,是否存在 stage1 這個資訊文件? grub> find /boot/grub/stage1(hd0,2) # 見鬼!怎么會只有一個!我們明明有 /boot/grub 與 /home/boot/grub 啊! # 因為 /boot 是獨立的,因此要找到該檔名就得要用如下的方式:grub> find /grub/stage1(hd0,0) # 這樣就能夠找到羅!要特別注意 grub 找到不是目錄樹,而是裝置內的文件。# 3. 搜尋一下是否可以找到核心? /boot/vmlinuz-2.6.18-92.el5 ? grub> find /boot/vmlinuz-2.6.18-92.el5 Error 15: File not found grub> find /vmlinuz-2.6.18-92.el5(hd0,0) # 再次強調,因為 /boot/ 是獨立的,因此就會變成上頭的模樣羅!# 4. 將主程序安裝上去吧!安裝到 MBR 看看! grub> setup (hd0)Checking if "/boot/grub/stage1" exists... no <==因為 /boot 是獨立的Checking if "/grub/stage1" exists... yes <==所以這個檔名才是對的!Checking if "/grub/stage2" exists... yesChecking if "/grub/e2fs_stage1_5" exists... yesRunning "embed /grub/e2fs_stage1_5 (hd0)"... 15 sectors are embedded. succeededRunning "install /grub/stage1 (hd0) (hd0)1+15 p (hd0,0)/grub/stage2 /grub/grub.conf"... succeeded <==將 stage1 程序安裝妥當羅! Done. # 很好!確實有裝起來~這樣 grub 就在 MBR 當中了!# 5. 那么重復安裝到我的 /dev/hda1 呢?亦即是 boot sector 當中? grub> setup (hd0,0)Checking if "/boot/grub/stage1" exists... noChecking if "/grub/stage1" exists... yesChecking if "/grub/stage2" exists... yesChecking if "/grub/e2fs_stage1_5" exists... yesRunning "embed /grub/e2fs_stage1_5 (hd0,0)"... failed (this is not fatal)Running "embed /grub/e2fs_stage1_5 (hd0,0)"... failed (this is not fatal)Running "install /grub/stage1 (hd0,0) /grub/stage2 p /grub/grub.conf "... succeeded Done. # 雖然無法將 stage1_5 安裝到 boot sector 去,不過,還不會有問題, # 重點是最后面那個 stage1 要安裝后,顯示 succeeded 字樣就可以了!grub> quit |
如此一來,就已經將 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 里面配置的東西嗎?沒錯!此時你還可以繼續進一步修改喔!注意看到上圖最底下的說明,你還可以使用:
- e:進入 grub shell 的編輯畫面;
- o:在光標所在行底下再新增一行;
- d:將光標所在行刪除。
我們說過, 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 這個文件,然后這樣搜尋:
| [root@www ~]# grep 'FRAMEBUFFER_CONSOLE' /boot/config-2.6.18-92.el5 CONFIG_FRAMEBUFFER_CONSOLE=y # 這個項目如果出現 y 那就是有支持啦!如果被注解或是 n ,那就是沒支持啦! |
那么如何調整 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 |
假設你想要將你的終端機螢幕解析度調整到 1024x768 ,且色彩深度為 15bit 色的時候,就得要指定 vga=790 那個數字!舉例來說,鳥哥的 tty1 就想要這樣的解析度時,你可以這樣做:
| [root@www ~]# vim /boot/grub/menu.lst ....(前面省略).... title CentOS (2.6.18-92.el5)root (hd0,0)kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet vga=790initrd /initrd-2.6.18-92.el5.img ....(后面省略).... |
重新啟動并選擇此菜單進入 Linux,你跑到 tty1 去看看,嘿嘿!就已經是 1024x768 的解析度羅!只是字會變的很小,但是畫面的范圍會加大就是了。不過,某些版本支持的是 16 進位制,所以還需要修改一下格式呢!一般使用上表當中的值應該就可以了。不過,由於不同的操作系統與硬件可能會有不一樣的情況,因此,上面的值不見得一定可以在您的機器上面測試成功,建議您可以分別配置看看哩~以找出可以使用的值! ^_^
BIOS 無法讀取大硬盤的問題
現今的硬盤容量越來越大,如果你使用舊的主板來安插大容量硬盤時,可能由於系統 BIOS 或者是其他問題,導致 BIOS 無法判斷該硬盤的容量,此時你的系統讀取可能會有問題。為什么呢?
我們在本章一開始的啟動流程講過,當進入 Linux 核心功能后,他會主動的再去偵測一下整個系統,因此 BIOS 捉不到的硬件在 Linux 核心反而可能會可以捉到而正常使用。舉例來說,過去很多朋友常常會發現,『我的系統使用 DVD 啟動安裝時,可以順利的安裝好 Linux ,但是第一次啟動時,螢幕只出現黑壓壓的一片,且出現 grub> 的字樣,而無法進入 Linux 系統中』,這又是怎么一回事?
- 在安裝的過程中,由於是使用 DVD 或 CD 啟動,因此加載 Linux 核心不成問題,而核心會去偵測系統硬件,因此可以捉到BIOS 捉不到的硬盤,此時你確實可以安裝 Linux 在大容量的硬盤上,且不會出現任何問題。
- 但是在進入硬盤啟動時,由於 kernel 與 initrd 文件都是透過 BIOS 的 INT 13 通道讀取的,因此你的 kernel 與 initrd 如果放置在 BIOS 無法判斷的磁區中,當然就無法被系統加載,而僅會出現 grub shell (grub>)等待你的處理而已。
更多 grub 錯誤的代碼查詢可以到底下的連結查閱:
- http://orgs.man.ac.uk/documentation/grub/grub_toc.html#SEC_Contents
現在你知道問題所在啦!那就是 BIOS 無法讀取大容量磁碟內的 kernel 與 initrd 文件。那如何解決呢?很簡單啦!就讓 kernel 與 initrd 文件放置在大硬盤的最前頭,由於 BIOS 至少可以讀到大磁碟的1024 磁柱內的數據,因此就能夠讀取核心與虛擬文件系統的文件羅。那如何讓 kernel 與 initrd 放置到整顆硬盤的最前面呢?簡單的要命吧!就創建 /boot 獨立分割槽,并將 /boot 放置到最前面即可!更多其他的解決方案可參考文后的延伸閱讀(注4)
萬一你已經安裝了 Linux 且發生了上述的問題,那該怎辦?你可以這樣作的:
- 最簡單的做法,就是直接重灌,并且制作出 /boot 掛載的 partition ,同時確認該 partition 是在 1024 cylinder 之前才行。
- 如果實在不想重灌,沒有關系,利用我們剛剛上頭提到的 grub 功能,額外創建一個可啟動軟盤,或者是直接以光驅啟動,然后以 grub 的編寫能力進入 Linux 。
- 另外的辦法其實是騙過 BIOS ,直接將硬盤的 cylinder, head, sector 等等資訊直接寫到BIOS 當中去,如此一來你的 BIOS 可能就可以讀得到與支持的到你的大硬盤了。
不過,鳥哥還是建議您可以重新安裝,并且制作出 /boot 這個 partition 啦! ^_^!這也是為啥這次更版中,鳥哥特別強調要分割出 /boot 這個分割槽的原因啊!
為個別菜單加上口令
想像一個環境,如果你管理的是一間計算機教室,這間計算機教室因為可對外開放,但是你又擔心某些 partition 被學生不小心的弄亂,因此你可能會想要將某些啟動菜單作個保護。這個時候,為每個菜單作個加密的口令就是個可行的方案啦!那如何在啟動的過程里面提供口令保護呢?首先,你必須要創建口令,而且還需要是加密過后的喔!否則人家跑到 /boot/grub/menu.lst 不就可以探查到你的啟動口令了?那如何創建加密的口令呢?我們可以透過 grub 提供的 md5 編碼來處理的,如下所示:
| [root@www ~]# grub-md5-crypt Password: <==輸入口令 Retype password: <==再輸入一次 $1$kvlI0/$byrbNgkt/.REKPQdfg287. <==這就是產生的 md5 口令! |
上面產生的最后一行,由 $ 開始到 . 結束的那行,就是你的口令經過 md5 編碼過后的咚咚!將這個口令復制下來吧!假設我們要將第一個選項加入這個口令,而第四個選項加入另外的口令,那你應該要這樣做:
| [root@www ~]# vim /boot/grub/menu.lst ....(前面省略).... title CentOS (2.6.18-92.el5)password --md5 $1$kvlI0/$byrbNgkt/.REKPQdfg287.root (hd0,0)kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet vga=790initrd /initrd-2.6.18-92.el5.img ....(中間省略).... title single user modepassword --md5 $1$GFnI0/$UuiZc/7snugLtVN4J/WyM/root (hd0,0)kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet singleinitrd /initrd-2.6.18-92.el5.img |
上表的案例中,我們兩個菜單進入的口令并不相同,可以進行同學的分類啦!不過這樣也造成一個問題,那就是一定要輸入口令才能夠進入啟動流程,如果你在遠程使用 reboot 重新啟動,并且主機前面并沒有任何人的話....你的主機并不會主動進入啟動程序喔! ^_^
你必須要注意的是:password 這個項目一定要在 title 底下的第一行。不過,此項功能還是可能被破解的,因為使用者可以透過編輯模式 (e) 進入菜單,并刪除口令欄位并按下 b 就能夠進行啟動流程了!真糟糕!那怎辦?只好透過整體的 password (放在所有的 title 之前) ,然后在 title 底下的第一行配置 lock ,那使用者想要編輯時,也得要輸入口令才行啊!配置有點像這樣:
| [root@www ~]# vim /boot/grub/menu.lst default=0 timeout=30 password --md5 $1$kvlI0/$byrbNgkt/.REKPQdfg287. <==放在整體配置處 splashimage=(hd0,0)/grub/splash.xpm.gz #hiddenmenu title CentOS (2.6.18-92.el5)lock <==多了鎖死的功能root (hd0,0)kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet vga=790initrd /initrd-2.6.18-92.el5.img |
那么重新啟動后,畫面會像這樣:
圖 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 來救援的。整個動作有點像這樣:
| grub edit> kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/ rhgb quiet single |
init 配置檔錯誤
前一個 root 口令挽救的方法其實可以用在很多地方,唯一一個無法挽救的情況,那就是 /etc/inittab 這個文件配置錯誤導致的無法啟動!根據啟動流程,我們知道 runlevel 0~6 都會讀取 /etc/inittab 配置檔,因此你使用 single mode (runlevel 1) 當然也是要讀取 /etc/inittab 來進行啟動的。那既然無法進入單人維護模式,就表示這題無解羅?非也非也,既然默認的 init 無法運行,那我們就告訴核心不要運行 init ,改呼叫 bash 啊!可以略過 init 嗎?可以的,同樣在啟動進入 grub 后,同樣在 grub edit 的情況下這樣做:
| grub edit> kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/ rhgb quiet init=/bin/bash |
因為我們指定了核心呼叫的第一支程序 (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 磁碟代號的對應喔!舉例來說,鳥哥的這個文件內容如下:
| [root@www ~]# cat /boot/grub/device.map (fd0) /dev/fd0 (hd0) /dev/hda |
如果你不清楚如何處理的話,也可以利用 grub-install 的功能喔!例如:
| [root@www ~]# grub-install --recheck /dev/hda1 |
這樣 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 來切換,以處理你的硬盤問題啊!那怎么做啊?粉簡單啦!
掛載點 裝置檔名/ → /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
重點回顧
- Linux 不可隨意關機,否則容易造成文件系統錯亂或者是其他無法啟動的問題;
- 啟動流程主要是:BIOS、MBR、Loader、kernel+initrd、/sbin/init 等流程
- Loader 具有提供菜單、加載核心文件、轉交控制權給其他 loader 等功能。
- boot loader 可以安裝在 MBR 或者是每個分割槽的 boot sector 區域中
- initrd 可以提供核心在啟動過程中所需要的最重要的模塊,通常與磁碟及文件系統有關的模塊;
- init 的配置檔為 /etc/inittab ,此文件內容可以配置默認 runlevel、系統初始化腳本、不同運行等級的服務啟動等;
- 額外的裝置與模塊對應,可寫入 /etc/modprobe.conf 中;
- 核心模塊的管理可使用 lsmod, modinfo, rmmod, insmod, modprobe 等命令;
- modprobe 主要參考 /lib/modules/$(uanem -r)/modules.dep 的配置來加載與卸載核心模塊;
- grub 的配置檔與相關文件系統定義檔大多放置於 /boot/grub 目錄中,配置檔名為 menu.lst
- grub 對磁碟的代號配置與 Linux 不同,主要透過偵測的順序來給予配置。如 (hd0) 及 (hd0,0) 等。
- menu.lst 內每個菜單與 titile 有關,而直接指定核心啟動時,至少需要 kernel 及 initrd 兩個項目
- menu.lst 內配置 loader 控制權移交時,最重要者為 chainloader +1 這個項目。
- 若想要重建 initrd ,可使用 mkinitrd 處理
- 重新安裝 grub 到 MBR 或 boot sector 時,可以利用 grub shell 來處理。
- 若想要進入救援模式,可於啟動菜單過程中,在 kernel 的項目后面加入『 single 』或『 init=/bin/bash 』等方式來進入救援模式。
- 我們可以對 grub 的個別菜單給予不同的口令。
本章習題
( 要看答案請將鼠標移動到『答:』底下的空白處,按下左鍵圈選空白處即可察看 )
- 情境模擬題一:利用救援光盤來處理系統的錯誤導致無法啟動的問題。
- 目標:了解救援光盤的功能;
- 前提:了解 grub 的原理,并且知道如何使用 chroot 功能;
- 需求:打字可以再加快一點啊! ^_^
這個部分鳥哥就不捉圖了,請大家自行處理羅~假設你的系統出問題而無法順利啟動,此時拿出原版光盤,然后重新以光盤來啟動你的系統。然后你應該要這樣作的:
- 利用光盤啟動時,到了看到 boot: 的階段,按下 [F5] 之后會看到可以輸入的選項,此時請輸入:
就能夠進入救援模式的偵測了!boot: linux rescue
- 然后請選擇語系與鍵盤對應,這個與安裝過程是一模一樣啦!所以選擇『 English』與『 us 』即可!
- 接下來會問你是否需要啟動網絡,因為我們的系統是出問題要處理,所以不需要啟動網絡啦!選擇『No』即可;
- 然后就進入救援光盤模式的文件系統搜尋了!這個救援光盤會去找出目前你的主機里面與 CentOS 5.x 相關的操作系統,并將該操作系統匯整成為一個 chroot 的環境等待你的處置!但是他會有三個模式可以選擇,分別是『continue』繼續成為可讀寫掛載;『Read-Only』將偵測到的操作系統變成唯讀掛載;『Skip』略過這次的救援動作。在這里我們選擇『 Continue 』吧!
- 然后系統會將偵測到的資訊通知你!一般來說,可能會在螢幕上顯示類似這樣的信息:『 chroot /mnt/sysimage』此時請按下 OK 吧!
- 按下 OK 后,系統會丟給你一個 shell 使用,先用 df 看一下掛載情況是否正確?若不正確請手動掛載其他未被掛載的 partition 。等到一切搞定后,利用 chroot /mnt/sysimage來轉成你原本的操作系統環境吧!等到你將一切出問題的地方都搞定,請 reboot 系統,且取出光盤,用硬盤啟動吧!
簡答題部分:
- 如何察看與修改 runlevel 呢? 察看很簡單,只要輸入『 runlevel 』就可以得知。而如果要修改目前的 runlevel ,可以直接輸入 init [level] 例如要去到 runlevel 3 可以:『 init 3 』即可。如果想要每次啟動都配置固定的 runlevel ,那么可以修改 /etc/inittab 這個文件!將里面這一行改成:『id:3:initdefault:』即可。
- 我有個朋友跟我說,他想要讓一個程序在 Linux 系統下一啟動就啟動,但是在關機前會自動的先結束該程序,我該怎么建議他? 由於 /etc/rc.d/rc[0-6].d 里面有的 Sxxname 與Kxxname 可以配置啟動啟動與關機結束的事項!所以我就可以輕易的寫一個 script放在 /etc/rc.d/init.d 里面,并連結到我的 run-level 里頭,就可以讓他自由自在的啟動與結束了!
- 萬一不幸,我的一些模塊沒有辦法讓 Linux 的核心捉到,但是偏偏這個核心明明就有支持該模塊,我要讓該模塊在啟動的時候就被加載,那么應該寫入那個文件? 應該寫入 /etc/modprobe.conf (kernel 2.6.x) 或者是 /etc/modules.conf (kernel 2.4.x) 這個文件,他是模塊加載相關的地方呢!當然,也可以寫入 /etc/sysconfig/modules/* 里面。
- 如何在 grub 啟動過程當中,指定以『 run level 1 』來啟動? 在啟動進入 boot loader 之后,利用 grub shell 的功能,亦即輸入『 e 』進入編輯模式,然后在 kernel 后面添加:
kernel (hd0,0)/boot/vmlinuz ro root=/dev/hda1 .... single
那個 single 也可以改成 1 ,就能夠進入。同樣的,若使用 lilo 時,按下 tab 按鍵后,輸入
label_name -s
就能夠進入 run level 1 羅! - 由於一些無心之過,導致系統啟動時,只要運行 init 就會產生錯誤而無法繼續啟動,我們知道可以在啟動的時候,不要以 init 加載系統,可以轉換第一支運行程序,假設我第一支運行程序想要改為 /bin/bash ,好讓我自行維護系統(不同於 run level 1 喔!),該如何進行此一工作? 在啟動的過程當中,進入 lilo 或 grub 的畫面后,在 kernel 的參數環境下,加入 init=/bin/bash來取代 /sbin/init ,則可略過 init 與 /etc/inittab 的配置項目,不過,您必須相當熟悉 grub 與 lilo 的配置才行喔! ^_^
- 在 CentOS 當中,我們如何自動可加載的模塊? 可以經由配置 /etc/modprobe.conf 或者是將自行做好的配置檔寫入到 /etc/sysconfig/modules/ 目錄中,并且將檔名取為 filename.modules ,注意喔,文件結果務必是 .modules 才行。相關資訊可以參考 /etc/rc.d/rc.sysinit 喔!
- 如果你不小心先安裝 Linux 再安裝 Windows 導致 boot loader 無法找到 Linux 的啟動菜單,該如何挽救?
方法有很多,例如:
(1)藉助第三方軟件,安裝類似 spfdisk 的軟件在 MBR 里面,因為他同時認識 Linux 與 Windows ,所以就可以用他來進入 Linux 啦!
(2)或者使用類似 KNOPPIX 的 Live CD 以光盤啟動進入 Linux 之后,再以 chroot 軟件切換根目錄 (/),然后重新安裝 grub 等 boot loader ,同樣也可以重新讓兩個操作系統存在啦!
總之,只要你知道 MBR / Super block / boot loader 之間的相關性,怎么切換都可能啊! ^_^
參考數據與延伸閱讀
- 注1:BIOS 的 POST 功能解釋:http://en.wikipedia.org/wiki/Power-on_self-test
- 注2:BIOS 的 INT 13 硬件中斷解釋:http://en.wikipedia.org/wiki/INT_13
- 注3:關於 splash 的相關說明:http://ruslug.rutgers.edu/~mcgrof/grub-images/
- 注4:一些 grub 出錯時的解決之道:
http://wiki.linuxquestions.org/wiki/GRUB_boot_menu
http://forums.gentoo.org/viewtopic.php?t=122656&highlight=grub+error+collection - info grub
- GNU 官方網站關於 grub 的說明文件:
http://www.gnu.org/software/grub/manual/html_node/ - 純文字螢幕解析度的修改方法:
http://phorum.study-area.org/viewtopic.php?t=14776
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 兄的建議,修改了一些地方!詳情請參考討論區建議!
出處:http://vbird.dic.ksu.edu.tw/linux_basic/0510osloader.php
總結
以上是生活随笔為你收集整理的鸟哥的Linux私房菜(基础篇)- 第二十章、启动流程、模块管理与 Loader的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 鸟哥的Linux私房菜(基础篇)- 第十
- 下一篇: 鸟哥的Linux私房菜(基础篇)- 第二