2015年6月7日 星期日

grub2: 開機光碟蒐集狂人的環保袋

用一顆隨身碟取代眾多開機光碟 貴哥有蒐集 linux 開機光碟的癖好; 可是我又不想真的燒一堆光碟片。 可以把很多張光碟的映像檔都擠在同一顆開機隨身碟上面嗎? 很不幸地 , 我比較熟悉的 extlinux grub legacy 這兩個開機管理員都無法直接開啟光碟映像檔 (除非那張光碟有特殊設計) 而且 extlinux 甚至無法開啟別的分割 (跟 extlinux 安裝目錄位於不同分割) 上面的檔案, 至於 grub legacy 又快被淘汰掉了... 還好有 grub2 可以解決上述所有問題!

其實我一直很不想學 grub2 ( 根本是學了很多次都學不起來 因為 grub2 的複雜設計真的很令人無言)。 我需要的基本功能有: (1) 啟動 iso 映像檔 (以及其他一般的 linux 正常開機) (2) 相關檔案可能放在別的分割上 (3) 相關檔案可能放在 lvm 上 (4) 要有美美的背景圖。 我要的不多, 就只有這樣而已, 可以跳過官方建議的 update-grub 複雜機制嗎? 這一篇示範 「直接手動編輯 (本來應該是由 update-grub 所產生的) grub.cfg 設定檔」 的非標準方式來設定 grub2。

首先, 我的 32G 隨身碟切成這樣:

所用裝置 開機      開始         結束      區塊   識別號  系統
/dev/sdx1   *        2048     8390655     4194304    c  W95 FAT32 (LBA)
/dev/sdx2         8390656    10029055      819200   83  Linux
/dev/sdx3        10029056    11667455      819200   83  Linux
/dev/sdx4        11667456    64757759    26545152   8e  Linux LVM

其中 /dev/sdx4 做成 lvm 分割, 它的 volume group 名為 vfnb, 上面有一個名為 isopool 的 volume。 你也可以省略 lvm, 直接改用 primary partition 或 logical partition 比較簡單。 以下的範例假設你放了一個 finnix-ckhung15c.iso 在 /dev/sdx3 上面, 又放了一個 bodhi-3.0.0-32.iso 在 lvm 的 vfnb 群組的 isopool 分割上。 ( bodhi linux 是 「採用 enlightenment 視窗環境」 的 ubuntu。 我還在測試。)

首先把 grub 管理員的程式碼給裝進隨身碟去:

mount /dev/sdx1 /mnt/t1
mkdir /mnt/t1/boot
grub-install --no-floppy --boot-directory=/mnt/t1/boot /dev/sdx

如上, 真正安裝的指令是 grub-install。 你用 --boot-directory 指定要裝到哪個分割的哪個子目錄底下。 然後它會在裡面再建一個 grub 子目錄。 也請用 grub-install -V 查看並記下你的 grub 版本。 如果開機隨身碟製作失敗, 未來要上網求助時, 一定要提供這個資訊, 因為不同版本的設定指令可能略有差異。 本文操作的環境是 bodhi 3.0.0, grub 版本是 2.02~beta2-9。

再來, 把一個 jpg 或 png 檔放到你的開機分割的 /boot/grub 底下, 比方叫做 autumn.jpg 好了。 根據 這一篇 圖檔不可以是 indexed 格式, 且 jpg 檔只能有 256 色。 建議先安裝 grub2-splashimages 套件, 拿 「確定 ok」 的檔案測式, 成功後再換你自己的圖。 我的 (不太豐富的) 經驗是: 如果有一張失敗的 fail.jpg, 可以用 (來自 imagemagick 套件的指令) convert fail.jpg success.jpg ; convert -colors 255 success.jpg success.jpg 轉出來的 success.jpg 可能就 ok 了。

然後把 grub.cfg 範例檔複製到你的 /mnt/t1/boot/grub 子目錄, 並加以修改。 最主要就是修改:

  1. background_image /boot/grub/autumn.jpg 圖片的路徑及檔名。
  2. set root 指定 iso 檔所在的分割。 例如 set root=(hd0,msdos3) 的 hd0 表示開機隨身碟本身, 而 msdos3 指示 grub 到 (可能被格式化成 vfat 或 ext2/ext3/ext4 的) 第三分割去找 iso 檔。 注意: 這裡的 msdos 指的並非該分割區的格式, 而是指: 整顆隨身碟採用傳統的 mbr 方式分割而非採用新的 gpt 方式分割
  3. loopback loop $isofile 指定要從 $isofile 這個 iso 檔開機。
  4. linuxinitrd 那兩句則是從 iso 檔裡面的設定檔改過來的。 例如 finnix-ckhung15c.iso 裡面, 請拿 /isolinux.cfg 來改; 又如 bodhi-3.0.0-32.iso 裡面, 請拿 /isolinux/isolinux.cfg 來改。

卸載隨身碟的所有分割之後, 如果要用 qemu-kvm 測試, 記得要先拔出隨身碟再插回去 -- 尤其是等一下修改 grub.cfg 或拷貝新的圖檔, 如果沒有拔出隨身碟, 電腦可能還是會看到舊的版本! 然後你跟我一樣會誤以為修改無效而白白浪費許多時間! 註:如果隨身碟上有 lvm 的話, 卸載分割後還必須 vgchange -an vfnb 才能拔出隨身碟。 詳見 這個問答

在 grub 開機畫面按 「c」 進入命令列模式。 修改/測試 grub.cfg 最惱人的地方就是看不見錯誤訊息, 只能矇著眼睛亂改。 直到我從 這一篇 學到一個秘技才終於出師。 測試開機時, 如果達不到預期的效果, 請在 grub 的開機畫面按 「c」 進入命令列模式。 在這裡, 你可以下 lsmod 查看 grub 已載入哪些模組、 下 set 查看許多變數的值。 最重要的是: 某些時候可以按 Tab 鍵讓 grub 幫你做命令列快打 (command completion 或 file name completion) 確認一下它到底有沒有看到你的檔案。 最最重要的是: 它會印出錯誤訊息! (我找你找得好久啊! 感動得快哭了) 如右圖: 它不只幫我拼出 background_image 的正確指令, 還讓我發現載入 jpg 模組的正確指令是 insmod jpeg 而不是 insmod jpg、 讓我學到圖檔名稱必須寫完整的絕對路徑。 改好之後, 可以按 Esc 回到開機選單。

這一篇如果可以幫你省下一些無頭蒼蠅的焦慮、 減少產生一些不必要的光碟片垃圾, 那麼我先前跟 grub2 奮戰所荒廢掉的好幾個週末也就有價值了 ^_^

5 則留言:

  1. YUMI (Your Universal Multiboot Installer)

    回覆刪除
  2. 貴哥,你篇文章幫我很大!我也是想要在硬碟上割一塊分割區,打算用 Grub 開啟 live-ISO 檔,但是當我用 [grub-install --boot-directory] 安裝 Grub 到 "post-MBR gap" (core.img) 和硬碟分割區檔案系統內後, 我一直想不出辦法要怎麼生出 [grub.cfg] 檔案 (因為不能用 update-grub 或 grub-mkconfig)。謝謝這篇好文!

    回覆刪除
  3. 有些 iso 會要在載入核心時指定路徑參數,像 ubuntu 的。

    ```
    menuentry "Try Ubuntu without installing" {
    loopback loop "$ubuntu"
    set root=(loop)
    set gfxpayload=keep
    linux /casper/vmlinuz file=/cdrom/preseed/ubuntu.seed boot=casper quiet splash ---
    initrd /casper/initrd.lz
    }
    ```

    但開機後核心不會知道那個 `/cdrom/pressed/ubuntu.seed`
    要去找隨身碟的分割裡的 iso 掛載後才有,
    所以很多 iso 在 grub 下都無法正常開機。
    我試過正常的只有你的 finnix ,
    那個 findiso 參數不知道為什麼找得到。

    回覆刪除
    回覆
    1. 我沒用過 preseed 耶。 那是 「無人看守自動安裝」 的情況下才需要的機制不是嗎? https://wiki.debian.org/DebianInstaller/Preseed 如果在設定檔裡直接省略那段參數可以嗎?

      刪除

因為垃圾留言太多,現在改為審核後才發佈,請耐心等候一兩天。