2009年1月13日 星期二

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 啦! ^_^