某些使用情境下,為了節省大量的安裝時間,及確保每台機器的安裝設定的一致性,製作一個免安裝版的映像檔就非常有必要了。
這次Violet來教大家如何製作純文字介面的免安裝ISO檔,同時也會說明如何使用指定的Kernel版本。
教學使用的作業系統為Debian11 bullseye,Kernel版本為5.10.166。
本篇文章適合無製作經驗的人參考,但需要對linux的開機順序有一定程度的了解,至少要知道什麼是root filesystem, kernel及initrd等。
清楚製作的需求後,接下來一起來看看本次的目標。
目標
- 使用bootstrap建構Debian11 bullseye rootfs,並打包成squashfs格式
產生的映像:filesystem.squashfs - 編譯Kernel 5.10.166
產生的映像:vmlinuz - 編譯busybox-1.36.1
產生的映像:busybox - 編寫init檔,並與busybox和rootfs打包成initrd.gz
產生的映像:initrd.gz - 編寫 isolinux.cfg 引導程式設定文件,並將其與上面產生出來的 initrd.gz、vmlinuz、rootfs 和其他必要的引導檔案一起打包成 ISO 檔,這個ISO檔就是我們最終拿來開機的image
產生的映像:debian11-customer.iso - 使用Vitrual Box來掛載debian11-customer.iso,開機後會自動進入Debian11系統,輸入以下指令來查看版本,以確認image製作成功
檢查作業系統版本:cat /etc/os-release
檢查內核版本:uname -a
也就是說,我們需要分別製作kernel, initrd.gz, busybox, root filesystem,將這些檔案放入指定位置,最後打包成ISO檔,ISO檔的結構如下:
debian11-customer.iso
└── iso/ (${ISO_DIR})
├── vmlinuz
├── initrd.gz (${INITRD_DIR})
├── init
├── linuxrc
├── live/
└── filesystem.squashfs
├── bin/
├── busybox
└── ...
├── sbin/
└── ...
└── usr/
└── ...
└── isolinux/
├── isohdpfx.bin
├── isolinux.bin
├── isolinux.cfg
├── ldlinux.c32
├── libutil.c32
└── menu.c32
製作步驟
知道ISO檔的結構後,我們只要將所有檔案都按照這個結構來放入,最後打包起來就完成了,如果到這邊都能讀懂的話,那麼接下來的步驟就都不會有太大問題了。
環境建置
1) 使用Virtual Box新建一台官方標準版的Debain 11虛擬機,我們會需要標準版Debian裡面的部分檔案,同時這也是我們接下來所有步驟的編譯環境2) 確定在編譯環境是Debian 11後,開始安裝必要的安裝包
sudo apt install git-lfs
sudo apt install build-essential libncurses-dev bison flex libssl-dev libelf-dev bc
sudo apt install rsync
sudo apt install debootstrap squashfs-tools
apt install busybox-static
3) 建立專案資料夾,在此資料夾裡新建相關檔案,bootstrap_debian就是我們製作的${ROOT_DIR}
mkdir bootstrap_debian
cd bootstrap_debian
製作rootfs
1) 建一個 Debian rootfs(這裡以 bullseye 為例)
debootstrap --arch=amd64 bullseye ./live-rootfs http://deb.debian.org/debian/
2) 將Debian rootfs打包成 squashfs格式,並放入指定的ISO檔目錄結構中
mkdir live/
mksquashfs ./live-rootfs ./live/filesystem.squashfs -e boot
製作vmlinuz
1) 建置kernek資料夾,下載 kernel 5.10.166到此資料夾(這邊想要改成其他kernel也可以,確認好自己的下載版本即可,但也要確認你所下載的版本是否能與Debian 11相容)
mkdir kernel
cd kernel
wget --no-check-certificate https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.166.tar.xz
2) 解壓縮剛剛下載的檔案
tar -xf linux-5.10.166.tar.xz
3) 進入kernel source code的根目錄
cd linux-5.10.166
4) 調整自己想要的kernel config,可以修改.config或者下指令make menuconfig來操作。這邊列出幾個比較重要的config設定:
- 關閉BTF及Enable loadable module suppor設定
- 開啟以下設定
CONFIG_NET=y
CONFIG_UNIX=y
CONFIG_NETLINK=y
CONFIG_UEVENT_HELPER=y
CONFIG_DEVTMPFS=y
5) 調整完後,確保config生效後再編譯
make olddefconfig make -j2
6) 編譯完成後,打包成.deb檔,編譯完後會產生類似的檔案linux-image-5.10.166_amd64.deb
make -j$(nproc) bindeb-pkg
7) 這個deb檔是kernel的更新檔,檔可以在現成的Debian系統上直接使用dpkg命令來安裝,但我們的目標是想要包成ISO檔,因此需要取出裡面的vmlinuz
ar x linux-image-5.10.166_amd64.deb
tar -xf data.tar.xz ./boot/vmlinuz-5.10.166
這裡的vmlinuz-5.10.166就是我們要的vmlinuz了,將其放到指定的ISO檔目錄結構中
cp -r boot/vmlinuz-5.10.166 ${ROOT_DIR}/iso/vmlinuz
製作busybox
1) 下載busybox並解壓縮
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
tar -xvjf busybox-1.36.1.tar.bz2
2) 進入busybox資料夾,在菜單中,啟用「Build static binary (no shared libs)」選項,並編譯靜態資料庫的busybox
cd busybox-1.36.1
make defconfig
make menuconfig
make
3) 編譯完成後,可在busybox的根目錄下找到busybox,將其放入指定的ISO檔目錄結構中,並在該目錄下安裝
${BUSYBOX_DIR}為你編譯busybox的目錄,Violet的busybox目錄是busybox-1.36.1
${INITRD_DIR}為之後要製作成initrd.gz的目錄
make -C ${BUSYBOX_DIR} CONFIG_PREFIX=${INITRD_DIR} install
產生isolinux資料夾裡的檔案
1) isolinux資料夾裡的檔案,除了isolinux.cfg之外,都可以在我們的Debian編譯環境中找到,找到後,將這些檔案放入指定的ISO檔目錄結構中。這些檔案是grub啟動時需要用到的,如果沒有會造成開機失敗
mkdir isolinux
#確保資料夾裡面有以下檔案,檔案都從Debian編譯環境中複製過來
├── isohdpfx.bin
├── isolinux.bin
├── ldlinux.c32
├── libutil.c32
└── menu.c32
2) isolinux.cfg是開機的引導程式設定文件,需要根據自己的需求來設定,以下是範例
# D-I config version 2.0
# search path for the c32 support libraries (libcom32, libutil etc.)
UI menu.c32
PROMPT 0
TIMEOUT 50
DEFAULT linux
LABEL linux
menu label ^Boot Kernel 5.10.166 (Violet build)
kernel /vmlinuz
append initrd=/initrd.gz root=/dev/sdb1 rw init=/bin/sh console=tty0,115200 quiet
製作initrd.gz
1) 上面的映像檔及必要檔案都製作完畢後,接下來要來編寫rootfs的初始化流程,也就是init檔,以下是範例
#!/bin/sh
mkdir -p /proc /sys /dev /mnt
mkdir -p /mnt/sys/fs/cgroup
mkdir -p /mnt/sys/fs/cgroup/systemd
mkdir -p /mnt/run
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev
echo "Mounting rootfs.squashfs..."
mount -t squashfs -o loop /live/filesystem.squashfs /mnt || {
echo "Mount failed!"
exec sh
}
mount --bind /dev /mnt/dev
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
echo "Switching to new root..."
exec switch_root /mnt /sbin/init
2) 編寫完成後,務必確認好檔案都就緒,接著進入要打包成initrd.gz的目錄,開始打包initrd.gz
find . -print0 | cpio --null -ov --format=newc | gzip > ${ISO_DIR}/initrd.gz
3) 當之後測試開機有問題時,可以使用指令來檢查打包的inird.gz結構是否正確
lsinitramfs ${ISO_DIR}/initrd.gz
使用xorriso來製作ISO檔
mkdir build_image
xorriso -as mkisofs \
-o build_image/debian11-customer.iso \
-isohybrid-mbr isolinux/isohdpfx.bin \
-c isolinux/boot.cat \
-b isolinux/isolinux.bin \
-no-emul-boot -boot-load-size 4 -boot-info-table \
-J -R -V "Debian 11 Custom kernel" \
live-rootfs
成功後,就可以拿這個debian11-customer.iso到另一台全新的虛擬機上測試是否能正常開機了,開機後要能直接進入到Debian11的環境,進入後查看版本是否正確
cat /etc/os-release #檢查作業系統版本
uname -a #檢查內核版本
完成
以上就是本次的步驟做法,如有任何問題,也歡迎留言提出討論哦~
感謝您耐心閱讀~
本專題將會持續收錄Violet的職場筆記。
若有理解不對的地方,歡迎留言指教!
若喜歡我的文章,歡迎贊助支持,您的支持將會成為我繼續創作的動力!