Fedora 备份与恢复:btrfs 快照、tar 与 SELinux 标签
备份最容易犯的错不是”没备份”,而是备了但恢复不回来。Fedora 上尤其如此——因为还有一层 SELinux 标签,普通的 tar -cf 会把它丢掉。
下面每一条都在 F45 上实测过。
先分清要备份什么
Section titled “先分清要备份什么”| 层次 | 内容 | 手段 |
|---|---|---|
| 系统状态 | 装了什么包、仓库配置 | rpm -qa 清单 + 配置文本 |
| 文件与数据 | /etc、/home、/var/lib | btrfs 快照 / tar / rsync |
| 整机回滚 | 整个根文件系统 | btrfs 快照 |
三类不能互相替代:包清单恢复不了数据,快照回滚不了”装错了一个包”这种细粒度问题。
btrfs 快照:位置比命令重要
Section titled “btrfs 快照:位置比命令重要”F45 默认是 btrfs(详见存储),快照是零成本的——只记录写时复制。
先看现状:
findmnt -no FSTYPE /sudo btrfs subvolume list /btrfs
ID 256 gen 364 top level 5 path rootID 257 gen 300 top level 5 path bootID 258 gen 368 top level 5 path homeID 259 gen 368 top level 5 path var一个容易踩的坑:快照套在自己里面
Section titled “一个容易踩的坑:快照套在自己里面”如果直接这样截图:
sudo mkdir -p /snapshotssudo btrfs subvolume snapshot -r / /snapshots/root-$(date +%Y%m%d)结果快照会落在根子卷内部:
ID 260 gen 369 top level 256 path root/snapshots/root-20261027top level 256 就是 root 子卷。这意味着下次截根快照时会把这次快照也包含进去,快照体积越滚越大。
正确做法:先建一个独立的顶层子卷
Section titled “正确做法:先建一个独立的顶层子卷”sudo mkdir -p /mnt/topsudo mount -o subvolid=5 /dev/sda3 /mnt/top # 挂顶层(subvolid=5)sudo btrfs subvolume create /mnt/top/snapshotssudo umount /mnt/top之后快照落在 snapshots 子卷里,与 root 平级:
sudo btrfs subvolume snapshot -r / /mnt/top/snapshots/root-$(date +%Y%m%d-%H%M)sudo btrfs subvolume list /mnt/top | grep snapshotsID 261 gen 371 top level 5 path snapshotsID 262 gen 371 top level 261 path snapshots/root-20261027-1747top level 261 是 snapshots 子卷——不再递归。
快照占多少空间:
sudo btrfs filesystem usage /Overall: Device size: 19.90GiB Device allocated: 5.02GiB Device unallocated: 14.88GiB快照本身不占 allocated;只有原文件被修改后才会分叉出新数据块。所以刚截完的快照几乎不增加占用。
tar:不带参数会丢 SELinux 标签
Section titled “tar:不带参数会丢 SELinux 标签”这是 Fedora 上最容易出问题的一步。同一个文件,三种情况:
# 造一个带特定标签的文件sudo mkdir -p /tmp/seltest/srcecho hi | sudo tee /tmp/seltest/src/file >/dev/nullsudo chcon -t httpd_sys_content_t /tmp/seltest/src/file
# 打包:一个不带参数,一个带 --selinux --xattrssudo tar -cf /tmp/seltest/no-selinux.tar -C /tmp/seltest/src .sudo tar --selinux --xattrs -cf /tmp/seltest/with-selinux.tar -C /tmp/seltest/src .
# 各自解开再比较标签sudo mkdir -p /tmp/seltest/a /tmp/seltest/bsudo tar -xf /tmp/seltest/no-selinux.tar -C /tmp/seltest/asudo tar --selinux --xattrs -xf /tmp/seltest/with-selinux.tar -C /tmp/seltest/bsudo ls -Z /tmp/seltest/src/file /tmp/seltest/a/file /tmp/seltest/b/fileoriginal : unconfined_u:object_r:httpd_sys_content_t:s0no-flag : unconfined_u:object_r:user_tmp_t:s0with-flag: unconfined_u:object_r:httpd_sys_content_t:s0中间那行就是灾难:标签从 httpd_sys_content_t 变成了 user_tmp_t(从目标目录继承的默认标签)。文件内容完好,但服务读不了。
正确的打包与解包:
sudo tar --selinux --xattrs --acls -czf backup-etc.tar.gz -C / etcsudo tar --selinux --xattrs --acls -xzpf backup-etc.tar.gz -C /mnt/restore-p 是保留权限位。--selinux 与 --xattrs 缺一不可——前者处理 SELinux 上下文,后者处理扩展属性(capabilities 也在里面)。
包清单:恢复系统状态的唯一依据
Section titled “包清单:恢复系统状态的唯一依据”rpm -qa | wc -lrpm -qa --qf '%{NAME}' | sort > /var/backups/pkgs.txt631F45 的基础系统是 631 个包。恢复时:
sudo dnf install $(cat /var/backups/pkgs.txt)还会想看仓库配置和最近的事务:
cp /etc/yum.repos.d/*.repo /var/backups/ 2>/dev/nullls /usr/share/dnf5/repos.d/ > /var/backups/repos-list.txt # F45 的自带仓库sudo dnf history list | head -5ID Command line Date and time Action(s) Altered10 dnf -y install dbus-daemon 2026-10-26 18:21:45 1 9 dnf -y install dbus-tools 2026-10-26 18:20:19 1恢复之后一定要做的两件事
Section titled “恢复之后一定要做的两件事”一、恢复 SELinux 标签(如果备份时标签没保住,或者恢复到了不同路径):
sudo restorecon -Rv /etc /var/www /home二、确认关键服务能起来:
sudo systemctl daemon-reloadsystemctl list-units --failed验证备份——最重要的一步
Section titled “验证备份——最重要的一步”没验证过的备份等于没有备份。 最小验证集:
# 1) 压缩包能读吗tar -tzf backup-etc.tar.gz | wc -l
# 2) 能解到临时目录吗mkdir -p /tmp/verify && tar -xzpf backup-etc.tar.gz -C /tmp/verify
# 3) 关键文件在吗、内容对吗diff -q /tmp/verify/etc/hostname /etc/hostname
# 4) 标签还在吗ls -Z /tmp/verify/etc/ssh/sshd_configbtrfs 快照的验证更直接——挂出来看:
sudo mount -o ro,subvol=/snapshots/root-20261028-0300 /dev/sda3 /mnt/checkls /mnt/check/etc | headsudo umount /mnt/check用 systemd timer 而不是 cron(F45 最小化镜像不带 crontab),写法见systemd 服务与定时器:
[Unit]Description=Nightly etc backup
[Timer]OnCalendar=*-*-* 03:30:00Persistent=true
[Install]WantedBy=timers.target配套的 .service 里放那条 tar --selinux --xattrs --acls ...。Persistent=true 保证关机错过的备份会在开机后补跑。
- 存储与文件系统 — btrfs 子卷、挂载与容量
- SELinux — 标签为什么重要、怎么恢复
- systemd 服务与定时器 — 定时备份的写法
- 升级到 Fedora 45 — 升级前该备份什么
- 官方:Btrfs