Linux 基礎學習篇 - Fedora Core 4

第十八章、開機關機流程與 Loader - for Fedora Core 4

整個 Linux 系統下的開關機流程介紹,以及開機管理軟體的介紹

最近更新時間: 2007/06/27

本文資料主要針對 Fedora Core 4 的系統進行說明, Fedora Core 1 主要是由 Red Hat Linux 9 改版而來, 這個 Red Hat Linux 9 並不是當前大家聽到的 RHEL 喔!那是在 RHEL 出現之前的產品,基本上是在 2003 年以前的作品了!Fedora Core 4 則是在 2005 年 6 月份釋出,使用的核心是 2.6.11 版,當時是很紅的一個作品!只是生命週期太短,所以用這個 Fedora 系列來介紹 Server, 當時的決定確實有點莫名其妙了...

建議您前往本站查詢最新版本的 Linux distribution 文章來閱讀,比較不會浪費時間。那為何還需要編輯 Fedora Core 4 的資料呢? 鳥哥只想要做個自己曾經撰寫過的文件內容保存而已囉! ^_^!最新文章請前往鳥站首頁查閱囉!

在這個章節當中,我們特別要來看一看整個開機的流程設定, 看看能不能在開機的時候就主動的幫我們將所需要的資訊都填進去!此外,還想要知道一下, 我們要如何來設定多重開機呢?設定多重開機的原理是什麼?最重要的是那個『什麼是開機管理程式 ( boot loader ) 呢?』這些東西對於家裡只有一部電腦,卻又要安裝多個作業系統的朋友來說, 是相當重要而有趣的項目呢!鳥哥底下會介紹 Linux 下的兩套相當棒的 boot loader 系統,分別是 lilo 及 grub。

開機流程簡介

開機不是只要按一下電源鈕而關機只要關掉電源鈕就可以了嗎?有何大學問?話是這樣沒錯啦,但是由於 Linux 是一套多人多工的作業系統,你難保你在關機時沒有人在線上,如果你關機的時候碰巧一大群人在線上工作, 那會讓當時在線上工作的人馬上斷線的!那不是害死人了!一些資料可是無價之寶哩!

另外,與 DOS 環境不同的是, Linux 在執行的時候,雖然你在畫面上只會看到黑壓壓的一片,完全沒有任何畫面, 但其實他是有很多的程式在背景底下執行的,例如登錄檔管控程式、前面兩章提到的例行性命令, 當然還有一大堆網路服務,如郵件伺服器、WWW伺服器等等。你如果隨便關機的話, 是很容易傷害硬碟及資料傳輸的動作的!所以在 Linux 下關機可是一門大學問喔。

既然開機是很嚴肅的一件事,呵呵,那我們來瞭解一下整個開機的過程吧! 好讓大家比較容易發現開機過程裡面發生錯誤的地方,與解決之道!不過,由於開機的過程中,那個開機管理程式 ( Boot Loader ) 使用的軟體可能不一樣,例如目前各大 Linux distributions 的主流為 grub, 但早期 Linux 預設是使用 LILO ,台灣地區則很多朋友喜歡使用 spfdisk 。 但無論如何,我們總是得要瞭解整個 boot loader 的工作情況,才能瞭解為何進行多重開機的設定時, 為何老是聽人家講要先安裝 Windows 再安裝 Linux 的原因~

我們先來想一想, Linux 整個開機的程序是怎樣呢?還記得我們提過,開機時要載入核心, 讓核心來驅動整個硬體,這樣才能算是一個最陽春、最基礎的作業系統吧?然後才能夠執行各種程式的運作。 同樣的,開機的流程也是需要先載入核心的。不過,載入核心前,卻需要一些前置作業,才能夠正確無誤的載入核心嘛! 所以,整個開機的程序是這樣的:
  1. 載入 BIOS 的硬體資訊,並取得第一個開機裝置的代號;
  2. 讀取第一個開機裝置的 MBR 的 boot Loader (亦即是 lilo, grub, spfdisk 等等) 的開機資訊;
  3. 載入 Kernel 作業系統核心資訊, Kernel 開始解壓縮,並且嘗試驅動所有硬體裝置;
  4. Kernel 執行 init 程式並取得 run-level 資訊;
  5. init 執行 /etc/rc.d/rc.sysinit 檔案;
  6. 啟動核心的外掛模組 (/etc/modprobe.conf);
  7. init 執行 run-level 的各個批次檔( Scripts );
  8. init 執行 /etc/rc.d/rc.local 檔案;
  9. 執行 /bin/login 程式,並等待使用者登入;
  10. 登入之後開始以 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 及核心載入流程示意圖
圖一、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 主要的工作大抵有這幾項:
  1. 取得網路環境與主機類型:
    首先讀取網路設定檔 /etc/sysconfig/network ,取得主機名稱與預設通訊閘 (gateway) 等網路環境。
  2. 測試與掛載記憶體裝置 /proc 及 USB 裝置 /sys:
    除掛載記憶體裝置 /proc 之外,還會主動偵測系統上是否具有 usb 的裝置, 若有則會主動載入 usb 的驅動程式,並且嘗試掛載 usb 的檔案系統。
  3. 決定是否啟動 SELinux :
    近期以來,很多 distributions 都加入了美國國家安全局發展的 Security Enhance Linux 套件, 這個 SELinux 可以更加強化 Linux 操作環境的安全性,不過,由於安全掛帥, 對於新手來說,不是很容易上手。因此,我們才會建議大家先不要啟動啊。無論如何, 在這個階段我們可以分析 SELinux 是否要啟動。
  4. 周邊設備的偵測與 Plug and Play (PnP) 參數的測試:
    根據核心在開機時偵測的結果 (/proc/sys/kernel/modprobe ) 開始進行 ide / scsi / 網路 / 音效 等周邊設備的偵測,以及利用以載入的核心模組進行 PnP 裝置的參數測試。
  5. 使用者自訂模組的載入
    使用者可以在 /etc/sysconfig/modules/*.modules 加入自訂的模組, 則此時會被載入到系統當中喔!
  6. 載入核心的相關設定:
    系統會主動去讀取 /etc/sysctl.conf 這個檔案的設定值,使核心功能成為我們想要的樣子。
  7. 設定系統時間 (clock):
  8. 設定終端機 (console) 字形:
  9. 設定 RAID 與 LVM 等硬碟功能:
  10. 以 fsck 檢驗磁碟檔案系統:
  11. 進行磁碟配額 quota 的轉換 (非必要):
  12. 重新以可讀取模式掛載系統磁碟:
  13. 啟動 quota 功能:
  14. 啟動系統亂數裝置 (產生亂數功能):
  15. 清除開機過程當中的暫存檔案:
  16. 將開機相關資訊載入 /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 的設定,我們可以說:
    1. 要每次開機都執行某個預設的 run level ,則需要修改 /etc/inittab 內的設定項目, 亦即是『 id:3:initdefault: 』裡頭的數字啊;

    2. 如果僅只是暫時變更系統的 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: Grub

    在看完了前面的整個開機流程,以及核心模組的整理之後,你應該會發現到一件事情, 那就是『 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 磁碟代號可完全是不同的! 他的代號有點像:
      (hd0,0)
    夠神了吧?跟 /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 要如何寫?
    答:
      只要列出 kernel 的檔名即可!因為我將 /boot 獨立成為 /dev/hda2 ,因此,整個核心檔案檔名應該是:

      /boot/vmlinuz-2.6.11-1.369FC4 -->
      (/dev/hda2)/vmlinuz-2.6.11-1.1369_FC4 -->
      (hd0,1)/vmlinuz-2.6.11-1.1369_FC4

      因為 /boot 是一個完整的 partition 嘛!所以說,整個核心檔案的寫法,可以這樣做:
      title FC4 default
          kernel (hd0,1)/vmlinuz-2.6.11-1.1369_FC4 ro root=/dev/hda1

    因為 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/.... 內的核心模組, 這樣才能夠開機完成。簡單的流程如下所示:
    1. 讀取 BIOS 設定,取得開機裝置與主機板晶片等資訊;
    2. 讀取 MBR 內的開機載入器 (loader),並透過主機的 INT 13 硬體功能讀取核心檔案
    3. 核心解壓縮並且偵測硬體
    4. 掛載根目錄,視需要載入 /lib/modules/`uname -r`/... 內的核心模組
    5. 開始執行 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 的開機圖示
    圖二、 grub 的開機圖示

    帥吧!鳥哥的主機上面竟然有七個可開機的選單呢!當然啦!要看到這樣的選單,你必須要在開機的過程中, 五秒內就得要按下任意鍵,否則就會進入到正常的開機程序當中了。 這個時候,注意看到上圖當中的最底下的一些文字說明,其實,我們可以進行線上編修喔! 在圖二當中,如果我在第一個開機選單當中按下『 e 』這個按鍵,就會進入 grub shell 的修改, 有點像底下這樣:

    grub 的編修畫面
    圖三、 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 的解析度與色彩度 』啦! 他的十進位代碼與相對應的解析度與彩度為:

    彩度\解析度640x480800x6001024x7681280x1024bit
    2567697717737758 bit
    3276878478779079315 bit
    6553678578879179416 bit
    16.8M78678979279532 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 啦! ^_^

    Boot Loader: LILO

    說實在的,整個開機以 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 )的硬碟之中,解決的方法可以如下:

      1. 用 Linux 光碟開機,然後在出現 boot: 處輸入『 linux root=/dev/hda1 (這個與你的 Linux 安裝的 partition 有關)』 順利開機之後,以 vi 修改 /etc/lilo.conf 將『linear』 這一行取消(如果沒有這一行的話,那就在 lilo.conf 中加入吧!)然後執行 『lilo』重新安裝 Lilo, 再取出光碟並重新開機試試看;
      2. 進入 BIOS ,將硬碟的 mode 改成 LBA 試看看;
      3. 將Linux往前面一點的磁區安裝,例如你可能安裝在 /etc/hdc1 ,那你可以重新安裝 Linux 在 /dev/hda2 試看看

    • 安裝Linux完成之後,卻是出現 010101... 等數字在螢幕上,無法進入 Linux ...

      這個問題的發生很有可能是硬碟出了問題了!這個時候可以使用 fsck 來掃瞄囉!

      1. 用軟碟或者是光碟開機後,使用fsck這個硬碟修正軟體掃瞄一下您的 root partition ,例如:fsck /dev/hda1
      2. 進入 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 是不需要密碼的。 整個動作有點像這樣:
    1. 在開機的時候,到達選單時,我們以較常見的 grub 作為介紹。出現選單後, 將光棒移動到要開機的那個項目上面,然後按下『 e 』進入細項設定,選擇『 kernel 』那一項, 再按『 e 』進入編修畫面,在最後面加上一個單一的『 1 』(數字 1, 2, 3 的 1 啊!), 按下 [Esc] 按鍵,然後按下『 b 』,就能夠以該 kernel 進入 run level 1 了。

    2. 進入 Linux 後,不需要輸入密碼,直接就會是 root 的身份,立刻 vi /etc/shadow , 將 root 所在那一行的第二個欄位給他全部抹除,儲存後離開,然後『 reboot 』重新開機。

    3. 由於 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 來切換, 以處理你的硬碟問題啊!那怎麼做啊?粉簡單啦!
    1. 用盡任何方法,進入一個完整的 Linux 系統 ( run level 3 或 5 );
    2. 假設有問題的 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 的環境啦!這樣說明,瞭了嗎? ^_^

    參考資料

    本章習題練習

    ( 要看答案請將滑鼠移動到『答:』底下的空白處,按下左鍵圈選空白處即可察看 )
    • 如何察看與修改 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 的設定才行喔! ^_^
    • 在 FC4 當中,我們如何自動可載入的模組?
    • 可以經由設定 /etc/modprobe.conf 或者是將自行做好的設定檔寫入到 /etc/sysconfig/modules/ 目錄中, 並且將檔名取為 filename.modules ,注意喔,檔案結果務必是 .modules 才行。 相關資訊可以參考 /etc/rc.d/rc.sysinit 喔!
    修改歷史:
    • 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 的說明,請參考這裡
    伺服器篇文件
    各版本彙整說明
    CentOS 6.x