動手學 grub (0.97)


[2015 年的今天, grub 0.97 已經改稱為 grub-legacy, 幾乎要被淘汰掉了。 我製作的 finnix-ckhung15c 還有收納; 新版大概就不會放進去了。 現在大部分時候我改用 extlinux; 有必要的時候就拿出最強大的 grub2。]

本主題的討論版

術語

一部 Linux 電腦開機時, 大概要經過下列程序:

  1. BIOS 根據 boot priority 的設定, 挑選某顆硬碟或隨身碟
  2. 這顆碟的 MBR (Master Boot Record)
  3. 開機管理程式 boot loader
  4. 使用者從選單挑一個作業系統
  5. 開機管理員載入 Linux 核心 (通常檔名類似 vmlinuz) 及初始的檔案系統 (通常檔名類似 initrd.gz)
  6. 將根目錄切換至某個分割, 進入正常系統

常用的 boot loader 有 lilo, syslinux, 及 grub。 不論採用那個 boot loader, 當然都要寫一個設定檔 (lilo.conf, syslinux.cfg, 或 menu.lst) 將來成為開機時的選單。 開機管理程式特別之處有兩點。 首先, 它必須佔據 MBR, 才有機會搶到主控權。 所以任何 boot loader 都有一個 「安裝」 的動作, 做完之後, 你原來的 MBR 就被蓋掉了。 如果因此而無法開機進入自己熟悉的作業系統, 不要緊張, 其實資料都還在, 只是 MBR 指錯地方而已。 把設定檔改好, 重裝一次 boot loader 即可。 萬不得已, 也可以將舊的 MBR 還原: 在 dos 底下用 fdisk /mbr 或在 Linux 底下用 lilo -u /dev/sdz 不過把 grub 裝好才是正途啦。 第二, boot loader 起來的時候, 連作業系統都還沒起來, 它如何認得檔案系統呢? (設定檔裡面所指定的路徑, 它如何翻譯成硬碟的 c/h/s 代碼呢?) 詳見 這篇文章 所以 lilo 的設定檔每次修改過後, 或是它所指定的檔案曾經被刪除又拷貝回來之後, 都必須重新安裝一次 lilo。 但是 grub 因為自己本身就認得多種檔案系統, 所以沒有這個煩惱。

總之, 結論就是: (1) 個人推薦 grub (2) boot loader 不屬於任何作業系統, 建議不要把它放在某個作業系統的分割, 而是放在純粹資料的分割。

切割

以下說明如何在一個 512MB 的隨身碟上面安裝 ttylinux (8.0 版解壓後約 16MB), Damn Small Linux (約 50MB), slax (約 192MB; 加上中文模組後約 260MB) 等數個版本的 Linux 藉此解說開機管理員 grub 的一些重要觀念。 以下的說明, 假設在 ubuntu 7.10 底下工作。 (本講義的最早版本, 在 mandriva 2006 底下測試, 所以在新的 mandriva 可能也不會差太多。)

首先瞭解一下 硬碟分割的觀念usb 開機的基本觀念, 本文採用的是 "CD 式" 安裝法。

先用 fdisk 將隨身碟切割如下:

  1. 第一分割: 主分割區, 將它的 type 設為 win95 fat32 分割。 之後將之格式化為 vfat。 這樣 windows 也可使用此分割, 可作為正常的隨身碟儲存資料的空間。 如果空間夠的話, 建議在此分割放 pietty, winscp 與 windows 版的 vnc 以便可以從任何 Windows 機器遠端登入自己的主機並傳檔。 也建議挑一套 portable apps 放上去。 使用跨平臺的自由軟體, 不論在任何作業系統都可以無入而不自得。
  2. 第二分割: 延申分割區。 進一步切出: 第五分割, 60MB, 放 dsl; 第六分割, 300MB, 放 slax。
  3. 第四分割: 主分割區, 24MB, 將它的 type 設為 linux 分割。 之後將之格式化為 ext2。 這裡要放 grub 及 ttylinux。 如此安排, 是希望掌管開機的最重要部分不受打擾, 不論其他分割如何受到破壞, 至少最難製作的開機部分還是可正常進入一個精簡版的 linux。

注意: (1) 隨身碟上不建議採用 ext3 (超慢) (2) grub 0.97 只認得最舊的 ext2 (inode 大小 128); 但很較新的 mkfs.ext2 預設值為 inode 大小 256, 所以建立檔案系統時, 記得要用: mkfs -t ext2 -I 128...

最後在 fdisk 裡面, 下 "p" 查看, 應該得到類似下面的結果:

	所用裝置 Boot      Start         End      Blocks   Id  System
	/dev/sdz1               1          11       88326   83  Linux
	/dev/sdz2              12         118      401561+   5  延伸的
	/dev/sdz4              58          60       24097+  83  Linux
	/dev/sdz5              12          20       72261   83  Linux
	/dev/sdz6              21          58      305203+  83  Linux

安裝 grub

把 grub 裝到 usb 碟之前, 最重要的是弄清楚 grub 怎麼稱呼你的 usb 碟。 對於熟悉 Linux 的人來說, IDE 硬碟及光碟是 /dev/hda /dev/hdb 等等; 而 SCSI 硬碟或 usb 裝置則是 /dev/sda /dev/sdb 等等。 但 grub 服務的對象不只是 Linux, 還包含 *BSD。 它稱呼硬碟為 (hd0) (hd1) 等等。 以下假設您已將 /dev/sdz4 掛載在 /mnt/sdz4 底下。

首先要先在 /mnt/sdz4 的某個目錄上 (就根目錄吧) 建立一個怪怪的, 從來沒用過的檔名, 例如叫做 x9k3j8m 好了。 進 grub 之後下指令 find /x9k3j8m (必須打 「相對於 usb 碟的完整路徑」) 於是 grub 到接上本電腦的所有儲存裝置的每個分割上, find 所指定的完整路徑, 逐一去找這個檔案, 然後印出它在何處找到, 例如 (hd26,0)。 最後打 quit 回到 shell 底下。

另一個方法更簡單: rm -f device.map ; echo | grub --batch --device-map=device.map 這樣不必進入 grub, 它會直接在目前目錄下, 產生一個對照表, 檔名如我們在命令列上指定的, 叫做 device.map。 注意: 一定要先刪除舊的 device.map, 不然會變成要求 grub 不分清紅皂白就以 (可能是錯的) device.map 來做事。 (結果什麼事都沒做, device.map 也沒改變。) 這裡面應該有一列長得像這樣:

    (hd26)   /dev/sdz

知道兩種稱呼方式在您機器上的對照之後, 安裝 grub 就很簡單了, 只要一句話: grub-install --root-directory=/mnt/sdz4 '(hd26)' 注意要拿掉 (hd26,0) 後面的 ",0" 不然 grub 會裝到一個分割的開頭, 而不是整顆隨身碟的開頭。 順便提醒: 這樣你安裝的 grub 是工作版 (例如上述的 mandriva 2006) 裡面的 grub, 而不是標的版 (例如 DSL 或 slax) 的 grub。 請注意 /mnt/sdz4 底下應該會多出一個 /boot/grub 目錄。 這就是安裝的部分成果; 至於安裝在 MBR 的那一部分, 沒有辦法直接檢視是否成功, 必須重新開機才知道。

測試空的 grub

事實上, 如果您的系統裝有 qemu 模擬器, 可以不必重開機, 直接這樣測試: qemu -usb /dev/sdz

不然, 就只好插好 usb 碟, 乖乖重新開機, 進入 BIOS 指定要從 usb 碟開機。 有些 BIOS 把 usb 碟歸類在 usb 裝置; 但更常見的是: 在硬碟的選單下才會看到你的 usb 碟。 儲存 BIOS 設定, 重新開機, ... 緊張一刻來了。 如果出現類似 grub> 的命令提示符號, 那麼恭喜你! 最難除錯的步驟已經通過! 請回到工作環境底下, 繼續較容易除錯的部分。 如果沒有提示符號... 那就有點糟糕了, 很可能是上述 '(hd26)' 參數給錯, 而且可能已經把不該動到的硬碟的 MBR 給攻佔下來了... 沒關係, 一不做二不休, 就乾脆改用 grub 來管理那顆硬碟吧。 不過請先專心把 usb 開機做完, 然後你自然會知道如何處理那顆被意外動到的硬碟。 (查看 grub 手冊, 或 google "grub boot windows" 之類的關鍵字)

另一方面, 在設定檔裡面, grub 一律以 (hd0) 稱呼 usb 碟, 因為將來做好以後, 當你以 usb 碟開機時, grub 被 BIOS 叫起來, 最先看到的當然就是他自己所在的 usb 碟, 所以就給它最前面的代號。 請把 menu.lst 貼到隨身上剛安裝完的 grub 目錄 (應該在 /boot/grub 底下)。 現在可以再次重開機, 測試 「有選單的 grub」, 應該出現文字模式的開機選單, 不再是令人不知所措的命令列。 當然, 因為尚未複製 iso 檔上面的資料, 自然無法開機; 但至少開機選單出現, 剩下來的步驟就簡單了。

從光碟上複製檔案

ttylinux 網站 下載 bootcd-i486-7.0.iso.gz (注意: 是光碟版), 解壓縮, 掛載映象檔, 最後拷貝進去:

        gunzip bootcd-i486-7.0.iso.gz
        mount -o loop /mnt/ttylinux bootcd-i486-7.0.iso
        cd /mnt/ttylinux
        mkdir /mnt/sdz4/boot/ttylinux
        cp -a . /mnt/sdz4/boot/ttylinux
        cd -
        umount /mnt/ttylinux

這裡假設 grub 的相關檔案已先裝入 /dev/sdz4 且 /dev/sdz4 已掛載在 /mnt/sdz4 底下, 所以已有一個 boot 子目錄。 為了避免真的燒一張光碟, 所以用 -o loop 掛載; 詳見 loop file system。 注意: 不要用 cp -a /mnt/ttylinux/* /mnt/sdz4 之類的指令, 因為這樣會漏掉隱藏檔。 最後, 必須離開 /mnt/ttylinux 子目錄, 才能將它卸載下來。

如果重開機或用 qemu 測試, 可以正常進入 ttylinux 的話, 就恭喜成功了! 登入的帳號密碼都是 root; 可用 halt 關機, 或直接暴力關機, 反正它沒去動您的硬碟。

到這裡, 這已是一顆可開機的隨身碟。 以後要安裝其他版本 (例如 dsl 或 slax), 或其他分割被破壞, 也都不會影響到 grub 及 ttylinux。 以後安裝其他版本, 只需要 (1) 拷貝檔案 (2) 修改 boot/grub/menu.lst 就可以了, 不再需要動到開機管理員。

更多設定

如何把其他光碟片放進隨身碟呢? 詳見 這篇。 這裡面也提到如何把 dsl 與 slax 放在同一分割的不同子目錄裡面; 還有如何修改背景圖片 (14 色)。 但如果你的 grub 0.97 是 gfxboot 版, 那麼 修改背景圖會稍微麻煩一點, 但可以享用 255 色。

參考資料

  1. Making a USB Stick bootable with Grub
  2. Getting started with GRUB