从零制作 Ubuntu 20.04 LiveCD
为什么要构建自己的 LiveCD
- 进行一些本地化修改;
- 对默认设置不满意;
- 对镜像的预装不满意。
构建条件
- 一个运行 Ubuntu 的设备(虚拟机也是可以的,但不推荐 WSL1/2,因为 WSL2 经过实际测试会出现一些问题)。
- 确保已经安装
dosfstools
、squashfs-tools
、xorriso
、grub-common
、grub-pc-bin
、grub-efi
软件包。还有nano
文本编辑器。
sudo apt-get install --no-install-recommends -y debootstrap squashfs-tools xorriso dosfstools mtools grub-efi grub-pc-bin nano
- 全程终端操作,需要
sudo
权限。
准备目录
准备一个空文件夹作为工作目录。这个空文件夹所在分区不能是 NTFS、FAT32 格式。
然后在这个文件夹中创建 target、livecd 这两个文件夹。target 里面是目标系统,livecd 是 ISO 文件夹目录。
livecd 里面要创建 casper boot EFI preseed 等文件夹
export CHROOT=$PWD/target
sudo mkdir -p $CHROOT livecd/{casper,boot/grub,EFI/boot}
准备镜像
- 基础系统
构建基础系统有两种方式:
- 利用 debootstrap 构建一个基础系统。
- 解压 Ubuntu Base。
debootstrap 是 Debian 系发行版的一个实用工具,允许您基于在线的软件源构建一个属于自己的 Debian 系发行版的基本系统。
Ubuntu Base 是 Ubuntu 的基本系统,说通俗点,就是 Ubuntu 帮你打包好的 debootstrap 后的基本系统。
如果你想使用 debootstrap 工具构建一个基本系统,请运行:debootstrap focal chroot https://mirrors.aliyun.com/ubuntu
sudo debootstrap --no-check-gpg --variant=minbase --arch=amd64 --exclude=gcc-9-base,gcc-10-base --components=main,restricted,universe,multiverse \
--include=bash-completion,systemd-sysv,locales,nano,casper,console-setup,netplan.io,whiptail focal $CHROOT https://mirrors.aliyun.com/ubuntu
- 配置软件源,因为默认是不完善的。
sudo chroot $CHROOT tee /etc/apt/sources.list << EOF
deb https://mirrors.aliyun.com/ubuntu focal main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu focal-security main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu focal-updates main restricted universe multiverse
EOF
- 挂载特殊文件系统
你需要先挂载一些特殊的文件系统。比如 dev proc sys run。
sudo mount -B /dev $CHROOT/dev
sudo chroot $CHROOT mount none -t proc /proc
sudo chroot $CHROOT mount none -t sysfs /sys
sudo chroot $CHROOT mount none -t devpts /dev/pts
sudo chroot $CHROOT bash -s << EOF
truncate -s 0 /etc/machine-id
ln -fs /etc/machine-id /var/lib/dbus/machine-id
dpkg-divert --local --rename --add /sbin/initctl
ln -s /bin/true /sbin/initctl
EOF
- 更新软件源
我们先更新一下软件源,升级一下基础系统里的软件包。
sudo chroot $CHROOT apt-get update
sudo chroot $CHROOT env DEBIAN_FRONTEND=noninteractive apt-get upgrade -y
- 安装 Linux 内核
这一步是必要的,安装的内核还将用于 ISO 镜像的引导。
sudo sed -i 's|COMPRESS=lz4|COMPRESS=lzma|' $CHROOT/etc/initramfs-tools/initramfs.conf
sudo chroot $CHROOT apt-get install -y linux-image-generic-hwe-20.04 grub-*-
- 复制内核到光盘镜像
sudo mv $CHROOT/boot/vmlinuz-**-**-generic livecd/casper/vmlinuz
sudo mv $CHROOT/boot/initrd.img-**-**-generic livecd/casper/initrd.img
- 给目标系统安装最小化桌面
sudo chroot $CHROOT env DEBIAN_FRONTEND=noninteractive apt-get install -y fonts-noto-cjk-extra language-pack-gnome-zh-hans ubuntu-desktop-minimal \
networkd-dispatcher netplan.io firefox- gedit- eog- evince- gnome-characters- gnome-user-docs- gnome-font-viewer- gnome-online-accounts- \
gnome-disk-utility- gnome-screenshot- gnome-logs- ubuntu-docs- fonts-deva- snapd- cups- cups-*- ibus- ibus-*-
sudo tee $CHROOT/etc/netplan/01-network-manager-all.yaml << EOF
# Let NetworkManager manage all devices on this system
network:
version: 2
renderer: NetworkManager
EOF
自定义配置
到这里结束之后,你可以在这个 chroot 容器里面进行自定义的设置,你想要预装什么软件,也可以操作。在容器里的操作和在本机操作的命令是相似甚至一致的。
- 添加额外 apt 源
# 添加 VSCode 源
curl -sL https://packages.microsoft.com/keys/microsoft.asc | sudo gpg --dearmor -o $CHROOT/etc/apt/trusted.gpg.d/microsoft.gpg
echo "deb [arch=amd64] https://packages.microsoft.com/repos/code stable main" | sudo tee $CHROOT/etc/apt/sources.list.d/vscode.list
echo "deb [arch=amd64] https://packages.microsoft.com/repos/edge stable main" | sudo tee $CHROOT/etc/apt/sources.list.d/microsoft-edge.list
# 添加 cmake 源
curl -sL https://apt.kitware.com/keys/kitware-archive-latest.asc | sudo gpg --dearmor -o $CHROOT/etc/apt/trusted.gpg.d/kitware.gpg
echo "deb https://apt.kitware.com/ubuntu/ focal main" | sudo tee $CHROOT/etc/apt/sources.list.d/kitware.list
curl -sL https://mirrors.aliyun.com/docker-ce/linux/debian/gpg | sudo gpg --dearmor -o $CHROOT/etc/apt/trusted.gpg.d/docker.gpg
echo "deb https://mirrors.aliyun.com/docker-ce/linux/ubuntu/ focal stable" | sudo tee $CHROOT/etc/apt/sources.list.d/docker-ce.list
- 安装字体
sudo unzip $HOME/fonts.zip -d $CHROOT/usr/share/fonts/truetype/microsoft
sudo chroot $CHROOT env DEBIAN_FRONTEND=noninteractive apt-get install -y gnome-tweaks
# 额外字体
echo msttcorefonts msttcorefonts/accepted-mscorefonts-eula select true | sudo chroot $CHROOT debconf-set-selections
sudo chroot $CHROOT apt-get install -y ttf-mscorefonts-installer
sudo chroot $CHROOT debconf-show ttf-mscorefonts-installer
- 个性化设置
sudo sed -i 's|\\w|\\W|g' $CHROOT/etc/skel/.bashrc
sudo mkdir -p $CHROOT/etc/dconf/profile $CHROOT/etc/dconf/db/local.d
sudo tee $CHROOT/etc/dconf/profile/user << EOF
user-db:user
system-db:local
EOF
sudo tee $CHROOT/etc/dconf/db/local.d/01-desktop << EOF
[org/gnome/desktop/media-handling]
automount=false
[org/gnome/desktop/interface]
font-name='微软雅黑 11'
document-font-name='微软雅黑 11'
[org/gnome/desktop/wm/preferences]
titlebar-font='微软雅黑 Bold 11'
EOF
sudo chroot $CHROOT dconf update
sudo mkdir $CHROOT/etc/docker
sudo tee $CHROOT/etc/docker/daemon.json << EOF
{
"data-root": "/opt/docker",
"registry-mirrors": [ "https://hub-mirror.c.163.com" ],
"log-driver": "journald",
"log-level": "warn",
"bridge": "none",
"debug": false
}
EOF
清理容器
到这一步,目标系统已经配置完毕了,下面应当进行清理。
sudo chroot $CHROOT apt-get autoremove --purge -y
for i in /dev/pts /dev /proc /sys; do sudo umount $CHROOT$i; done
sudo chroot $CHROOT bash -s << EOF
cat /dev/null > /etc/machine-id
rm /sbin/initctl
dpkg-divert --rename --remove /sbin/initctl
EOF
打包容器
# 建立清单
sudo chroot $CHROOT dpkg-query -W --showformat='${Package} ${Version}\n' | sudo tee livecd/casper/filesystem.manifest
# 打包目标系统
sudo mksquashfs $CHROOT livecd/casper/filesystem.squashfs -noappend -wildcards -e "var/cache/*" -e "var/log/*" -e "var/lib/apt/lists/*" -e "usr/share/man/*"
ISO 镜像的制作
- 创建 GRUB 引导文件
# 生成引导菜单
sudo tee livecd/boot/grub/grub.cfg << EOF
search --set=root --file /casper/vmlinuz
insmod all_video
set timeout=30
menuentry "Ubuntu Live" {
linux /casper/vmlinuz boot=casper net.ifnames=0 locale=zh_CN.UTF-8 toram fsck.mode=skip quiet splash --
initrd /casper/initrd.img
}
menuentry "Ubuntu persistent" {
linux /casper/vmlinuz boot=casper net.ifnames=0 locale=zh_CN.UTF-8 persistent fsck.mode=skip quiet splash --
initrd /casper/initrd.img
}
EOF
# 创建 GRUB EFI 引导文件
sudo grub-mkstandalone --format=x86_64-efi --output=livecd/EFI/boot/bootx64.efi --locales="" --fonts="" \
"boot/grub/grub.cfg=livecd/boot/grub/grub.cfg"
sudo LC_CTYPE=C bash -s << EOF
dd if=/dev/zero of=efiboot.img bs=1M count=3 && \
mkfs.vfat efiboot.img && \
mmd -i efiboot.img efi efi/boot && \
mcopy -i efiboot.img livecd/EFI/boot/bootx64.efi ::efi/boot/
EOF
# 创建 GRUB LEGACY 引导文件
sudo grub-mkstandalone --format=i386-pc --output=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=livecd/boot/grub/grub.cfg"
cat /usr/lib/grub/i386-pc/cdboot.img core.img > bios.img
- ISO 的生成
sudo xorriso -as mkisofs -iso-level 3 -full-iso9660-filenames -volid "UBUNTU" -output Ubuntu-20.04-LiveCD-x86_64.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 efiboot.img \
-graft-points "livecd" "/EFI/efiboot.img=efiboot.img" "/boot/grub/bios.img=bios.img"
参考资料
https://github.com/mvallim/live-custom-ubuntu-from-scratch
https://manpages.ubuntu.com/manpages/focal/man7/casper.7.html