在 2018 年的一篇 早前的文章 中，我们介绍了在升级 Fedora Linux 前如何利用 LVM 复制根文件系统，以便在可能出现错误的情况下能有一个回退机制。然而如今，Fedora 工作站的默认安装已经是 Btrfs 文件系统了。现在，你可以利用 Btrfs 快照来更简便地创建一个可引导的回退系统。注意，本文不涉及会如何从其它文件系统转换或迁移到 Btrfs 上。确认根文件系统是否为 Btrfs本示例采用的是 Pinebook aarch64 笔记本电脑。在开始前，务必确认你的根文件系统是否采用 Btrfs。要明确，不是所有的定制版或者镜像文件默认都使用 Btrfs。$ df -T Filesystem Type 1K-blocks Used Available Use% Mounted on devtmpfs devtmpfs 4096 0 4096 0% /dev tmpfs tmpfs 998992 0 998992 0% /dev/shm tmpfs tmpfs 399600 6360 393240 2% /run /dev/mmcblk2p3 btrfs 56929280 39796116 15058348 73% / tmpfs tmpfs 998996 24 998972 1% /tmp tmpfs tmpfs 5242880 0 5242880 0% /var/lib/mock /dev/mmcblk2p3 btrfs 56929280 39796116 15058348 73% /f34 /dev/mmcblk2p3 btrfs 56929280 39796116 15058348 73% /home /dev/mmcblk2p2 ext4 996780 551888 376080 60% /boot /dev/mmcblk2p1 vfat 194348 31648 162700 17% /boot/efi tmpfs tmpfs 199796 100 199696 1% /run/user/1000 tmpfs tmpfs 199796 84 199712 1% /run/user/0 列出当前的 Btrfs 子卷以上的示例输出显示挂载在 “根”（/）的文件系统类型是 Btrfs。你会注意到，有三个挂载点显示了相同的备份设备以及 已用 和 可用 的块数。这是因为它们是从同一 Btrfs 文件系统挂载的不同部分（子卷）。比如，/f34 子卷是我去年创建的那个可引导快照。默认的 Fedora Btrfs 安装会创建一个 Btrfs 文件系统，并在其上分别挂载两个子卷，root 和 home ，挂载路径分别为 / 和 /home。让我们一起来看看我还添加了哪些其它的子卷：$ sudo btrfs subvol list / ID 272 gen 110428 top level 5 path root ID 273 gen 110426 top level 5 path home ID 300 gen 109923 top level 5 path f34 ID 301 gen 95852 top level 5 path home.22Jul26 ID 302 gen 95854 top level 5 path f36.22Jul26 在这里，我们有一个来自最近一次系统升级的 f34 子卷，以及两个只读快照 home 和 f36。要添加和删除这些快照，最简单的方法就是挂载 Btrfs 的根目录。我会更新系统并创建当前 f36 root 子卷的新快照。如果你已经重命名了你的 root 子卷，我相信你知道该如何调整以下的示例以适应你的系统。创建 Btrfs 的回退快照$ sudo dnf update --refresh ...更新了很多部分（如果升级了内核还需要重启） $ sudo mkdir -p /mnt/root $ sudo mount /dev/mmcblk2p3 /mnt/root $ cd /mnt/root $ ls f34 f36.22Jul26 home home.22Jul26 root $ sudo btrfs subvol snapshot root f36 Create a snapshot of 'root' in './f36' 因为 Btrfs 快照是以文件系统为基础的，所以并不需要在创建快照之前进行 “同步”，正如我在 LVM 中建议的。要从新的子卷引导为回退，你需要使用你喜欢的编辑器编辑 /mnt/root/f36/etc/fstab。如果你是刚入门的话，nano 就是一款十分简单的文本编辑器，功能基本够用。以下是我 fstab 文件中的一些行：LABEL=PINE / btrfs subvol=root,compress=zstd:1 1 1 UUID=e31667fb-5b6f-48d9-aa90-f2fd6aa5f005 /boot ext4 defaults 1 2 UUID=75DB-5832 /boot/efi vfat umask=0077,shortname=winnt 0 2 LABEL=PINE /home btrfs subvol=home,compress=zstd:1 1 1 LABEL=SWAP swap swap discard=once 0 0 将 subvol=root 更改为 subvol=f36。这个改动是作用在快照中的文件，而并非你实际运行中的 fstab 文件。你可以通过 diff /etc/fstab /mnt/root/f36/etc/fstab 对比它们的区别。在我的情况下，我还使用了 sudo btrfs subvol delete f34 来删除我去年的 f34 快照。测试 Btrfs 的回退快照你现在可以进行回退的测试了。你可以使用 grubby 或在 /boot/loader/entries 中编辑一项来将 subvol=root 替换为 subvol=f36。然而，为了初学者的安全起见，我们更建议你在启动时编辑 GRUB 进行操作。你可以参考 关于 GRUB 的这篇文章 了解如何进入 GRUB 菜单。在你到达那里后，按下 e 键编辑默认的内核启动项。放心 —— 你所做的更改都只存在于内存中，如果你弄错了，重启电脑即可重新开始。就像编辑 fstab 文件一样，找到 subvol=root 并将其更改为 subvol=f36。然后，按 F10 或 Ctrl + X 来引导你修改过的项目。通过这些更改，你的系统应该能够引导进入你的新快照。你可以查看 /etc/fstab 确保你正在引导至正确的子卷，或键入 mount | grep subvol 查看此时在 / 上挂载的子卷。进行 Fedora Linux 的系统升级如果你的回退功能没问题，重启并返回你的正常根文件系统（并像上面所述，进行确认）。然后，按照 维基页面 上的指南进行标准的系统升级。提示：在运行 dnf system-upgrade reboot 之前，给 root 子卷创建另一个快照，你可以给它命名为 root.dl。这样，如果你发现硬盘空间不够，你不必再下载五个 GB 的文件包。因为除了下载的包以外，所有的内容都将与 root 和 f36 共享，因此它不会占用任何额外的空间。然后说到磁盘块的共享问题……因为在 root 子卷中的 f36 文件和 f36 子卷中的相同文件都使用的是相同的磁盘位置，所以在处理 Btrfs 报告的可用空间时，dnf system-upgrade 会感到困惑。因此在升级过程中从 root 子卷中删除它们并不会真正释放任何空间。如果你耗尽了所有空间，并且决定重启电脑，那么图形用户界面（GUI）将无法启动。此时，你需要使用 Ctrl + Alt + F2 进入文本控制台并登录，这将是你磨练命令行技能的好机会。如何清空空间或扩展根文件系统在这里先不做讨论（我的文件系统经常在一个 LVM 的卷上，可以被扩展）。通常，为升级保留超过 50% 的空闲空间是比较保险的。恢复环节如果不幸出现问题，你可以重启电脑，并编辑 GRUB 条目以引导启动回退快照。如果你是新手，一旦需要在磁盘上修改 GRUB 条目（这样你就不需要每次启动时都进行编辑），可能需要一些指导。删除或重命名损坏的 root 子卷是非常直接的。你可以为 f36 子卷（或 root.dl 快照）创建一个快照，然后尝试再一次进行系统升级。以下是在子卷 f36 上启动到回退系统后重新开始的示例：$ mount | grep subvol $ sudo mount /dev/mmcblk2p3 /mnt/root $ cd /mnt/root $ sudo mv root root.failed $ sudo btrfs subvol snapshot f36 root Create a snapshot of 'f36' in './root' Don't forget to edit /mnt/root/root/etc/fstab to change the subvol mounted on "/" to "root". 事实证明，新的 f38 版本的 kernel-6.2.11 在我的 Pinebook 上进行系统升级后并未成功启动！（不过请不要担心，ARM 只是 Fedora Linux 的可选 CPU 架构——在主流设备上，你很少会遭遇此类问题。）的确，我成功地按照前文所述，在启动时编辑了 GRUB 条目并恢复到了 f36 的 kernel-6.2.10。现在，我继续使用着 f38，但同时搭载了 f36 的 kernel-6.2.10。更新：kernel-6.2.12 已经发布，且我已确认它在 Pinebook 上运行正常。过期问题随着你不断更新 f38 系统，它最终可能会希望删除 /boot 下的最后一个 f36 内核。通常来说，这并不是问题，因为到那个时候，你已经完全熟悉 f38，而 f36 快照只是一个存档。然而，如果你希望你的复刻版本（即 f36 的快照）能无限期地启动，那么你应当在 /boot 下保存一个能正常工作的 f36 内核。最简单的方法是在 /etc/dnf/dnf.conf 文件中设置 installonly_limit=0 并手动移除旧的内核，这种方法既简单又安全（尽管可能稍显繁琐）。这里还有一个更复杂的解决方案（不适合新手）：运行 find /boot -name "*fc36*" 指令，列举出所有在 f36 子卷快照中的内核及 GRUB 文件（这些文件并未包含在快照之内）。将这些文件备份至安全位置（例如我会挂载 f36 子卷，并将文件备份至其下的一个目录）。当 f38 系统启动后，对于每一个 f36 内核版本，都需使用 dnf 删除特定版本的内核（例如，使用 dnf remove kernel-core-5.19.11-200.fc36）。千万不要删除 f38 的内核！然后将你先前备份的 f36 内核恢复至 /boot 下。此时，f38 系统已经无法再识别 f36 的内核，因此也不会将其从 /boot 中删除。然而，使用此方法有一个缺点，那就是你可能会不小心删除正在运行的 f38 内核。如果大家有更佳的解决办法，欢迎在评论区分享。展望未来对于习惯于修改 GRUB 条目的用户，他们可能会考虑创建一个命名为 f38 的快照子卷。将当前的 GRUB 条目进行修改，以便启动到这个子卷，重启后，在这个子卷中进行系统升级。此后，总是根据它所包含的 Fedora Linux 版本来命名根文件系统的子卷。但在本文中，我没有采用这种作法，原因有两点：将当前活动的子卷命名为 root，这是遵循 Fedora Linux 的默认设置。坚持使用 root 作为当前子卷，这样在进行正常的系统升级操作之外，并不需要任何永久性的更改。正如本文所展示的，针对重大系统更改（如系统版本升级）可能引发问题时，只读快照作为本地恢复点，非常有用。这些快照还可以通过 Btrfs 的 send 子命令，发送至远程备份。（如果远程备份设备已经包含了先前的备份数据，Btrfs 可以进行增量发送，仅传输发生变更的文件，这样就能节省时间和空间。）如果你打算长期存档这些快照，保持清晰不混淆且能明确恢复顺序的关键，就是要使用一套一致的命名规则。关于如何使用 Btrfs 的 send 命令来创建备份的更多信息，你可以参考关于 Btrfs 快照备份 的文章。（题图：MJ/6aed1d19-f1dd-4935-ad6f-61f6a868f150）via: https://fedoramagazine.org/make-use-of-btrfs-snapshots-to-upgrade-fedora-linux-with-easy-fallback/作者：Stuart D Gathman 选题：lujun9972 译者：ChatGPT 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
大多数用户发现使用标准流程升级从一个 Fedora 版本升级到下一个很简单。但是，Fedora 升级也不可避免地会遇到许多特殊情况。本文介绍了使用 DNF 和逻辑卷管理（LVM）进行升级的一种方法，以便在出现问题时保留可引导备份。这个例子是将 Fedora 26 系统升级到 Fedora 28。此处展示的过程比标准升级过程更复杂。在使用此过程之前，你应该充分掌握 LVM 的工作原理。如果没有适当的技能和细心，你可能会丢失数据和/或被迫重新安装系统！如果你不知道自己在做什么，那么强烈建议你坚持只使用得到支持的升级方法。准备系统在开始之前，请确保你的现有系统已完全更新。$ sudo dnf update $ sudo systemctl reboot # 或采用 GUI 方式检查你的根文件系统是否是通过 LVM 挂载的。$ df / Filesystem 1K-blocks Used Available Use% Mounted on /dev/mapper/vg_sdg-f26 20511312 14879816 4566536 77% / $ sudo lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert f22 vg_sdg -wi-ao---- 15.00g f24_64 vg_sdg -wi-ao---- 20.00g f26 vg_sdg -wi-ao---- 20.00g home vg_sdg -wi-ao---- 100.00g mockcache vg_sdg -wi-ao---- 10.00g swap vg_sdg -wi-ao---- 4.00g test vg_sdg -wi-a----- 1.00g vg_vm vg_sdg -wi-ao---- 20.00g如果你在安装 Fedora 时使用了默认值，你可能会发现根文件系统挂载在名为 root 的逻辑卷（LV）上。卷组（VG）的名称可能会有所不同。看看根卷的总大小。在该示例中，根文件系统名为 f26，大小为 20G。接下来，确保 LVM 中有足够的可用空间。$ sudo vgs VG #PV #LV #SN Attr VSize VFree vg_sdg 1 8 0 wz--n- 232.39g 42.39g该系统有足够的可用空间，可以为升级后的 Fedora 28 的根卷分配 20G 的逻辑卷。如果你使用的是默认安装，则你的 LVM 中将没有可用空间。对 LVM 的一般性管理超出了本文的范围，但这里有一些情形下可能采取的方法：1、/home 在自己的逻辑卷，而且 /home 中有大量空闲空间。你可以从图形界面中注销并切换到文本控制台，以 root 用户身份登录。然后你可以卸载 /home，并使用 lvreduce -r 调整大小并重新分配 /home 逻辑卷。你也可以从 现场镜像 Live image 启动（以便不使用 /home）并使用 gparted GUI 实用程序进行分区调整。2、大多数 LVM 空间被分配给根卷，该文件系统中有大量可用空间。你可以从现场镜像启动并使用 gparted GUI 实用程序来减少根卷的大小。此时也可以考虑将 /home 移动到另外的文件系统，但这超出了本文的范围。3、大多数文件系统已满，但你有个已经不再需要逻辑卷。你可以删除不需要的逻辑卷，释放卷组中的空间以进行此操作。创建备份首先，为升级后的系统分配新的逻辑卷。确保为系统的卷组（VG）使用正确的名称。在这个例子中它是 vg_sdg。$ sudo lvcreate -L20G -n f28 vg_sdg Logical volume "f28" created.接下来，创建当前根文件系统的快照。此示例创建名为 f26_s 的快照卷。$ sync $ sudo lvcreate -s -L1G -n f26_s vg_sdg/f26 Using default stripesize 64.00 KiB. Logical volume "f26_s" created.现在可以将快照复制到新逻辑卷。当你替换自己的卷名时，请确保目标正确。如果不小心，就会不可撤销地删除了数据。此外，请确保你从根卷的快照复制，而不是从你的现在的根卷。$ sudo dd if=/dev/vg_sdg/f26_s of=/dev/vg_sdg/f28 bs=256k 81920+0 records in 81920+0 records out 21474836480 bytes (21 GB, 20 GiB) copied, 149.179 s, 144 MB/s给新文件系统一个唯一的 UUID。这不是绝对必要的，但 UUID 应该是唯一的，因此这避免了未来的混淆。以下是在 ext4 根文件系统上的方法：$ sudo e2fsck -f /dev/vg_sdg/f28 $ sudo tune2fs -U random /dev/vg_sdg/f28然后删除不再需要的快照卷：$ sudo lvremove vg_sdg/f26_s Do you really want to remove active logical volume vg_sdg/f26_s? [y/n]: y Logical volume "f26_s" successfully removed如果你单独挂载了 /home，你可能希望在此处制作 /home 的快照。有时，升级的应用程序会进行与旧版 Fedora 版本不兼容的更改。如果需要，编辑旧根文件系统上的 /etc/fstab 文件以在 /home 上挂载快照。请记住，当快照已满时，它将消失！另外，你可能还希望给 /home 做个正常备份。配置以使用新的根首先，安装新的逻辑卷并备份现有的 GRUB 设置：$ sudo mkdir /mnt/f28 $ sudo mount /dev/vg_sdg/f28 /mnt/f28 $ sudo mkdir /mnt/f28/f26 $ cd /boot/grub2 $ sudo cp -p grub.cfg grub.cfg.old编辑 grub.conf 并在第一个菜单项 menuentry 之前添加这些，除非你已经有了：menuentry 'Old boot menu' { configfile /grub2/grub.cfg.old }编辑 grub.conf 并更改默认菜单项以激活并挂载新的根文件系统。改变这一行：linux16 /vmlinuz-4.16.11-100.fc26.x86_64 root=/dev/mapper/vg_sdg-f26 ro rd.lvm.lv=vg_sdg/f26 rd.lvm.lv=vg_sdg/swap rhgb quiet LANG=en_US.UTF-8如你看到的这样。请记住使用你系统上的正确的卷组和逻辑卷条目名称！linux16 /vmlinuz-4.16.11-100.fc26.x86_64 root=/dev/mapper/vg_sdg-f28 ro rd.lvm.lv=vg_sdg/f28 rd.lvm.lv=vg_sdg/swap rhgb quiet LANG=en_US.UTF-8编辑 /mnt/f28/etc/default/grub 并改变在启动时激活的默认的根卷：GRUB_CMDLINE_LINUX="rd.lvm.lv=vg_sdg/f28 rd.lvm.lv=vg_sdg/swap rhgb quiet"编辑 /mnt/f28/etc/fstab，将挂载的根文件系统从旧的逻辑卷：/dev/mapper/vg_sdg-f26 / ext4 defaults 1 1改为新的：/dev/mapper/vg_sdg-f28 / ext4 defaults 1 1然后，出于参考的用途，只读挂载旧的根卷：/dev/mapper/vg_sdg-f26 /f26 ext4 ro,nodev,noexec 0 0如果你的根文件系统是通过 UUID 挂载的，你需要改变这个方式。如果你的根文件系统是 ext4 你可以这样做：$ sudo e2label /dev/vg_sdg/f28 F28现在编辑 /mnt/f28/etc/fstab 使用该卷标。改变该根文件系统的挂载行，像这样：LABEL=F28 / ext4 defaults 1 1重启与升级重新启动，你的系统将使用新的根文件系统。它仍然是 Fedora 26，但是是带有新的逻辑卷名称的副本，并可以进行 dnf 系统升级！如果出现任何问题，请使用旧引导菜单引导回到你的工作系统，此过程可避免触及旧系统。$ sudo systemctl reboot # or GUI equivalent ... $ df / /f26 Filesystem 1K-blocks Used Available Use% Mounted on /dev/mapper/vg_sdg-f28 20511312 14903196 4543156 77% / /dev/mapper/vg_sdg-f26 20511312 14866412 4579940 77% /f26你可能希望验证使用旧的引导菜单确实可以让你回到挂载在旧的根文件系统上的根。现在按照此维基页面中的说明进行操作。如果系统升级出现任何问题，你还会有一个可以重启回去的工作系统。进一步的考虑创建新的逻辑卷并将根卷的快照复制到其中的步骤可以使用通用脚本自动完成。它只需要新的逻辑卷的名称，因为现有根的大小和设备很容易确定。例如，可以输入以下命令：$ sudo copyfs / f28提供挂载点以进行复制可以更清楚地了解发生了什么，并且复制其他挂载点（例如 /home）可能很有用。via: https://fedoramagazine.org/use-lvm-upgrade-fedora/作者：Stuart D Gathman 选题：lujun9972 译者：wxy 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出