2017年9月3日 星期日

把已灌入硬碟的系統變成 live cd

live-boot 的開機流程 玩出來了! 太感動了! Debian 系列 (含 *ubuntu) 有一個 live-boot 套件, 它可以把你已安裝在硬碟上的 linux 系統打包變成一張開機光碟 (live CD)。 這有什麼好處?

  1. 因為光碟是唯讀的, 所以你可以把系統用 squashfs 的方式壓縮到很小, 很省空間。
  2. 這張光碟可以用 pxe 從網路開機。
  3. 你可以把這張光碟放到隨身碟上, 再加上 persistence 功能, 又讓它變成可寫入的版本。 幫麻瓜製作開機隨身碟變得又快又簡單!。

一、 開機流程

製作好的光碟的開機流程如上圖:

  1. isolinux 取得控制權, 讀取 isolinux/isolinux.cfg
  2. 載入指定的 vmlinuz 跟特製的 initrd
  3. 特製的 initrd 在 live/ 目錄下找到一個 squashfs, 檔名任意, 把它變成 root file system。 但是會先用 overlayfs 在上面覆蓋一個 (位於記憶體內的) 可讀寫的檔案系統, 所以用起來感覺跟可寫入的正常系統一樣 -- 變成了一張像是 ubuntu 安裝光碟, 可試用的 live CD。

其中聽起來最可怕的 「特製的 initrd」, 其實超簡單, 甚至連下指令都不需要! 只要安裝 live-boot live-boot-initramfs-tools 這兩個套件, 系統就會自動根據目前的 kernel 立即幫你產生一個 「特製的 initrd」, 它認得 man live-boot 手冊裡面所講的這些特殊參數, 所以你可以在 isolinux/isolinux.cfg 設定檔裡面使用這些參數。 對於熟悉 extlinux 開機設定 的讀者來說, 剩下的事情就都很簡單了。

二、 製作 iso 檔

以下把 「想要變成 live CD 的那個系統」 稱為廚窗展示系統。 嚴正提醒: 不要放入個人隱私資料 然後又把做好的 iso 放到 ftp 上讓網友下載你的信用卡號或家裡 wifi 密碼等等 :-) 完整製作步驟如下:

  1. 用廚窗展示系統開機。 (虛擬機可)
  2. apt-get install live-boot live-boot-initramfs-tools 在 /boot 底下產生 「特製的 initrd」。
  3. 用別的輔助 linux (例如含平常的工作系統, 或 live CD 或可開機隨身碟) 開機、 把廚窗展示系統用唯讀的方式掛載起來, 例如 mount -o ro /dev/sdz99 /mnt/showoff
  4. 在這個輔助系統上安裝 squashfs-tools isolinux xorriso 三個套件。
  5. 建一個工作目錄, 假設叫做 /some/large/part/worksp 好了。 把廚窗展示系統的 kernel (vmlinuz) 跟剛產生的特製的 initrd 都拷貝到 /some/large/part/worksp 底下。
  6. 把 /usr/lib/syslinux 整個目錄也拷過去, 改名為 isolinux 。 又把 /usr/lib/ISOLINUX/isolinux.bin /usr/lib/syslinux/modules/bios/ldlinux.c32 兩個檔案都複製到 isolinux/ 底下 (也就是跟 isolinux.cfg 放在同一層子目錄裡)。 還有, 把 我的範例 isolinux.cfg 也放到 isolinux/ 底下。 重點是 boot=live 那一小段叫特製的 initrd 啟用 live-boot 功能。
  7. 把整個廚窗展示系統壓縮成一個 squashfs 檔案系統, 放到 /some/large/part/worksp 底下的 live 子目錄裡面: mkdir /some/large/part/worksp/live ; mksquashfs /mnt/showoff /some/large/part/worksp/live/root.squashfs 它的 /etc/fstab 或是其他任何檔案都不需要修改, 因為掛載 root file system 的動作, 早在它變成 root 就已完成, 所以裡面指定 (或根本沒指定) 誰是 root file system 根本不重要。 所產生的檔案, 副檔名為 .squashfs ; 檔名前半部任意 (例如上面的 root)。
  8. 最後 /some/large/part/worksp 的目錄結構長這樣:
      44444K ./initrd.img-4.8.0-41-generic
      92937  ./isolinux/cyut-bv.jpg
      40960  ./isolinux/isolinux.bin
       1540  ./isolinux/isolinux.cfg
     116492  ./isolinux/ldlinux.c32
        439  ./isolinux/mbr/altmbr.bin
        440  ./isolinux/mbr/gptmbr.bin
        440  ./isolinux/mbr/mbr.bin
      25628  ./isolinux/memdisk
             ...
       1256  ./isolinux/modules/bios/cmd.c32
       3688  ./isolinux/modules/bios/cmenu.c32
       1492  ./isolinux/modules/bios/config.c32
             ...
       3096  ./isolinux/modules/bios/vesa.c32
       2204  ./isolinux/modules/bios/vesainfo.c32
      26724  ./isolinux/modules/bios/vesamenu.c32
             ...
       1913M ./live/root.squashfs
       7140K ./vmlinuz-4.8.0-41-generic
    
  9. 製作 .iso 檔: xorriso -as mkisofs -o /some/large/part/result.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table /some/large/part/worksp
  10. isohybrid 加工 (尚未測試)

然後就可以用 kvm 去測試你的 /some/large/part/result.iso 了! 如果你的記憶體夠大的話, 可以在 kernel 命令列上 (亦即 isolinux/isolinux.cfg 的 append 那句) 加上 「toram」 那麼整個 *.squashfs 會被載入記憶體, 之後執行速度變得飛快, 而且光碟可以拔掉! 很訝異這麼讚的東西, 竟然搜尋不太到教學文, 甚至連僅有的少數英文教學文都寫得不清不楚。 Ubuntu 的 casper 也是用 live-boot 做出來的; 但多數文章都沒解釋細節, 我也一直無法理解為什麼設定檔裡看不見 *.squashfs 的檔名。 最後是靠 這個簡短的問答 才學會的。

測試過程當中, 最容易遇到的錯誤有兩種: 如果是像左邊這個 kernel panic, 很有可能是因為你用的 initrd 是舊的、 錯誤的、 沒有經過 live-boot-initramfs-tools 加持的版本。 如果是像右邊這個 busybox, 那就是 initrd 已經執行到底, 可是卻找不到 live/*.squashfs 。 這時可能需要檢查 *.squashfs 放置的位置, 或是在 isolinux.cfg 裡的 append 那句後面加上 live-media-path=... (預設值是 live-media-path=/live )。

kernel panic busybox

三、 persistence

如果 live CD 開機之後, 某顆硬碟或某顆隨身碟上面有正確的映像檔, 那麼系統會用 overlayfs 把這個映像檔覆蓋到唯讀的 squashfs 之上, 於是所有的變動就又可以存入映像檔。 這個機製稱為 persistence。 在 isolinux.cfg 的 kernel 命令列上要包含這幾段: persistence persistence-path=/live-save persistence-label=stux.img 之類的設定, 這樣光碟開機時, 會到每顆硬碟、 每顆隨身碟的每個分割裡的 /live-save 目錄下尋找 stux.img 檔案。 stux.img 必須是一個 loopback file system, 而且它的根目錄下必須有一個 persistence.conf 設定檔。 以下是製作 stux.img 的範例指令:

dd count=524288 bs=1024 < /dev/zero > stux.img
mkfs -t ext4 stux.img
mount stux.img /mnt/t1
echo '/ union' > /mnt/t1/persistence.conf
umount /mnt/t1

更詳盡的設定語法請見 persistence.conf ; 這一頁 有更多範例。 這個映像檔最最起碼要有 300MB 的容量, 因為 /var/cache/apt 會吃掉很多空間; 但一開始也並不需要設很大, 因為日後空間不夠用時還可以擴增, 例如這樣做可以幫它增加 1.5G 的容量:

dd count=1572864 bs=1024 < /dev/zero >> stux.img
e2fsck -f stux.img
resize2fs stux.img

如果用 live CD 開機有看到類似下面的 /lib/live/mount/persistence/loop1 那麼 persistence 的設定應該就成功了:

檔案系統        1K-區段    已用     可用 已用% 掛載點
udev            1000092       0  1000092    0% /dev
tmpfs            204784    3728   201056    2% /run
/dev/sda1      18308352 2540816 15767536   14% /lib/live/mount/persistence/sda1
/dev/loop0      1959040 1959040        0  100% /lib/live/mount/rootfs/root.squashfs
tmpfs           1023916       0  1023916    0% /lib/live/mount/overlay
/dev/loop1       499656  256960   206000   56% /lib/live/mount/persistence/loop1
overlay          499656  256960   206000   56% /
tmpfs           1023916      72  1023844    1% /dev/shm
tmpfs              5120       0     5120    0% /run/lock
tmpfs           1023916       0  1023916    0% /sys/fs/cgroup
tmpfs           1023916       4  1023912    1% /tmp
tmpfs            204784  131796    72988   65% /run/user/1000

我的 6G 的系統, 用 mksquashfs 壓縮之後只剩 2G。 再搭配一個 2G 的 persistence 映像檔, 只需要 4G 的空間就可以享受將近 8G 的自由。 而且這全部可以安裝在 vfat 分割上。 也就是說, 麻瓜拿隨身碟給我, 不需要燒毀, 只要還有足夠的空間, 就可以幫他製作開機隨身碟!

四、 網路開機

假設你已成功設定 透過 pxe 從網路啟動簡單的 live CD。 想要把 live-boot 所製作的 live CD 放到網路上, 除了 dnsmasq 基本的設定之外, 還需要在 pxe 伺服器上架設一個 http 服務 (例如 apache2), 由它來提供 *.squashfs 。 假設 pxe 伺服器的 apache2 的 DocumentRoot 是 /var/www/html, 又假設 iso 檔已放在伺服器的 /large/partition/result.iso 。 可以這樣掛載並建立連結:

mkdir /var/lib/tftpboot/os/myliveCD
mount /large/partition/result.iso /var/lib/tftpboot/os/myliveCD
ln -s /var/lib/tftpboot/os/myliveCD /var/www/html

那麼你的 /var/lib/tftpboot/pxelinux.cfg/default 裡面跟這張 iso 相關的部分應該長得類似這樣:

label myliveCD
        kernel /os/myliveCD/vmlinuz-4.8.0-41-generic
        append initrd=/os/myliveCD/initrd.img-4.8.0-41-generic boot=live fetch=http://192.168.xx.yy/myliveCD/live/root.squashfs

其中 192.168.xx.yy 當然是 pxe 伺服器的 IP。 (必須用數字 IP!) 也就是說, 客戶端透過 tftp 取得 vmlinuz 跟 initrd; 但是下一階段的 root file system 必須用 fetch=... 透過 http 的方式取得, 而且這種做法自動會把整個 root.squashfs 載入客戶端的記憶體。 如果客戶端記憶體容量不夠大, 但有硬碟可用, 可以試試 live-boot 手冊裡的 todisk 參數。 我沒試過; 但猜想可用這個功能來取代電腦教室裡的還原卡。

[9/21] gregslab17C.iso 的 initramfs 版本不能從網路開機 (好像跟 bug/1636530 有關?) 如果需要從網路開機, 請改用較舊的 lab179-b.iso , 沒有 mbootuz 也沒有 persistence 。 正在製作新版解決問題...

live-boot 真是太讚了! 好想把這招分享給電腦老師們啊! 有沒有學校想辦電腦教室網管研習呢?

1 則留言:

  1. 太感謝了~~一直很愛live cd裡面toram的功能,沒想到我也可以把自己的系統製作成live cd,好好的拜讀老師的文章!!

    回覆刪除