玩出來了! 太感動了! Debian 系列 (含 *ubuntu) 有一個 live-boot 套件, 它可以把你已安裝在硬碟上的 linux 系統打包變成一張開機光碟 (live CD)。 這有什麼好處?
- 因為光碟是唯讀的, 所以你可以把系統用 squashfs 的方式壓縮到很小, 很省空間。
- 這張光碟可以用 pxe 從網路開機。
- 你可以把這張光碟放到隨身碟上, 再加上 persistence 功能, 又讓它變成可寫入的版本。 幫麻瓜製作開機隨身碟變得又快又簡單!。
2022/10/30 若要製作 UEFI 版的開機光碟, 請參考 支援 UEFI 光碟的開機載入程式 rEFInd。
一、 開機流程
製作好的光碟的開機流程如上圖:
- isolinux 取得控制權, 讀取 isolinux/isolinux.cfg
- 載入指定的 vmlinuz 跟特製的 initrd
- 特製的 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 密碼等等 :-) 完整製作步驟如下:
- 用廚窗展示系統開機。 (虛擬機可)
apt-get install live-boot live-boot-initramfs-tools
在 /boot 底下產生 「特製的 initrd」。- 用別的輔助 linux (例如含平常的工作系統, 或 live CD 或可開機隨身碟) 開機、 在這個輔助系統上安裝 squashfs-tools isolinux xorriso 三個套件。
- 把廚窗展示系統用唯讀的方式掛載起來, 例如
mount -o ro /dev/sdz99 /mnt/showoff
- 建一個工作目錄, 假設叫做 /some/large/part/worksp 好了。 把廚窗展示系統的 kernel (vmlinuz) 跟剛產生的特製的 initrd 都拷貝到 /some/large/part/worksp 底下。
- 把 /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 功能。 [2020/3/4 補充: kernel 命令列需要加一些選項: ip=frommedia 避免 ubuntu 清除網路設定、 net.ifnames=0 biosdevname=0 堅持採用傳統的網卡簡單命名。] - 把整個廚窗展示系統壓縮成一個 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)。 - 最後 /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
- 製作 .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
- 用 isohybrid 加工 (尚未測試)
然後就可以用 kvm 去測試你的 /some/large/part/result.iso 了! 很訝異這麼讚的東西, 竟然搜尋不太到教學文, 甚至連僅有的少數英文教學文都寫得不清不楚。 Ubuntu 的 casper 也是用 live-boot 做出來的; 但多數文章都沒解釋細節, 我也一直無法理解為什麼設定檔裡看不見 *.squashfs 的檔名。 最後是靠 這個簡短的問答 才學會的。
如果失敗, 就用螢幕錄影軟體 (例如 gtk-recordmydesktop) 把開機過程錄下來, 看看掛載 *.squashfs 成功之後, 發生了什麼事。 有時虛擬機開機速度太快, 可能需要把 gtk-recordmydesktop 的 「效能=>每秒畫格」 從 15 調到 30 之類的, 才拍得到。 有一個可能的原因: 記憶體不足。 造成 kernel panic 的另一個原因可能是: 你用的 initrd 是舊的、 錯誤的、 沒有經過 live-boot-initramfs-tools 加持的版本, 例如右圖。 這時可以移除 live-boot live-boot-initramfs-tools 這兩個套件、 再重裝一次, 系統就會自動更新 /boot 底下的所有 initrd*。
如果是像右邊這個 busybox, 那就是 initrd 已經執行到底, 可是卻找不到 live/*.squashfs 。 這時可能需要檢查 *.squashfs 放置的位置, 或是在 isolinux.cfg 裡的 append 那句後面加上 live-media-path=... (預設值是 live-media-path=/live )。
三、 把 squashfs 放在 lvm 裡面
Debian live 所製作的 initrd 會自動到各個 mbr 分割區或各個 gpt 分割的 /live 目錄下尋找任何名為 *.squashfs 的檔案來掛載。 所以熟悉 extlinux 開機設定 的讀者也不需要製作光碟, 可以直接把 vmlinuz、 initrd、 *.squashfs 等三個檔案搬到一般的分割上, 而且 *.squashfs 甚至不需要跟 extlinux 放在同一個分割區。
但若想搬到 lvm 的 logical volume 呢? 此時, 光指定 live-media-path 是不夠的。 還必須用 live-media 直接指定那個 logical volume 的 device name, 類似這樣:
label grml-lvm menu label grml from lvm /dev/mapper/eeepc-iso kernel /grml/vmlinuz append initrd=/grml/initrd.img boot=live live-media=/dev/mapper/eeepc-iso live-media-path=/grml
當然, 前提是 這個版本的 initrd 必須認得 lvm2 (grml 有)。 如果預設的 initrd 不認得, 就必須先把它安裝到硬碟上 (或用下節的 persistence 機制)、 安裝 lvm2 套件, 然後系統會自動建立新的 initrd。 你必須改用這個新的 initrd 來開機。
以後可以在硬碟上切一個 lvm 的 logical volume, 裡面專門放一堆各種版本的 debian-live 的 squashfs, 那麼單單是這一個 logical volume 就可以讓開機選單變得很熱鬧了啊~~
四、 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-label 所指定的, 未必要是一個映像檔, 也可以是一個分割。 以 lubuntu 17.04 所製作的 live boot 光碟, 它會去每個 MBR 或 GPT 分割還有每個 LVM 的 volume 檢查, 如果有哪一個分割或 volume 的 label (以 e2label 檢查出來的為準; 跟 lvs 列出來的名稱無關) 正好符合 persistence-label 後面的參數 (以上例而言, 如果這個分割的 e2label 正好也叫做 stux.img), 那麼 live boot 光碟的 initrd 就會在這個分割或 volume 的根目錄底下尋找 persistence.conf 設定檔。 在這種情況下, persistence-path 這個參數設定任何值都無所謂 -- 它會被忽略。
更詳盡的設定語法請見 persistence.conf ; 這一頁 有更多範例。 這個映像檔最最起碼要有 300MB 的容量, 因為 /var/cache/apt 會吃掉很多空間; 但一開始也並不需要設很大, 因為日後空間不夠用時還可以擴增, 例如這樣做可以幫它增加 1.5G 的容量:
dd count=1572864 bs=1024 < /dev/zero >> stux.img e2fsck -f stux.img resize2fs stux.img
右圖的錯誤訊息顯示它有找到 persistence 的分割區, 可是無法掛載 (也許是那個分割區並未格格式化之類的)。 最後如果用 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 壓縮之後只剩 2.3G。 再搭配一個 2G 的 persistence 映像檔, 只需要 4.3G 的空間就可以享受將近 6G 的自由。 而且這全部可以安裝在 vfat 分割上。 也就是說, 麻瓜拿隨身碟給我, 不需要燒毀, 只要還有足夠的空間, 就可以幫他製作開機隨身碟!
五、 全部載入記憶體, 豪邁帥氣裸奔!
如果你的記憶體夠大, 可以把整張光碟或隨身碟的整個分割載入記憶體。 一旦載入成功, 開機完成之後, 就可以拔掉隨身碟或光碟, 而且執行速度變得飛快!
載入記憶體的最佳方式, 就是在 kernel 命令列
(亦即 isolinux/isolinux.cfg 的 append 那句)
加上 toram=root.squashfs
之類的 boot option --
請根據你的光碟或隨身碟上的 *.squashfs 檔名
及放置位置 來修改,
檔名就好, 不要加路徑!)
於是整個 *.squashfs 會被載入記憶體。
這個寫法在手冊上找不到, 是從
這一頁 學來的。
手冊上的 toram 後面沒有參數, 結果會把 (*.squashfs 所在的)
整個分割或整張光碟上所有檔案拷貝進記憶體,
有可能會因此而太撐、 失敗。
另一個方式是在 kernel 命令列上採用
findiso=/gregslab17E.iso
之類的寫法, 載入整張光碟的映像檔。
這雖然比載入 *.squashfs 要浪費一些,
至少不會把隨身碟同一分割上所有不相關的所有檔案一起抓進來。
不論用哪一種方式載入記憶體,
開機完成後記得要先下 df
確認已掛載的裝置裡面沒有你的開機光碟或隨身碟, 才能拔掉。
還有, 當然, 載入記憶體跟隨身碟的 persistence 是無法並存的。
六、 網路開機
假設你已成功設定 透過 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 參數。 我沒試過; 但猜想可用這個功能來取代電腦教室裡的還原卡。
live-boot 真是太讚了! 好想把這招分享給電腦老師們啊! 有沒有學校想辦電腦教室網管研習呢?
太感謝了~~一直很愛live cd裡面toram的功能,沒想到我也可以把自己的系統製作成live cd,好好的拜讀老師的文章!!
回覆刪除使用persistence 功能 ,更改使用者密碼下一次開機的確是有所變動。 可是更改網路參數到此設定檔 /etc/network/interfaces,下一次開機並沒有變動,還是原設定檔。
回覆刪除老師~不好意思打擾~~請教一下:
回覆刪除文章上說到: 把 /usr/lib/syslinux 整個目錄也拷過去, 改名為 isolinux 。 又把 /usr/lib/ISOLINUX/isolinux.bin /usr/lib/syslinux/modules/bios/ldlinux.c32 兩個檔案都複製到 isolinux/ 底下
請問"isolinux.bin"這個檔案是在那邊?還是怎麼產生的呢?!
喔,要先安裝 isolinux 套件。
刪除感謝!老師的回答...是我漏掉!
刪除老師~不好意思打擾~~請教一下:
回覆刪除您這篇大作,好像只能Legacy 模式,如果要支援UEFI的話,該做那些的修正才能達到同樣的效果呢?
可以看這篇喔: https://newtoypia.blogspot.com/2022/10/refind.html 我把連結加上去好了。
刪除教授真的非常有求知精神,我太懶只會用人家做好的工具。最近有發現一個 Penguins' Eggs 工具可以完成上述功能的大部分,而且功能強大還沒了解到很透徹,開發者是義大利人,我試著用此工具將 Debian-based 發行版,如 Debian, Sparky, MX, LMDE 加入此工具做成 ISO 檔,有興趣可以下載玩看看。 https://sourceforge.net/projects/antix-mate-respin/
回覆刪除