准备(GNU/Linux Debian/Ubuntu)
安装构建环境所需的应用程序。
sudo apt-get install \
binutils \
debootstrap \
squashfs-tools \
xorriso \
grub-pc-bin \
grub-efi-amd64-bin \
mtools
mkdir $HOME/live-ubuntu-from-scratch
引导程序
构建基础系统
sudo debootstrap \
--arch=amd64 \
--variant=minbase \
22.04 \
$HOME/live-ubuntu-from-scratch/chroot \
https://mirrors.aliyun.com/ubuntu/
debootstrap
用于从头开始创建 Debian
基础系统,而不需要dpkg
或apt
的可用性。它通过从镜像站点下载 .deb
文件并将其解压缩到最终可以chroot到的目录中来做到这一点。
外部挂载点
sudo mount --bind /dev $HOME/live-ubuntu-from-scratch/chroot/dev
sudo mount --bind /run $HOME/live-ubuntu-from-scratch/chroot/run
由于将更新和安装的一些软件包(其中包括grub),这些挂载点在chroot环境中是必需的。
定义 chroot 环境
Unix操作系统上的chroot是一种更改当前运行进程及其子进程的明显根目录的操作。在这种修改后的环境中运行的程序无法命名(因此通常无法访问)指定目录树之外的文件。术语“chroot”可以指 chroot
系统调用或 chroot
包装程序。修改后的环境称为 chroot jail
。
访问chroot环境
sudo chroot $HOME/live-ubuntu-from-scratch/chroot
配置挂载点、家庭和语言环境
挂载无 -t proc /proc
挂载无 -t sysfs /sys
挂载无 -t devpts /dev/pts
导出 HOME=/root
导出 LC_ALL=C
这些挂载点在chroot环境中是必需的,因此我们能够顺利完成安装。
设置自定义主机名
echo "ubuntu-fs-live" > /etc/hostname
配置 apt sources.list
cat <<EOF > /etc/apt/sources.list
deb http://us.archive.ubuntu.com/ubuntu/ focal main restricted universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ focal main restricted universe multiverse
deb http://us.archive.ubuntu.com/ubuntu/ focal-security main restricted universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ focal-security main restricted universe multiverse
deb http://us.archive.ubuntu.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ focal-updates main restricted universe multiverse
EOF
更新包索引
apt-get update
安装systemd
apt-get install -y libterm-readline-gnu-perl systemd-sysv
systemd是 Linux 的系统和服务管理器。它提供了积极的并行化能力,使用套接字和 D-Bus 激活来启动服务,提供守护进程的按需启动,使用 Linux 控制组跟踪进程,维护挂载和自动挂载点,并实现精细的基于事务依赖的服务控制逻辑。
配置 machine-id
并转移
dbus-uuidgen > /etc/machine-id
ln -fs /etc/machine-id /var/lib/dbus/machine-id
该/etc/machine-id文件包含在安装或引导期间设置的本地系统的唯一机器 ID。机器 ID 是一个以换行符结尾的十六进制 32 个字符的小写 ID。从十六进制解码时,这对应于 16 字节/128 位值。此 ID 可能并非全为零。
dpkg-divert --local --rename --add /sbin/initctl
ln -s /bin/true /sbin/initctl
dpkg-divert是用于设置和更新转移列表的实用程序。
安装 Live System 所需的软件包
apt-get install -y \
sudo \
ubuntu-standard \
casper \
lupin-casper \
discover \
laptop-detect \
os-prober \
network-manager \
resolvconf \
net-tools \
wireless-tools \
wpagui \
locales \
grub-common \
grub-gfxpayload-lists \
grub-pc \
grub-pc-bin \
grub2-common
apt-get install -y --no-install-recommends linux-generic
图形安装程序
apt-get install -y \
ubiquity \
ubiquity-casper \
ubiquity-frontend-gtk \
ubiquity-slideshow-ubuntu \
ubiquity-ubuntu-artwork
安装过程中将出现tui
对话框,无需做任何配置修改。
安装窗口管理器
apt-get install -y \
plymouth-theme-ubuntu-logo \
ubuntu-gnome-desktop \
ubuntu-gnome-wallpapers
安装有用的应用程序
apt-get install -y \
clamav-daemon \
terminator \
apt-transport-https \
curl \
vim \
nano \
less
安装 Visual Studio Code (可选)
curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/
echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list
rm microsoft.gpg
apt-get update
apt-get install -y code
安装 Google Chrome (可选)
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
echo "deb http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list
apt-get update
apt-get install google-chrome-stable
安装 JDK (可选)
apt-get install -y \
openjdk-8-jdk \
openjdk-8-jre
移除不需要的应用 (可选)
apt-get purge -y \
transmission-gtk \
transmission-common \
gnome-mahjongg \
gnome-mines \
gnome-sudoku \
aisleriot \
hitori
删除不用的软件包
apt-get autoremove -y
重新配置
生成语言配置
dpkg-reconfigure locales
# 选择语言和默认语言
重新配置 resolvconf
dpkg-reconfigure resolvconf
配置网络
cat <<EOF > /etc/NetworkManager/NetworkManager.conf
[main]
rc-manager=resolvconf
plugins=ifupdown,keyfile
dns=dnsmasq
[ifupdown]
managed=false
EOF
dpkg-reconfigure network-manager
清理 chroot 环境
# If have installed software
truncate -s 0 /etc/machine-id
# Remove the diversion
rm /sbin/initctl
dpkg-divert --rename --remove /sbin/initctl
# Clean up
apt-get clean
rm -rf /tmp/* ~/.bash_history
umount /proc
umount /sys
umount /dev/pts
export HISTSIZE=0
exit
# Unbind mount points
sudo umount $HOME/live-ubuntu-from-scratch/chroot/dev
sudo umount $HOME/live-ubuntu-from-scratch/chroot/run
映像目录并填充
cd $HOME/live-ubuntu-from-scratch
mkdir -p image/{casper,isolinux,install}
sudo cp chroot/boot/vmlinuz-**-**-generic image/casper/vmlinuz
sudo cp chroot/boot/initrd.img-**-**-generic image/casper/initrd
sudo cp chroot/boot/memtest86+.bin image/install/memtest86+
wget --progress=dot https://www.memtest86.com/downloads/memtest86-usb.zip -O image/install/memtest86-usb.zip
unzip -p image/install/memtest86-usb.zip memtest86-usb.img > image/install/memtest86
rm image/install/memtest86-usb.zip
Grub 配置
cd $HOME/live-ubuntu-from-scratch
touch image/ubuntu
创建 /image/isolinux/grub.cfg
cat <<EOF > image/isolinux/grub.cfg
search --set=root --file /ubuntu
insmod all_video
set default="0"
set timeout=30
menuentry "Try Ubuntu FS without installing" {
linux /casper/vmlinuz boot=casper quiet splash ---
initrd /casper/initrd
}
menuentry "Install Ubuntu FS" {
linux /casper/vmlinuz boot=casper only-ubiquity quiet splash ---
initrd /casper/initrd
}
menuentry "Check disc for defects" {
linux /casper/vmlinuz boot=casper integrity-check quiet splash ---
initrd /casper/initrd
}
menuentry "Test memory Memtest86+ (BIOS)" {
linux16 /install/memtest86+
}
menuentry "Test memory Memtest86 (UEFI, long load time)" {
insmod part_gpt
insmod search_fs_uuid
insmod chain
loopback loop /install/memtest86
chainloader (loop,gpt1)/efi/boot/BOOTX64.efi
}
EOF
创建 manifest
在接下来的步骤中,清单的创建很重要,因为它告诉我们每个包的哪个版本安装在 Live 版本中,以及哪些包将在将要安装的版本中删除或维护(保留在硬盘中)。
cd $HOME/live-ubuntu-from-scratch
sudo chroot chroot dpkg-query -W --showformat='${Package} ${Version}\n' | sudo tee image/casper/filesystem.manifest
sudo cp -v image/casper/filesystem.manifest image/casper/filesystem.manifest-desktop
sudo sed -i '/ubiquity/d' image/casper/filesystem.manifest-desktop
sudo sed -i '/casper/d' image/casper/filesystem.manifest-desktop
sudo sed -i '/discover/d' image/casper/filesystem.manifest-desktop
sudo sed -i '/laptop-detect/d' image/casper/filesystem.manifest-desktop
sudo sed -i '/os-prober/d' image/casper/filesystem.manifest-desktop
压缩 chroot
cd $HOME/live-ubuntu-from-scratch
# 创建 squashfs
sudo mksquashfs chroot image/casper/filesystem.squashfs
# 生成 filesystem.size
printf $(sudo du -sx --block-size=1 chroot | cut -f1) > image/casper/filesystem.size
Squashfs是一个高度压缩的 Linux 只读文件系统。它使用 zlib 压缩来压缩文件、inode 和目录。系统中的 inode 非常小,所有块都被打包以最小化数据开销。支持大于 4K 的块大小,最大支持 64K。 Squashfs旨在用于一般只读文件系统、存档使用(即在可能使用 .tar.gz 文件的情况下)以及需要低开销的受限块设备/内存系统(例如嵌入式系统)。
创建磁盘说明
README文件通常可以在 Linux LiveCD 安装光盘上找到,例如 Ubuntu Linux 安装光盘;通常命名为“ README.diskdefines ”并且可以在安装过程中被引用。
cd $HOME/live-ubuntu-from-scratch
# Create file image/README.diskdefines
cat <<EOF > image/README.diskdefines
#define DISKNAME Ubuntu from scratch
#define TYPE binary
#define TYPEbinary 1
#define ARCH amd64
#define ARCHamd64 1
#define DISKNUM 1
#define DISKNUM1 1
#define TOTALNUM 0
#define TOTALNUM0 1
EOF
为 LiveCD 创建 ISO 映像 (BIOS + UEFI)
cd $HOME/live-ubuntu-from-scratch/image
# 创建 grub UEFI 映像
grub-mkstandalone \
--format=x86_64-efi \
--output=isolinux/bootx64.efi \
--locales="" \
--fonts="" \
"boot/grub/grub.cfg=isolinux/grub.cfg"
# 创建包含 EFI 引导加载程序的 FAT16 UEFI 引导磁盘映像
(
cd isolinux && \
dd if=/dev/zero of=efiboot.img bs=1M count=10 && \
sudo mkfs.vfat efiboot.img && \
LC_CTYPE=C mmd -i efiboot.img efi efi/boot && \
LC_CTYPE=C mcopy -i efiboot.img ./bootx64.efi ::efi/boot/
)
# 创建 grub BIOS 映像
grub-mkstandalone \
--format=i386-pc \
--output=isolinux/core.img \
--install-modules="linux16 linux normal iso9660 biosdisk memdisk search tar ls" \
--modules="linux16 linux normal iso9660 biosdisk search" \
--locales="" \
--fonts="" \
"boot/grub/grub.cfg=isolinux/grub.cfg"
# 组合可引导的 grub cdboot.img
cat /usr/lib/grub/i386-pc/cdboot.img isolinux/core.img > isolinux/bios.img
# 生成md5sum.txt
sudo /bin/bash -c "(find . -type f -print0 | xargs -0 md5sum | grep -v "\./md5sum.txt" > md5sum.txt)"
# 使用命令行从镜像目录创建iso
sudo xorriso \
-as mkisofs \
-iso-level 3 \
-full-iso9660-filenames \
-volid "Ubuntu from scratch" \
-output "../ubuntu-from-scratch.iso" \
-eltorito-boot boot/grub/bios.img \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
--eltorito-catalog boot/grub/boot.cat \
--grub2-boot-info \
--grub2-mbr /usr/lib/grub/i386-pc/boot_hybrid.img \
-eltorito-alt-boot \
-e EFI/efiboot.img \
-no-emul-boot \
-append_partition 2 0xef isolinux/efiboot.img \
-m "isolinux/efiboot.img" \
-m "isolinux/bios.img" \
-graft-points \
"/EFI/efiboot.img=isolinux/efiboot.img" \
"/boot/grub/bios.img=isolinux/bios.img" \
"."
另一种方法,如果前一个失败,创建一个混合 ISO
# 创建 ISOLINUX (syslinux) 启动菜单
cat <<EOF> isolinux/isolinux.cfg
UI vesamenu.c32
MENU TITLE Boot Menu
DEFAULT linux
TIMEOUT 600
MENU RESOLUTION 640 480
MENU COLOR border 30;44 #40ffffff #a0000000 std
MENU COLOR title 1;36;44 #9033ccff #a0000000 std
MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
MENU COLOR unsel 37;44 #50ffffff #a0000000 std
MENU COLOR help 37;40 #c0ffffff #a0000000 std
MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
MENU COLOR msg07 37;40 #90ffffff #a0000000 std
MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
LABEL linux
MENU LABEL Try Ubuntu FS
MENU DEFAULT
KERNEL /casper/vmlinuz
APPEND initrd=/casper/initrd boot=casper
LABEL linux
MENU LABEL Try Ubuntu FS (nomodeset)
MENU DEFAULT
KERNEL /casper/vmlinuz
APPEND initrd=/casper/initrd boot=casper nomodeset
EOF
# 包括 syslinux bios 模块
apt install -y syslinux-common && \
cp /usr/lib/ISOLINUX/isolinux.bin isolinux/ && \
cp /usr/lib/syslinux/modules/bios/* isolinux/
# 从镜像目录创建iso
sudo xorriso \
-as mkisofs \
-iso-level 3 \
-full-iso9660-filenames \
-volid "Ubuntu from scratch" \
-output "../ubuntu-from-scratch.iso" \
-isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin \
-eltorito-boot \
isolinux/isolinux.bin \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
--eltorito-catalog isolinux/isolinux.cat \
-eltorito-alt-boot \
-e /EFI/boot/efiboot.img \
-no-emul-boot \
-isohybrid-gpt-basdat \
-append_partition 2 0xef EFI/boot/efiboot.img \
"$HOME/live-ubuntu-from-scratch/image"
制作可启动的 USB 映像
sudo dd if=ubuntu-from-scratch.iso of=<device> status=progress oflag=sync
小结
生成的 ISO 可以在虚拟机中进行测试,例如VirtualBox或写入媒体并从标准 PC 启动。