btrfs-convert 可以把现有的 ext2/3/4 文件系统原地转换为 Btrfs,不需要先删除分区再重装系统。但它仍然是一次高风险的磁盘操作:转换会重写文件系统元数据,断电、设备选错、备份不可用或引导配置没有更新,都可能让系统无法启动甚至丢失数据。
这篇文章记录一套适合公开分享、也适合自己照着执行的流程。示例环境是 Debian 13(trixie)、x86_64、UEFI、GRUB,以及一块 NVMe 磁盘上的 ext4 根分区。命令中的设备名和 UUID 只代表示例,必须以你在 Live 环境中重新执行的检查结果为准。
先说结论:什么时候不要做
如果重要数据只有 Ventoy U 盘上的一份备份,建议先暂停转换。这个 U 盘既是备份介质,又是唯一的救援启动介质,属于明显的单点故障。把 ISO 文件复制到 Ventoy 数据分区本身不会格式化 U 盘,但它不能替代第二份独立备份;U 盘损坏时,备份和 Live 环境可能同时失效。
至少满足下面条件后再继续:
- 重要数据有另一份独立副本,或者已经从现有备份实际恢复过几个重要文件并确认可用;
- 能在 Ventoy 中启动 Linux Live ISO,并确认是 UEFI 模式;
- 根分区没有加密、LVM、软 RAID、硬件 RAID 或复杂的多层存储映射;
- 目标分区能完全卸载,
fsck.ext4检查没有待修复错误; - 愿意保留
ext2_saved一段时间,并在确认系统和备份正常前不执行 balance。
官方文档也提醒,原地转换依赖源文件系统的空闲空间,无法事先精确估算所需空间;如果可以接受重新分区和复制数据,重新格式化为 Btrfs 再从备份恢复通常更干净。Btrfs btrfs-convert 文档把这种方案列为应当考虑的替代方案。
我的本地环境
本文写作时检查到的环境如下:
| 项目 | 当前值 |
|---|---|
| 系统 | Debian GNU/Linux 13(trixie) |
| 内核 | 6.12.85,x86_64 |
| 启动方式 | UEFI |
| 系统盘 | /dev/nvme0n1,约 954 GiB |
| EFI 系统分区 | /dev/nvme0n1p1,约 976 MiB,vfat,挂载到 /boot/efi |
| 根分区 | /dev/nvme0n1p2,约 921 GiB,ext4,挂载到 / |
| 交换分区 | /dev/nvme0n1p6,约 31.7 GiB |
| 根分区使用量 | 约 447 GiB / 906 GiB,52% |
| 根分区 UUID | b81fd5ad-9c5f-4b60-9ae1-d884ab37145d |
| EFI UUID | D941-6C56 |
| 当前启动项 | Debian 的 shimx64.efi |
这个布局意味着本次转换的对象只有 /dev/nvme0n1p2。EFI 分区、交换分区和分区表不需要转换,/home 也在根分区里面,因此根分区转换会同时覆盖系统文件和 /home 中的文件。
本机当前没有安装 btrfs-progs,所以不能在已启动的系统里直接执行 btrfs-convert;转换工具应该从 Live 环境提供,转换完成后还要把 btrfs-progs 安装进目标 Debian 系统。GRUB 文件实际位于 /usr/sbin/grub-install,只是当前普通用户的 PATH 没有包含 /usr/sbin,不要仅凭 command -v 的结果判断 GRUB 是否安装。
一、准备 Ventoy Live 环境
1. 下载并校验 ISO
对于这台 Debian 13 amd64 机器,可以从 Debian Live 官方页面 下载 amd64 Live ISO。桌面版比较大,标准版比较小;转换时只要能进入终端、联网安装工具即可。
下载 ISO 后,先计算校验和,并与 Debian 发布目录中的 SHA256SUMS 对比:
sha256sum debian-live-13*-amd64-*.iso
不要跳过校验。ISO 下载不完整或被替换,会让唯一的救援介质变得不可靠。
2. 把 ISO 复制到 Ventoy 数据分区
确认插入的是 Ventoy U 盘后再执行:
lsblk -e7 -o NAME,PATH,MODEL,SIZE,TYPE,FSTYPE,LABEL,UUID,MOUNTPOINTS
findmnt -D
Ventoy 的数据分区通常是 exFAT、NTFS 或 ext4。把 ISO 作为普通文件复制到这个数据分区,不要对整个 U 盘执行 dd,也不要运行任何格式化命令。复制完成后执行 sync。
本文开始检查时没有检测到已插入的 Ventoy 设备,说明不能凭当前系统输出推断 U 盘的设备名。插入后必须重新运行 lsblk;尤其不要把 /dev/nvme0n1 或 /dev/nvme0n1p2 误认为 U 盘。
3. 从 UEFI 模式启动 Live ISO
重启,在固件启动菜单中选择带有 UEFI 字样的 USB/Ventoy 项,再选择 Live ISO。进入终端后确认:
test -d /sys/firmware/efi && echo "UEFI mode" || echo "Legacy BIOS mode"
如果输出是 Legacy BIOS,先重启并改用 UEFI 项。当前机器的启动项是 Debian 的 shimx64.efi,不要在 Legacy 模式下进行转换。
二、进入 Live 环境后的安全检查
1. 安装或确认工具
Live 环境可能没有预装 Btrfs 工具。连接网络后执行:
sudo apt update
sudo apt install btrfs-progs e2fsprogs efibootmgr
btrfs --version
btrfs-convert --version
fsck.ext4 -V
efibootmgr -v
如果 Live 环境没有网络,要么换一个带工具的 Live ISO,要么提前准备好 btrfs-progs 及其依赖。在无法安装目标系统所需工具之前,不要重启进入转换后的系统。
2. 重新识别目标分区
在原系统中可以先记录自己的 /etc/fstab;进入 Live 后,下面这些命令用于重新识别磁盘,不要直接照抄本文 UUID。注意:Live 环境里的 /etc/fstab 属于 Live 系统,不是硬盘上的 Debian;目标系统的 fstab 要在后面挂载到 TARGET 后再读取。
lsblk -e7 -o NAME,PATH,MODEL,SIZE,TYPE,FSTYPE,FSVER,LABEL,UUID,MOUNTPOINTS,PARTUUID
findmnt -no SOURCE,TARGET,FSTYPE,OPTIONS /
findmnt -no SOURCE,TARGET,FSTYPE,OPTIONS /boot/efi
swapon --show
本文对应的机器应类似于:
/dev/nvme0n1p1 vfat /boot/efi
/dev/nvme0n1p2 ext4 /
/dev/nvme0n1p6 swap [SWAP]
如果设备名、容量、挂载点或文件系统类型有任何不同,停止并重新判断。 /dev/sda、/dev/nvme0n1、/dev/nvme0n1p2 不是可以互换的写法。
3. 检查备份和空间
转换前至少保存并核对 /home 中的重要文档、照片、代码和密钥,以及 ~/.ssh、GPG 密钥、服务配置和数据。也应保存 /etc、/etc/fstab 和已安装软件清单。
df -hT /
sudo cp -a /etc/fstab /path/to/your/backup/fstab.before-btrfs
dpkg --get-selections > /path/to/your/backup/dpkg-selections.before-btrfs.txt
把 /path/to/your/backup 换成备份介质上的实际路径。仅仅看到备份文件存在不等于备份可恢复,至少要抽查并打开几个重要文件。
转换利用 ext4 的空闲空间。当前根分区使用率约 52%,比接近满盘宽裕,但这不是成功保证;所需空间取决于文件布局和元数据。空间紧张时只能清理可重新下载的缓存,不要为了挤空间删除尚未备份的重要文件。
三、卸载根分区并检查 ext4
假设已经确认设备,先写入变量。下面的值只适用于本文记录的本地环境:
ROOT_DEV=/dev/nvme0n1p2
ESP_DEV=/dev/nvme0n1p1
SWAP_DEV=/dev/nvme0n1p6
TARGET=/mnt/ext4-to-btrfs
printf 'root=%s\nesp=%s\nswap=%s\n' "$ROOT_DEV" "$ESP_DEV" "$SWAP_DEV"
lsblk -o PATH,SIZE,TYPE,FSTYPE,MOUNTPOINTS "$ROOT_DEV" "$ESP_DEV" "$SWAP_DEV"
Live 桌面可能自动挂载内部磁盘。先查看并卸载对应挂载点:
findmnt -S "$ROOT_DEV"
findmnt -S "$ESP_DEV"
sudo swapoff "$SWAP_DEV"
确保根分区完全卸载后,执行强制检查:
sudo fsck.ext4 -f "$ROOT_DEV"
只有检查完成且没有待修复错误时才能继续。如果 fsck 修复了问题,修复后再运行一次;如果检查失败、要求人工处理或报告硬件 I/O 错误,停止转换。
四、执行原地转换
这是风险最高的一步。转换前再次确认目标分区未挂载、备份可恢复、Live 以 UEFI 启动,且笔记本接通电源。然后执行:
sudo btrfs-convert --progress "$ROOT_DEV"
等待命令完整结束并返回成功。不要在进度停顿时反复按 Ctrl+C,也不要在失败后直接重试;转换耗时可能从几分钟到数小时。
转换成功后,Btrfs 中会保留名为 ext2_saved 的原 ext4 元数据镜像。转换成功不代表可以立刻重启,要先验证文件并修正启动配置。
转换异常与回滚
出现错误时先保存终端输出,保持分区不变,不要运行 fsck.ext4、mkfs.btrfs、balance 或压缩命令。
在 ext2_saved 仍然存在、且没有改变转换后 Btrfs 布局的操作时,官方提供了回滚方式:
sudo btrfs-convert --rollback "$ROOT_DEV"
回滚会丢弃转换后的 Btrfs 改动。特别要记住:准备回滚时不要执行 balance;官方文档明确指出,balance 会改变 extent 布局,使原地回滚不可用。如果错误状态不明确,不要猜测,优先保留现场并从独立备份恢复。
五、挂载并验证结果
sudo mkdir -p "$TARGET"
sudo mount "$ROOT_DEV" "$TARGET"
sudo mkdir -p "$TARGET/boot/efi"
sudo mount "$ESP_DEV" "$TARGET/boot/efi"
findmnt "$TARGET"
sudo btrfs filesystem show "$TARGET"
sudo btrfs filesystem usage "$TARGET"
sudo btrfs subvolume list "$TARGET"
sudo ls -la "$TARGET"
sudo ls -la "$TARGET/ext2_saved"
随机打开或校验几个重要文件,尤其是 /home 下的大文件和密钥文件。转换后的 Btrfs UUID 通常会与原 ext4 UUID 不同:
NEW_UUID=$(sudo blkid -s UUID -o value "$ROOT_DEV")
printf 'new Btrfs UUID=%s\n' "$NEW_UUID"
sudo blkid "$ROOT_DEV"
如果 blkid 没有输出,先不要修改 fstab,检查挂载和 btrfs filesystem show 的结果。
六、修改 Debian 的 fstab
先备份并编辑目标系统配置:
sudo cp -a "$TARGET/etc/fstab" "$TARGET/etc/fstab.before-btrfs"
sudoedit "$TARGET/etc/fstab"
当前根分区行类似:
UUID=b81fd5ad-9c5f-4b60-9ae1-d884ab37145d / ext4 errors=remount-ro 0 1
转换后改成下面的结构,把新 UUID 填入:
UUID=<NEW_BTRFS_UUID> / btrfs compress=zstd:3 0 0
UUID=D941-6C56 /boot/efi vfat umask=0077 0 0
UUID=d316d907-75d8-40b1-a747-1187b8ad8b35 none swap sw 0 0
要点是:根分区类型改为 btrfs;根 UUID 使用新值;Btrfs 根分区最后一列设为 0。当前 ext4 行的 errors=remount-ro 不要原样保留。 compress=zstd:3 是可选参数,也可以首次启动时先去掉,确认成功后再加入;它不会自动压缩转换前已经存在的数据。
如果 fstab 使用的是 PARTUUID,转换文件系统通常不会改变 GPT 分区表里的 PARTUUID,但仍要以实际检查为准。EFI 和 swap 的行不要无故改动。
七、chroot、initramfs 与 GRUB
把 Live 环境的设备、伪文件系统和运行时目录绑定到目标系统:
for dir in /dev /dev/pts /proc /sys /run; do
sudo mount --rbind "$dir" "$TARGET$dir"
sudo mount --make-rslave "$TARGET$dir"
done
sudo chroot "$TARGET" /bin/bash
export HOME=/root
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
当前目标系统没有 btrfs-progs,这一步不能省略:
apt-get update
apt-get install btrfs-progs
update-initramfs -u -k all
检查配置并重新生成 Debian 的 UEFI GRUB:
findmnt -no SOURCE,FSTYPE,UUID /
grep -nE 'root=|btrfs|ext4' /etc/fstab /boot/grub/grub.cfg 2>/dev/null
update-grub
当前环境使用 Debian 的 shimx64.efi。如果 EFI 文件或启动项本身需要修复,再执行:
grub-install \
--target=x86_64-efi \
--efi-directory=/boot/efi \
--bootloader-id=debian \
--recheck
update-grub
如果 grub-install 报告 EFI 变量不可用,先退出并确认 Live 是 UEFI 模式;不要在 Legacy 模式下盲目写引导器。启用 Secure Boot 时保留 Debian 的 shim-signed 和签名 GRUB。
退出并卸载:
exit
sudo umount -R "$TARGET"
sudo reboot
八、第一次启动后的验证
进入系统后,先不要删除 ext2_saved,也不要立即 balance:
findmnt -no SOURCE,FSTYPE,UUID,OPTIONS /
lsblk -f
df -hT /
sudo btrfs filesystem usage /
sudo btrfs subvolume list /
sudo btrfs device stats /
预期根分区的 FSTYPE 为 btrfs,根目录可读写,EFI 和 swap 正常。然后检查服务、桌面、网络、重要文件和常用软件。
建议做一次 scrub:
sudo btrfs scrub start -B /
sudo btrfs scrub status /
sudo btrfs device stats /
Scrub 会验证数据和元数据校验和;单磁盘 Btrfs 没有第二份副本,因此发现不可纠正错误时不能凭空恢复数据。如果出现 uncorrectable、csum 或 I/O 错误,停止大量写入,先复制还能读取的数据到独立磁盘。
至少经过几次正常重启、重要文件抽查、服务验证和一次成功 scrub 后,再考虑删除回滚镜像:
sudo btrfs subvolume delete /ext2_saved
删除后就不能再使用 btrfs-convert --rollback 回到 ext4,因此不要在刚启动成功时急着做。
九、整理、压缩、快照与维护
原地转换会继承 ext4 的数据布局,Btrfs 元数据块组可能比较碎。确认已经放弃回滚后才考虑整理;无过滤条件的 balance 会搬迁整个文件系统,耗时、耗 I/O,并需要额外工作空间。Btrfs balance 文档明确提醒 full balance 可能非常耗时。
可选的整理命令如下,首次启动不需要执行:
sudo btrfs filesystem defrag -v -r -f -t 32M /
sudo btrfs balance start -m /
sudo btrfs balance status /
compress=zstd:3 只影响之后写入的文件。如果已经完成备份、验证并删除 ext2_saved,可以只对特定目录压缩:
sudo btrfs filesystem defrag -v -r -f -czstd /home
对已经压缩的媒体、加密文件或数据库,收益可能很小;对含有快照的目录执行 defrag 也可能改变共享 extent,应该先理解子卷布局。
Btrfs 快照适合应对误删和错误更新,但同一块物理磁盘损坏时快照也会一起丢失。快照不是独立备份,重要数据仍要复制到另一块设备或另一台机器。
可以手动定期 scrub:
sudo btrfs scrub start /
sudo btrfs scrub status /
systemctl list-unit-files 'btrfs-scrub@*.timer'
sudo systemctl enable --now btrfs-scrub@-.timer
最后一条只有在前一条确实列出对应 unit 时才执行;不同发行版的 unit 名称和默认周期可能不同。
十、常见失败场景
空间不足或转换失败
不要直接删除数据、缩小分区或重试。先记录错误,确认是否仍可回滚;如果转换已经开始,不能把它当作普通命令失败。分区缩放是另一项高风险操作,必须先有独立备份并阅读针对该错误的官方说明。
能进 GRUB,但找不到根文件系统
从 Live 启动并挂载目标,检查新 UUID 是否写入 fstab:
sudo mount "$ROOT_DEV" "$TARGET"
sudo grep -n ' / ' "$TARGET/etc/fstab"
sudo blkid "$ROOT_DEV"
多数情况是仍使用旧 ext4 UUID,或 initramfs/GRUB 没重建。修正后按本文 chroot 步骤重新执行 update-initramfs -u -k all 和 update-grub。
Btrfs 出现校验错误
先停止 balance、压缩和大量写入:
sudo btrfs scrub start -B /
sudo btrfs scrub status /
sudo btrfs device stats /
dmesg -T | grep -iE 'btrfs|I/O error|checksum|csum' | tail -n 80
单盘没有冗余副本时,scrub 只能报告问题,不能保证修复。优先复制仍可读取的重要数据并检查 SSD 健康状态;不要直接使用 btrfs check --repair。
系统能启动,但回滚不了
常见原因是已经删除 ext2_saved,或者执行了 balance 改变 extent 布局。回滚能力只是临时安全网,不是完整备份;真正的数据安全来自独立、可验证的备份。
最后的执行清单
- 重要数据至少有一份独立、可恢复的备份;
- Ventoy 数据分区中已有通过校验的 Debian Live ISO;
- 已从 Ventoy 以 UEFI 模式启动;
- 已重新确认目标是
/dev/nvme0n1p2,不是整块磁盘或 U 盘; - 根分区已卸载,swap 已关闭;
-
fsck.ext4 -f没有待修复错误; - 已备份原始
fstab; - 已准备好在 chroot 中安装
btrfs-progs; - 已知道转换后的 UUID 要写入
fstab; - 已重建 initramfs 和 GRUB;
- 首次启动验证前不会删除
ext2_saved或执行 balance。
这次迁移真正改变的不是一条命令,而是系统的故障模型:Btrfs 提供校验、快照、子卷和透明压缩,但不会替你创建第二份数据。只有把 Live 救援环境、可验证备份、可回滚窗口和启动配置一起准备好,ext4 到 Btrfs 的转换才是一次可管理的迁移,而不是一次碰运气的重启。