背景
在以往的 Ubuntu 版本中,如果在安装时手动将根分区格式化为 BTRFS,旧版安装程序(Ubiquity)会自动为我们创建 @(用于根目录)和 @home(用于家目录)这两个标准的子卷(Subvolume)。这种标准的子卷结构是著名系统备份工具 Timeshift 能够开启 BTRFS 模式(秒级快照)的强制前提。
然而,Ubuntu 24.04 启用了全新的系统安装器。这个新安装器在处理 BTRFS 时存在一个极大的局限性:它不支持直接生成标准的 BTRFS 子卷布局。
如果你在新安装器中直接选择“手动分区”并将根目录挂载为 BTRFS,它会把整个系统直接“铺平”安装在 BTRFS 的**顶层(Top Level, ID 5)**上,而不会创建任何子卷。
致命后果:安装完成后,由于缺少 @ 子卷,Timeshift 的 BTRFS 快照模式无法正常工作,导致无法体验 BTRFS 最核心的“时光机回滚”功能。
本教程的目的,就是通过“先正常安装 -> 在 Live USB 中把系统搬进子卷 -> 手动修复 fstab 与引导”的方案,规避 Ubuntu 24.04 安装器的缺陷。
方案简介
本指南旨在物理机上部署一套具备企业级数据安全特性的 Ubuntu 桌面系统。 核心特性包括:
- BTRFS 文件系统:利用写时复制 (CoW) 特性保护数据。
- 子卷结构 (
@/@home):标准的 Ubuntu BTRFS 布局,完美兼容 Timeshift。 - 透明压缩 (ZSTD):大幅提升 SSD 寿命和 I/O 性能。
- 秒级快照 (Timeshift):无论系统如何损坏,均可瞬间回滚。
- GRUB 快照启动:在开机引导菜单直接选择历史快照进入系统。
准备工作
- Ubuntu 24.04 LTS 安装镜像 (USB 启动盘)。
- 目标物理机(建议备份好重要数据,安装过程将清空硬盘)。
第一阶段:基础系统安装
目的:先让 Ubuntu 安装程序把系统装进 BTRFS 分区中(此时处于非标准的顶层状态)。
-
使用 USB 启动盘引导,选择 “Try Ubuntu” (试用 Ubuntu) 进入 Live 桌面环境。
-
自动进入安装程序界面,按照常规步骤选择。
-
在“安装类型”步骤,选择 “Manual installation” (手动安装 / Something else)。
-
配置分区表 (假设是空盘,需新建分区表):
- p1 (EFI): 512MB - 1GB,格式化为 FAT32,Use as:
EFI System Partition(选择启动设备会自动创建 EFI 分区)。
- p2 (Swap): (可选) 建议与物理内存大小一致,格式化为
swap。 - p3 (Root): 剩余空间,格式化为
btrfs,挂载点设为/(根目录)。勾选“格式化此分区”。
- p1 (EFI): 512MB - 1GB,格式化为 FAT32,Use as:
-
继续执行安装,等待进度条走完。
-
选择Continue Testing" (继续试用)
安装完成后,当提示重启时,请务必选择 "Continue Testing" (继续试用)!
第二阶段:子卷结构迁移
目的:系统刚刚装好,非常干净。我们要在 Live USB 环境下,将原本位于顶层的系统文件安全、完整地“复制”到标准的 @ 和 @home 子卷中。
打开终端 (Terminal),执行以下命令获取管理员权限并确认磁盘分区:
sudo -i
#
lsblk
卸载残留挂载点并进行结构迁移:
卸载安装程序残留的挂载点
umount -R /target
干净地挂载 BTRFS 根分区到 /mnt (请根据 lsblk 的结果替换设备名)
物理机可能是 /dev/nvme0n1p3,虚拟机可能是 /dev/vda3
mount /dev/vda3 /mnt
创建标准的 Ubuntu 子卷
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
使用rsync将系统文件同步到子卷:
rsync -aAXv --exclude={'/@','/@home','/home'} /mnt/ /mnt/@/
将原本家目录下的内容复制入 @home 子卷
rsync -aAXv /mnt/home/ /mnt/@home/
清理顶层的旧文件
cd /mnt
#
shopt -s extglob
#
rm -rf !(@|@home)
再次列出目录确认,此时应该只有 @ 和 @home 两个项目
ls -a
第三阶段:配置 fstab 与修复引导 (Chroot)
目的:文件结构已经完美,现在必须修改系统配置,告诉 GRUB 引导器和内核系统已经搬家到了 @ 子卷。
修改 fstab 配置
nano /mnt/@/etc/fstab
找到挂载 / 和 /boot/efi 的行:
- 为
/的挂载选项添加subvol=@以及透明压缩compress=zstd:1。 - 复制
/的那一行,把挂载点改为/home,选项改为subvol=@home,compress=zstd:1。
修改后的 fstab 大致如下:
# 根目录
UUID=... / btrfs defaults,subvol=@,compress=zstd:1 0 1
# 家目录 (需手动添加)
UUID=... /home btrfs defaults,subvol=@home,compress=zstd:1 0 2
# EFI 分区 (保留原样不动)
UUID=... /boot/efi vfat ...
(保存:Ctrl+O, 回车, Ctrl+X)
挂载虚拟文件系统并进入 Chroot
先卸载刚才的顶层挂载
umount -R /mnt
直接挂载 @ 子卷到 /mnt 挂载 EFI 分区 (非常重要,假设是 p1,虚拟机为 /dev/vda1)
mount -o subvol=@ /dev/vda3 /mnt
#
mount /dev/vda1 /mnt/boot/efi
挂载必要的系统接口目录 (如果是 UEFI 启动,通常还需要挂载 efivars,防止 grub-install 报错找不到 EFI 变量)
#
mount --bind /dev /mnt/dev
mount --bind /dev/pts /mnt/dev/pts
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
mount --bind /run /mnt/run
#
mount --bind /sys/firmware/efi/efivars /mnt/sys/firmware/efi/efivars
为了重新生成引导,需要使用chroot进入刚装好的系统:
# 进入系统
chroot /mnt
更新并重装 GRUB
在 chroot 环境中执行以下命令修复引导:
将 grub 重新安装到物理硬盘 (注意:这里是整个磁盘如 nvme0n1 或 vda,不带分区号)
grub-install /dev/vda
更新 grub 菜单 (它会自动识别 rootflags=subvol=@)
update-grub
如果输出 Installation finished. No error reported. 说明成功。
退出chroot并重启机器
exit
umount -R /mnt
reboot
第四阶段:部署Timeshift & GRUB快照
验证btrfs文件系统是否成功
打开终端,输入:
sudo btrfs subvolume list /
如果输出包含 path @ 和 path @home,说明配置Btrfs设置成功。
安装并配置 Timeshift
sudo apt update
sudo apt install timeshift -y
打开 Timeshift 并按照引导进行配置,
选择 Btrfs快照模式
选择Btrfs的分区
选择自动快照(每日快照+每次启动生成快照)
选择快照包含@home卷
完成配置
点击create 手动创建快照
快照创建
安装 GRUB 启动菜单集成
安装 grub-btrfs 后,允许你在开机 GRUB 菜单中直接选择历史快照启动。
安装git make inotify-tools依赖
sudo apt install git make inotify-tools -y
下载并 编译安装 grub-btrfs
cd ~
git clone https://github.com/Antynea/grub-btrfs.git
cd grub-btrfs
sudo make install
为守护进程添加 Timeshift 兼容配置:
(通过创建 systemd override 文件,安全覆盖默认的 /.snapshots 监控路径)
sudo mkdir -p /etc/systemd/system/grub-btrfsd.service.d
echo -e "[Service]\nExecStart=\nExecStart=/usr/bin/grub-btrfsd --syslog --timeshift-auto" | sudo tee /etc/systemd/system/grub-btrfsd.service.d/override.conf
修复 Ubuntu UUID 读取问题
问题描述:grub-btrfs 的探测脚本使用 awk 提取 UUID 时使用了 \s 正则表达式。但 Ubuntu 默认使用的是轻量级的 mawk 工具,不支持 \s 语法,导致提取失败并提示 UUID of the root subvolume is not available。
解决办法:修改脚本,将正则表达式替换为通用的兼容写法。
编辑探测脚本:
sudo nano /etc/grub.d/41_snapshots-btrfs
使用 Ctrl+W 搜索 ^\s*UUID 定位到代码。将代码中的 /^\s*UUID/ 替换为 /^[ \t]*UUID/。修改后如下所示:
root_uuid_subvolume="$(btrfs subvolume show / 2>/dev/null | \
awk -F':' '/^[ \t]*UUID/ {gsub(/^[ \t]+/, "", $2); print $2}')"
重新加载配置并启用后台监控服务:
sudo systemctl daemon-reload
sudo systemctl enable --now grub-btrfsd
查看 当前grub-btrfsd服务状态正常监控到快照
sudo systemctl status grub-btrfsd
手动更新grub查看启动项正常识别并生成
sudo update-grub
恢复指南
如果系统因误操作或更新导致黑屏、卡 Logo,可按以下步骤恢复:
- 强制重启,在 BIOS/Logo 界面后狂按
Esc或按住Shift调出 GRUB 菜单。 - 在菜单中选择 “Ubuntu snapshots"。
- 选择最近一次状态正常的快照(按日期排序)。
评论