# 使用 ZFS 启动环境更新 FreeBSD

* [Upgrade FreeBSD with ZFS Boot Environments](https://vermaden.wordpress.com/2021/02/23/upgrade-freebsd-with-zfs-boot-environments/)
* 作者：𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗
* 发布时间：2021/02/23

我以强烈支持 **ZFS 启动环境** 而闻名……而这并非没有理由。我已经多次说明了支持的原因，但大多数（或全部）内容在这里被浓缩了——<https://is.gd/BECTL>——在我关于此的演示中。即将发布的 FreeBSD 13.0-RELEASE 看起来非常有希望。在许多测试中，它的速度几乎是 12.2-RELEASE 的两倍。哎呀！ ![](https://vermaden.wordpress.com/wp-content/uploads/2021/02/phoronix-mean.png?w=960)

详细测试可以在 [phoronix.com](https://www.phoronix.com/scan.php?page=article\&item=freebsd-13-beta1) 网站上查看。由于我已经安装了 12.2-RELEASE，我想测试 13.0-BETA\*，看看对我来说重要的功能——比如正常工作的挂起/恢复——在新版本中是否如宣传般正常工作。这正是使用 *ZFS Boot Environments* 可以完美实现的任务。

在下面的示例中，我们将创建一个全新的 **ZFS 启动环境**，克隆我们当前的 12.2-RELEASE 系统，并在该 BE 中升级到 13.0-BETA3 版本……这样重启时只需一次，而不像典型的 **freebsd-update(8)** 升级流程需要三次重启。

我假设你已经安装了带 ZFS 的 FreeBSD 12.2-RELEASE（FreeBSD 默认 ZFS 安装），并且系统以 UEFI 或 UEFI+BIOS 模式安装。以下是所需的步骤。

```sh
(host) # beadm create 13                        # 创建新的 '13' ZFS Boot Environment
       Created successfully
(host) # beadm mount 13 /var/tmp/BE-13          # 将新的 '13' BE 挂载到某个目录
       Mounted successfully on '/var/tmp/BE-13'
(host) # chroot /var/tmp/BE-13                  # 切换到该目录的 chroot(8) 环境
  (BE) # mount -t devfs devfs /dev              # 在该 BE 中挂载 devfs(8)
  (BE) # rm -rf /var/db/freebsd-update          # 删除任何旧补丁
  (BE) # mkdir /var/db/freebsd-update           # 为补丁创建新的目录
  (BE) # freebsd-update upgrade -r 13.0-BETA3   # 获取升级所需的补丁
  (BE) # freebsd-update install                 # 安装内核及内核模块
  (BE) # freebsd-update install                 # 安装用户空间程序/二进制文件/库
  (BE) # pkg upgrade                            # 使用 pkg(8) 升级所有软件包
  (BE) # freebsd-update install                 # 移除旧的库和文件
  (BE) # exit                                   # 退出 chroot(8) 环境
(host) # umount -f /var/tmp/BE-13/dev           # 卸载该 BE 中的 devfs(8)
(host) # beadm activate 13                      # 激活新的 '13' BE
       Activated successfully
```

我在这个过程中使用的是我的 [**sysutils/beadm**](https://github.com/vermaden/beadm)，但你也可以使用 FreeBSD 基础系统自带的 **bectl(8)**。

我们还需要更新新的 FreeBSD **loader(8)** —— 通过这种方式可以更新 —— 感谢 [@JeffSipek](https://twitter.com/JeffSipek) 的指点。

在我的系统中，FreeBSD 安装在 **ada1** 设备上。

```sh
(host) # gpart show -p ada1 | grep efi                # 查找 UEFI msdosfs(5) 分区
               40     409600  ada1p1  efi  (200M)     # <-- 就是这一项
(host) # mount_msdosfs /dev/ada1p1 /mnt               # 将其挂载到 /mnt 下
(host) # find /mnt                                    # 显示其内容
       /mnt
       /mnt/efi
       /mnt/efi/boot
       /mnt/efi/boot/bootx64.efi                      # 更新 bootx64.efi 文件
(host) # cp /boot/boot1.efi /mnt/efi/boot/bootx64.efi # 从 /boot/boot1.efi 文件复制
(host) # umount -f /mnt                               # 卸载 /mnt 文件系统
```

有小概率你无法挂载 **efi** 分区。即使使用 **fsck(8)** 也无法解决此问题。

一些用户遇到的典型错误如下：

```sh
(host) # mount_msdosfs /dev/ada1p1 /mnt # 尝试挂载 EFI 分区时出错
       mount_msdosfs: /dev/ada1p1: Invalid argument

(host) # fsck_msdosfs -y /dev/ada1p1    # 尝试对该分区执行 fsck(8) 时出错
       ** /dev/ada1p1
       Invalid signature in boot block: 0b6a
```

如果你遇到这个问题，首先将当前的 **efi** 分区备份，例如备份到 **/BACKUP.ada1p1** 文件。

```sh
(host) # dd < /dev/ada1p1 > /BACKUP.ada1p1 bs=1m
```

现在我们将从零开始创建全新的 **efi** 分区。

```sh
(host) # newfs_msdos -F 32 -c 1 /dev/ada0p1            # 创建新的 FAT32 分区
(host) # mount_msdosfs /dev/ada0p1 /mnt                # 挂载到 /mnt 下
(host) # mkdir -p /mnt/efi/boot                        # 创建所需目录
(host) # cp /boot/loader.efi /mnt/efi/boot/bootx64.efi # 从 /boot/loader.efi 复制文件
(host) # umount -f /mnt                                # 卸载 /mnt 文件系统
```

现在你应该已经有了新的“可用” **efi** 分区。

最后一步是 **reboot(8)** 进入新的 13.0-BETA3 系统。

```sh
(host) # reboot
```

如果你发现新的引导加载程序无法加载你的新 FreeBSD，也可以选择将 **/boot/boot1.efi** 而不是 **/boot/loader.efi** 复制到 **/mnt/efi/boot/bootx64.efi**。

请记住，如果你从 **geli(8)** 加密系统启动，那么 **/boot/loader.efi** 是必需的，如果使用 **/boot/boot1.efi** 文件将无法启动。

完成。

现在你应该能看到全新的 FreeBSD **loader(8)**：🙂

![](https://vermaden.wordpress.com/wp-content/uploads/2021/02/fancy-loader.png?w=960)

你现在可以享受最新的 FreeBSD 13.0-BETA3 安装。

同样的步骤将适用于即将发布的 FreeBSD 13.0-RC\*（RC1/RC2/RC3）版本的更新，最终希望在 2021 年 3 月发布 FreeBSD 13.0-RELEASE。

## 更新 1 – 如果一切顺利

你现在拥有最先进的 FreeBSD 系统，运行速度应该比 12.2-RELEASE 更快，同时你仍保留旧的 12.2-RELEASE Boot Environment，如果在 13.0 版本中遇到问题，可以回退。

在我的系统中，它看起来是这样的：

```sh
(host) # beadm list
       BE   Active Mountpoint Space Created
       12.2 -      -           6.5G 2021-02-12 10:15
       13   NR     /          18.8G 2021-02-13 11:32
```

**Space** 列有点容易误导，因为它会计算例如快照占用的空间。要获取每个 Boot Environment 占用的精确信息，请使用 **-D** 选项。这样你可以分别查看每个 Boot Environment 的空间信息。

```sh
(host) # beadm list -D
       BE   Active Mountpoint  Space Created
       12.2 -      -            9.8G 2021-02-12 10:15
       13   NR     /            9.6G 2021-02-13 11:32
```

我会暂时保留 12.2-RELEASE Boot Environment —— 可能在 13.0-RELEASE 发布后一个月左右删除它，但如果你测试过所有需求，并且发现 13.0 能像 12.2-RELEASE 一样或更好地满足需求，那么你可以使用下面的命令删除旧的 Boot Environment。

```sh
(host) # beadm destroy 12.2
```

## 更新 2 – 如果出现问题

一般来说，如果新 BE 名为 ‘**13**’ 无法启动（或在启动时挂起），只需选择你在升级前使用的旧 Boot Environment —— 也就是包含 12.2-RELEASE 的那个。

这样你就可以回到升级前可正常工作的系统。

如果这也失败了（或者引导加载程序损坏），那么下载 [FreeBSD-13.0-BETA3-amd64-memstick.img](http://ftp.freebsd.org/pub/FreeBSD/releases/ISO-IMAGES/13.0/FreeBSD-13.0-BETA3-amd64-memstick.img) 镜像，并用 **dd(8)** 命令写入 U 盘。

```sh
# dd if=FreeBSD-13.0-BETA3-amd64-memstick.img of=/dev/da0 bs=1M status=progress
```

现在你有了 FreeBSD 13.0-BETA3 的 U 盘，可以从它启动并修复你的安装。启动后选择 **LiveCD**，在 **login:** 提示符下输入 **root** 并按 **\[ENTER]** 留空密码。

接下来可以执行的操作取决于具体损坏情况，我无法预估每种可能的错误和修复方案。如果在升级过程中遇到任何问题，请通过你方便的方式联系我，我们会一起解决。

## 更新 3 – 使用新版本 beadm(8) 更快升级

今天（2022/05/06）我发布了新版本 **beadm(8)** 1.3.5，带来了新的 **chroot(8)** 功能。它已经提交到 FreeBSD Ports 树的 [263805](https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=263805) PR 中，所以预计很快就能获取到软件包。

你也可以直接这样更新 **beadm(8)**：

```sh
# fetch -o /usr/local/sbin/beadm https://raw.githubusercontent.com/vermaden/beadm
```

现在讲更快的升级流程 —— 以下说明根据你使用的 shell 而定。

* **ZSH / CSH**

```sh
# beadm create 13.1-RC6
# beadm chroot 13.1-RC6
BE # zsh || csh
BE # yes | freebsd-update upgrade -r 13.1-RC6
BE # 重复执行 3 次 freebsd-update install
BE # exit
# beadm activate 13.1-RC6
# reboot
```

* **SH / BASH / FISH / KSH**

```sh
# beadm create 13.1-RC6
# beadm chroot 13.1-RC6
BE # sh || bash || fish || ksh
BE # yes | freebsd-update upgrade -r 13.1-RC6
BE # seq 3 | xargs -I- freebsd-update install
BE # exit
# beadm activate 13.1-RC6
# reboot
```

祝升级顺利 :🙂:


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://translated-articles.bsdcn.org/2025-nian/upgrade-freebsd-with-zfs-boot-environments.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
