详解:把 Linux 系统做成 Livecd

详解:把 Linux 系统做成 Livecd

本文比较长,制作 LiveCD 的时间也比较长

Linux Livecd 有很多好处,比如常用于修复受损的系统,可以随时随地用一台电脑启动,对于 kali linux 来说用来做好人好事不留名,很刑很好。但是目前网上相关制作资料大多很差:

  • 要么是非常古老的资料,甚至十年前还是32位的制作方法。
  • 要么一通乱写,各种命令的作用、后果完全不讲,工作目录也不管,他自己做完了而我们很难跟得上。
  • 要么很多方法早已弃用。
  • 即使是很多官方文档也多年没有更新。

我会尽可能比较详细认真地讲解一下制作方法。

Kali Linux 发行版自带 Livecd:kali-linux-2023.4-live-amd64.iso,但对于我来说,不符合我的要求。我希望的 Kali Livecd 是:

  • 有图形界面,预装微信、QQ、vscode、搜狗输入法等软件以便于使用。
  • 自带 ssh 密钥等以方便随时随地连接服务器。
  • 修改外观以使得其符合个人审美。

我摸爬滚打很长时间之后终于差不多搞明白制作方法了,我也成功制作了一个满足上述要求的 LiveCD,大概 1.6 GB(如果带上那些 kali linux 自带的网络安全方面的工具则有 4.0GB;原始 Kali Livecd 大概 4.3G),能方便地修复系统、随时工作还是很香的。我的 Livecd:https://www.cnblogs.com/KZ25T/p/18269916

最终效果:

准备材料

  • 电脑(x86_64,UEFI启动)别的情况的我不好说。
  • 电脑里有一个预装的 Linux A,有 sudo 和一定的空闲空间,建议 50GB
    • 最好是 Debian 系发行版,不是 Debian 系应该也不是大问题
    • docker 也行,wsl 应该也可以。
  • 另有预留空间以安装 Linux B,目标是把 B 制作成 LiveCD;
    • 如果只需要制作一个简单 Livecd 而不需要“把 B 制作成 Livecd”,那么就不需要 Linux B 了。
    • B 是要一个完整的操作系统,docker、wsl 不行。
    • 如果空间不足,可以使用外置硬盘。
    • B 不要求是 Debian 系。
  • 大容量(≥8GB)高速(≥usb3.0)外置存储设备,最好是移动硬盘,U盘也可以。不然做实验中,如果多次拷贝可能会比较慢。我从电脑城手里收的25块120G、50块240G SATA固态,搭配某摇一摇软件买的十块钱的 usb3.0 硬盘盒暂未翻车(翻车了也不心疼)

操作步骤

1. 安装 Linux B

我这里A 和 B 都是 Kali Linux;安装的详细过程不再细说,可以参考我其他的文章:

需要注意的事情有:

  • 只安装必要、常用的软件。
    • 图形界面安装轻量的 xfce 可以节省空间。
    • 不要安装太多,这会导致最终的 iso 过大。比如我安装 QQ、vscode、搜狗输入法以及一些上网软件,这些比较常用。
    • 至于 WPS 等软件,感觉并不会很常用,需要用的时候上网下载安装即可。
  • 修改配置文件。
    • 比如把 ssh 密钥拷贝过去:cp LinuxA/home/xxx/.ssh LinuxB/home/xxx -r 可以方便 ssh 上服务器。
    • gpg、git、vim 等同理。
    • VSCode 同步插件,并只选择常用的,删除不常用的。删除缓存。
  • 删除缓存。如 QQ 各种缓存、VSCode 加载的缓存,还有 bash 或 zsh_history 等。
  • 调整桌面环境到一个自己喜欢的状态。
  • 删除多余软件及备用内核。另外一般发行版还有初始 initramfs,备用的也要删除。
    • 更新、删除多余软件:sudo apt update + upgrade + autoremove
    • 删除 apt 缓存:sudo apt clean
    • 生成新的 initramfs:很多发行版都需要 initramfs 启动。看一下 ls /bootls /lib/modules 里,最晚的一组 vmlinuz、initrd.img 和 module 的名字,比如 initrd.img-6.5.0-kali3-amd64,重新生成它:sudo mkinitramfs -k -o /boot/initrd.img-xxxxx xxxxx,并保证其能启动。
    • 成功重启之后删除其他的 vmlinuz/initramfs/modules:sudo apt remove --purge linux-image-xxx 以及 sudo rm -rf /lib/modules/xxx,xxx 是所有不是最新的内核套件的后缀。

另外,制作 livecd 的系统貌似还需要安装 livecd 专用工具,包括 live-toolslive-boot(apt直接安装)

我感觉……大概装完这些就好了。

总之,B 应该是在干净和实用中取一个平衡的位置。我这里强调了干净这一点。此时我的系统大约 18GB;

2. 复制操作系统 B

在 A 中找个位置把 B 的所有文件拷贝进来:

sudo mount B分区 B挂载位置 # 挂载
sudo mkdir /LinuxB # 找个位置
sudo cp -rp B挂载位置 /LinuxB # 保存全部权限

进一步清一下缓存,或者一些不需要的东西。不会清就算了,不是大问题。

3. 利用 Debian Live-build 制作简单的 Debian Livecd

sudo apt install live-build

Debian 官方制作工具,不过看起来好些年了,也确实可能有点问题。

其他发行版:该软件包依赖于 debootstrap,除此之外看样子没有太多奇怪的依赖,可以在别的地方 apt download 搞来包之后手动解包安装,或者开个 docker 也行。

sudo mkdir /live # 随便找个位置
cd /live
sudo lb clean # 不知道为什么用这个名,这一步生成了 .build
sudo lb build # 先别急着做

按照官方文档,最后一步执行完之后就能在 /live 下生成一个 livecd iso了,但看样子它可能有不少问题。而且 lb 的脚本过于复杂,看不懂,于是就一路到处尝试。这里我遇到几个问题,几乎全是 apt:

  • 首先是 apt 源。其直接使用默认 apt 源下载,也没找到什么配置的地方。所以速度特别慢。以下是一种解决办法:sudo lb build 之后大概一两秒之后就会显示一行文字:

    I: Retrieving InRelease
    

    然后就开始慢了。按 ctrl+c 中断。经过我的十几次尝试,发现 config/bootstrap 出现了一堆疑似软件源的链接,改了就能好一些,比如选择科大源

    sudo sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' ./config/bootstrap
    

    回去重新 build 有些地方就快了。

    如果你去看了一下这个文件的内容,可能会发现里边还有 Debian security 的链接,我也尝试换源了,但是换完之后就一堆 verify error,不换就特别慢,暂时没找到啥好的办法。

  • 第二个还是 apt 源,此 apt 源非彼 apt 源。等到 ./chroot 初步形成基本目录的时候(忘了啥时候了),你可能会发现其 /etc/apt/sources.list 里还是 deb.debian.org,这个文件还得换,

    sudo sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' ./chroot/etc/apt/sources.list
    

    换完之后重新 build;

  • 第三个还是 apt 源,因为 Debian 过于追求干净所以有的包在 main 仓库里不存在,忘了什么时候了,大概是第一次出问题停下来的时候(个人感觉越早越好,上一步可以接着这个),把 non-free 加到软件源的每一行里:

    sudo sed -i 's/$/ non-free/g' ./chroot/etc/apt/sources.list
    

    记得看看文件内容,检查一下是不是改错了。

    chroot 进去,apt update,回来重新 build

  • 第四个还是 apt,有几次停下来是因为找不到包(即使上边加上 non-free 了),这时候手动 chroot 去装。感觉应该是这个工具太老了所以有的包名字有变化,自己 apt search 一下找找正确的包名。

大概经历这些千辛万苦之后就会在工作目录下出现一个 live-image-amd64.hybrid.iso,你就可以拿它去刻录到硬盘/U盘上启动了:

sudo dd if=live-image-amd64.hybrid.iso of=/dev/sda # 移动硬盘位置,lsblk查看,别搞错了

这里分享一下我做出来的:百度网盘 大概 175MB,你的制作过程可能比从这里下载还慢。

这个 livecd 没法挂载 ext4,没法连 WiFi,甚至找不到无线网卡。甚至它还没有 dhcp,有线网也几乎上不了。所以这个只能证明理论上可以启动,实用性几乎没有。

4. 对于构建 iso 的探索

这一步很多内容不影响你最终的 livecd 生成,但我建议你看

我们需要知道这个 iso 是咋生成的。

首先,在 /live 下大概有这些东西:

$ ls -A .
auto                        chroot                   live-image-amd64.contents          live.zip         
binary                      chroot.files             live-image-amd64.files             local            
binary.modified_timestamps  chroot.packages.install  live-image-amd64.hybrid.iso
.build                      chroot.packages.live     live-image-amd64.hybrid.iso.zsync                   
cache                       config                   live-image-amd64.packages

其中是目录的是:

auto  binary .build  cache  chroot  config  local

首先 chroot 正如其名就是像个操作系统根目录。

然后我们试试打开 iso 看看内容,比对一下这里的内容,会发现它和 binary 里的东西十分甚至九分的相似:

$ ls -A binary                               
boot  .dist  EFI  efi.img  isolinux  live  sha256sum.README  sha256sum

在 .disk 里我们就会发现这样一个东西:

$ ls binary/.disk/
archive_trace  info  mkisofs

前两个貌似没什么用,最后一个打开看像是一个生成 iso 的命令:

$ cat binary/.disk/mkisofs 
xorriso -as mkisofs -R -r -J -joliet-long -l -cache-inodes -iso-level 3 -isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin -partition_offset 16 -A "Debian Live" -p "live-build 20230502+kali2; https://salsa.debian.org/live-team/live-build" -publisher "Debian Live project; https://wiki.debian.org/DebianLive; debian-live@lists.debian.org" -V "Debian bullseye 20231212-21:32" --modification-date=2023121213324700 -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot --efi-boot boot/grub/efi.img -append_partition 2 0x01 binary/boot/grub/efi.img -o live-image-amd64.hybrid.iso binary

试了一下,执行这个命令确实能打包生成 iso,而且各种引号里的东西都能随便改,modification-date 也能随便改,于是我用这个命令生成:

sudo xorriso -as mkisofs -R -r -J -joliet-long -l -cache-inodes -iso-level 3 -isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin -partition_offset 16 -A "myLive" -p "myBuild" -publisher "myName" -V "myLiveVolume" --modification-date=2023121300000000 -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot --efi-boot boot/grub/efi.img -append_partition 2 0x01 binary/boot/grub/efi.img -o my.iso binary

确实能生成 my.iso ,dd刻录之后成功启动。很多参数咱也看不懂(之前我用过好多次 xorriso 都经常出各种问题,这个倒是没啥问题),先不管那么多,接下来就用这个命令生成 iso 即可。

刚发现 CSDN 上了一个自动注释功能,这是它写的注释,我没去查证真实性,也先不用管:

sudo xorriso -as mkisofs \
-R -r -J -joliet-long -l -cache-inodes -iso-level 3 \    # 设置ISO文件系统的选项
-isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin \          # 设置ISO的引导方式为isohybrid
-partition_offset 16 \                                   # 设置分区偏移量
-A "myLive" \                                            # 设置卷标
-p "myBuild" \                                           # 设置预发行者
-publisher "myName" \                                    # 设置发布者
-V "myLiveVolume" \                                      # 设置卷名
--modification-date=2023121300000000 \                   # 设置修改日期
-b isolinux/isolinux.bin \                               # 设置ISO引导文件
-c isolinux/boot.cat \                                   # 设置启动目录
-no-emul-boot \                                          # 设置光盘启动模式
-boot-load-size 4 \                                      # 设置引导加载大小
-boot-info-table \                                       # 启用引导信息表
-eltorito-alt-boot --efi-boot boot/grub/efi.img \        # 设置EFI引导文件
-append_partition 2 0x01 binary/boot/grub/efi.img \      # 添加一个符合GPT标准的引导分区
-o my.iso binary                                         # 输出的ISO文件名

最后一条肯定不对,binary 是源文件的目录名。

我们再来看看 binary 有什么(省略了部分文件):

$ tree binary -a
binary/
├── boot
│   └── grub
│       ├── config.cfg
│       ├── efi.img
│       ├── grub.cfg
│       ├── i386-efi
│       │   ├── acpi.mod
│       │   │   (省略)
│       │   └── zstd.mod
│       ├── live-theme
│       │   └── theme.txt
│       ├── loopback.cfg
│       ├── theme.cfg
│       ├── unicode.pf2
│       └── x86_64-efi
│           ├── acpi.mod
│           │   (省略)
│           └── zstd.mod
├── .disk
│   ├── archive_trace
│   ├── info
│   └── mkisofs
├── EFI
│   └── boot
│       ├── bootia32.efi
│       ├── bootx64.efi
│       └── grubx64.efi
├── efi.img
├── isolinux
│   ├── hdt.c32
│   │    (省略了一些 c32)
│   ├── isolinux.bin
│   ├── isolinux.cfg
│   ├── live.cfg
│   ├── menu.cfg
│   ├── splash800x600.png
│   ├── splash.png
│   ├── stdmenu.cfg
│   ├── utilities.cfg
│   └── vesamenu.c32
└── live(好像还有点别的东西,但我删了)
    ├── filesystem.squashfs
    ├── initrd.img
    ├── initrd.img-xxx
    ├── vmlinuz
    └── vmlinuz-xxx

10 directories, 546 files

像这些 EFI 文件,咱也不知道都有啥用,不敢动。其他的就是像 grub 里常见的配置文件,会改 grub 的可以自己改一下配置,换个自己喜欢的主题。像我改成了纯色:

$ sudo vim binary/boot/grub/live-theme/theme.txt
文字颜色什么的
top 什么的也可以自己改

还有这里边的 desktop-image 貌似并不能去掉,去了之后启动报错(不过也能启动),于是生成透明的 png 图片,替代 isolinux 下面的两张图:

# chatgpt 告诉我的
ffmpeg -f lavfi -i color=c=black@0:size=800x600,format=rgba -frames:v 1 binary/isolinux/splash800x600.png
ffmpeg -f lavfi -i color=c=black@0:size=640x480,format=rgba -frames:v 1 binary/isolinux/splash.png

换成透明图之后,grub 启动页面背景变黑了,这不重要,看起来十分具有 unix 遗风。

于是我又换了个表情包当背景:

结果全屏了:

试了一下, ffmpeg 可以调整亮度,调完了正常一些:

ffmpeg -i in1.png -vf "eq=brightness=-0.5" out1.png

把两张图都调完之后正常一点:

此处设置的未选中颜色是 #ffffff,选中颜色是 #66ccff

又试了一下,看样子似乎并不要求图像尺寸。

grub 的修改就到此为止。

然后我们发现 live 里的 initrd.img 和 vmlinuz 分别有两个,diff 一下还都一样,于是猜测分别删一个,只留下短的。里边的 filesystem.squashfs 开头的文件,除了那个最大的(就是不带任何后缀)别的可以试一下都删了也没问题。于是 live 下面就留了三个文件:

$ ls binary/live
filesystem.squashfs  initrd.img  vmlinuz

记得把 grub 选项也给改了:

$ sudo vim binary/boot/grub/grub.cfg
# 把每一项的 linux 和 initrd 那两行的文件都给改了,就是把 initrd.img-xxx 和 vmlinuz-xxx 后缀去掉

除此之外,各种什么 md5 之类的都可以删,.disk 里的 archive_trace 和 mkisofs 也可以删,info 删了就爆炸,不过好像内容可以随便写,不知道为什么。最后用上边那个超长 xorriso 命令打包,试一下能不能启动,看来是可以的。

以上都是我启动了几十遍 livecd 试出来的结果

于是我们可以总结出最简 binary 目录结构:

binary/
├── boot
│   └── grub
│       ├── config.cfg
│       ├── efi.img
│       ├── grub.cfg(一定要改)
│       ├── i386-efi(省略)
│       ├── live-theme
│       │   └── theme.txt(可以自己改)
│       ├── loopback.cfg
│       ├── theme.cfg
│       ├── unicode.pf2
│       └── x86_64-efi(省略)
├── .disk
│   └── info(必须有,但内容疑似随便写)
├── EFI
│   └── boot
│       ├── bootia32.efi
│       ├── bootx64.efi
│       └── grubx64.efi
├── efi.img
├── isolinux
│   ├── (省略了一些 c32,不知道干啥的)
│   ├── isolinux.bin
│   ├── isolinux.cfg
│   ├── live.cfg
│   ├── menu.cfg
│   ├── splash800x600.png(可以改)
│   ├── splash.png(可以改)
│   ├── stdmenu.cfg
│   └── utilities.cfg
└── live
    ├── filesystem.squashfs(文件系统)
    ├── initrd.img         (大部分发行版都有的启动 ramfs)
    └── vmlinuz            (内核)

5. 对于构建 squashfs 的探索

毋庸置疑,这里的 squashfs 是用 chroot 内的内容构造的。那么是如何构造的?

虽然我没找到构造命令,但是注意到:

$ file binary/live/filesystem.squashfs 
binary/live/filesystem.squashfs: Squashfs filesystem, little endian, version 4.0, xz compressed, xxxxx bytes, xxxxx inodes, blocksize: 131072 bytes, created: Wed Dec 13 08:52:29 2023

可以看到是 xz 压缩。Unsquashfs 挂载看一下, diff -recursive 对比一下 chroot,几乎相同,不同的主要是把内核及 initramfs 删了。于是尝试使用这个命令:

sudo rm binary/live/filesystem.squashfs # 好像必须要先删除,否则出问题
cd chroot
sudo mksquashfs . ../binary/live/filesystem.squashfs  -comp xz -e ./vmlinuz -e ./vmlinuz.old -e ./initrd.img -e ./initrd.img.old -e ./boot/* -e ./etc/fstab -e ./etc/NetworkManager/system-connections/*
cd -

最后两项是:一个是需要排除挂载文件系统(livecd不需要按照常规系统挂载),第二个是删除网络连接配置。可以视情况自行调整。

打包刻录启动,正常启动。

为了能上网,我们试试 chroot 进去安装:

$ sudo chroot live
(live) $ apt install net-tools wireless-tools iw iwd wpasupplicant # 大概是这几样东西
(live) $ # 按 ctrl+D 退出

制作 squashfs,打包刻录启动,正常启动后可以上网。

6. 把系统 B 制作成 livecd

先看一下我的最终结果:

$ file my.iso
my.iso: ISO 9660 CD-ROM filesystem data (DOS/MBR boot sector) 'KaliLive' (bootable)
$ ll my.iso 
-rw-r--r-- 1 root root 5.1G 12月14日 08:55 my.iso
$ md5sum my.iso 
56b8416bd11d6fc4845d2d054302ec01  my.iso

至此,看样子 livecd 只差仿照 5 这一步,只差 live 里的三个文件了。我们把 B 进行类似的操作:

$ cd /LinuxB
$ sudo mksquashfs . /live/binary/live/filesystem.squashfs  -comp xz -e ./vmlinuz -e ./vmlinuz.old -e ./initrd.img -e ./initrd.img.old -e ./boot/* -e ./etc/fstab -e ./etc/NetworkManager/system-connections/*
$ sudo cp boot/vmlinuz-xxx /live/binary/live/vmlinuz
$ sudo cp boot/initrd.img-xxx /live/binary/live/vmlinuz

接下来需要注意的就是 grub 引导参数。以我的 kali 为例,正常的系统的启动引导参数:

$ vim -R /boot/grub/grub.cfg
# 观察正常启动的选项中,linux 开头的那一行。我的是:
# linux /boot/vmlinuz-xxx root=UUID=xxx ro quiet split_lock_detect=off splash

kali 有 livecd,可以从网上下载 kali livecd 看一下引导参数:

# 打开 kali 原装 livecd 的 iso,看 boot/grub/grub.cfg
# menuentry "Live system (amd64)" --hotkey=l {                                                         
# 	linux   /live/vmlinuz-xxx boot=live components quiet splash noeject findiso=${iso_path}
# 	initrd  /live/initrd.img-xxx
# }

再看一下我们制作的 Debian Livecd 的引导参数:

$ cat binary/boot/grub/grub.cfg
# menuentry "Live system (amd64)" --hotkey=l {
#	linux   /live/vmlinuz boot=live components quiet splash findiso=${iso_path}
#	initrd  /live/initrd.img
# }

综合对比一下,自己选一个合适的参数,修改 binary/boot/grub/grub.cfg 相应位置。我这里直接选择了 kali livecd 的选项,也就是 debian 的引导参数加上 noeject 一项,其实我并不只是每一项都是啥意思,但这样其实也确实能启动。

另外,fall-safe mode 的参数也可以同样适当修改。

打包刻录启动测试,一气呵成,成功。

7. 听说有的人完全没学会,卡在第3步?

那我给一个最简单的方法:

对于 binary 目录,如果都是 x86_64 电脑,那么我们做出来应该都一样。我直接把我做的 binary 献上来:百度网盘,只有 8MB(删了 binary/live 里需要自己填的 3 个文件,下载很快),不过这里已经是我(针对自己的需求)调整过 grub 外观和引导参数,并删除我能找出来的多余文件的。

现在你需要做的是:

  1. 解压文件:
    sudo mkdir /live
    sudo unzip live.zip -d /live
    sudo mv /live/live/binary /live
    sudo rmdir /live/live
    # 现在 /live 下,应该只有一个 binary
    
  2. 按照第 1、2 步构造 B
  3. 复制 B 的相关文件到 live 里:
    cd /LinuxB
    sudo mksquashfs . /live/binary/live/filesystem.squashfs  -comp xz -e ./vmlinuz -e ./vmlinuz.old -e ./initrd.img -e ./initrd.img.old -e ./boot/* -e ./etc/fstab -e ./etc/NetworkManager/system-connections/*
    sudo cp boot/vmlinuz-xxx /live/binary/live/vmlinuz
    sudo cp boot/initrd.img-xxx /live/binary/live/initrd.img
    
  4. 根据你的实际情况,调整 /live/binary/boot/grub/grub.cfg 的引导参数和 grub 外观、
  5. 打包:
    cd /live/binary
    sudo xorriso -as mkisofs -R -r -J -joliet-long -l -cache-inodes -iso-level 3 -isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin -partition_offset 16 -A "myLive" -p "myBuild" -publisher "myName" -V "myLiveVolume" --modification-date=2023121300000000 -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot --efi-boot boot/grub/efi.img -append_partition 2 0x01 binary/boot/grub/efi.img -o my.iso binary
    
  6. 刻录,启动:
    sudo dd if=/live/my.iso of=/dev/sda # of 是外置 USB 移动硬盘或 U 盘的设备名
    
    重启后选择外置 USB 设备启动,方法根据电脑品牌自己查。
posted @ 2024-06-26 20:58  KZ25T  阅读(403)  评论(0编辑  收藏  举报