16.7 ZFS 启动环境与多版本共存
借助 ZFS 启动环境,可在同一台机器上保留多个独立的系统版本,升级失败时无需重新安装即可回滚到先前状态,从而实现原子更新、多系统并存与快速回滚。
16.7.1 创建启动环境 15.0-RELEASE
ZFS 启动环境(Boot Environment,BE)允许在系统中创建多个独立的系统环境,实现不同版本的共存与安全切换。以下创建启动环境 15.0-RELEASE。
- 使用工具 bectl 创建启动环境
15.0-RELEASE:
# bectl create 15.0-RELEASE注意
此处仅命名为 15.0,系统仍为 14.3-RELEASE。
- 使用 bectl 检查启动环境:
$ bectl list # 显示所有启动环境
BE Active Mountpoint Space Created
15.0-RELEASE - - 176K 2025-12-05 22:27
default NR / 10.6G 2025-01-14 20:36Active 字段解释:
N:表示该启动环境当前是否处于活动状态(当前是否位于此环境中)R:在重启时是否处于活动状态(下次是否选中,用于固定选项)T:是否会在下次启动时生效(且仅下次,用于一次性选项)NRT:当前活动、重启后活动且仅下一次启动生效列出系统中所有 ZFS 文件系统及其属性:
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
……其他省略……
zroot/ROOT/15.0-RELEASE 8K 83.8G 10.6G /
……其他省略……其中 zroot/ROOT/15.0-RELEASE 一行即为新创建的启动环境。
16.7.2 将启动环境中的系统版本更新到 15.0-RELEASE
创建启动环境后,需要更新到目标版本。操作分为挂载、验证版本、转换为 pkgbase、升级四个步骤。
16.7.2.1 挂载启动环境 15.0-RELEASE
操作启动环境前,需先挂载到文件系统中。创建临时目录并执行挂载:
- 创建一个临时目录,用于更新启动环境 15.0-RELEASE 中的系统
# mkdir /mnt/upgrade/mnt/
└── upgrade/ # 启动环境挂载目录
└── usr/
└── local/
└── etc/
└── pkg/
└── repos/
└── FreeBSD-base.conf # pkgbase 源配置文件- 将启动环境(实际上是一个数据集)15.0-RELEASE 挂载到指定路径
# bectl mount 15.0-RELEASE /mnt/upgrade
/mnt/upgrade- 显示已挂载文件系统的磁盘使用情况:
# df
Filesystem 1K-blocks Used Avail Capacity Mounted on
……其他省略……
zroot/ROOT/15.0-RELEASE 99036272 11132688 87903584 11% /mnt/upgrade
……其他省略……16.7.2.2 验证当前 FreeBSD 版本
目前 15.0-RELEASE 实际仍是 14.3-RELEASE,可使用 freebsd-version 验证:
在 /mnt/upgrade 环境中运行 freebsd-version:
# chroot /mnt/upgrade freebsd-version -kru
14.3-RELEASE
14.3-RELEASE
14.3-RELEASEfreebsd-version 参数解释:
-k:打印已安装内核的版本和补丁级别。与 uname(1) 不同的是,如果新的内核已经安装但系统尚未重启,freebsd-version会打印新内核的版本和补丁级别。-r:打印正在运行中的内核的版本和补丁级别。与 uname(1) 不同的是,freebsd-version不受环境变量影响。-u:打印已安装用户态的版本和补丁级别。这些信息在构建过程中会写入程序freebsd-version中。
16.7.2.3 使用 pkgbase 将启动环境中的 14.3-RELEASE(系统版本)转换为 pkgbase
升级之前,需将传统的 FreeBSD 系统转换为 pkgbase 格式。pkgbase 是 FreeBSD 官方提供的基本系统打包方式,使用 pkg 包管理器管理系统组件。
pkgbase 的设计初衷是让 stable、current 和 release(包括 BETA、RC 等)都能使用统一的二进制工具更新。此前,stable 和 current 只能通过编译源代码来更新。
注意
仅 FreeBSD 14.0-RELEASE 及更高版本才能直接转换为 pkgbase。旧版仍需要通过
freebsd-update更新(运行时 pkgbasify 会提示Unsupported FreeBSD version,即 FreeBSD 版本不受支持)。
警告
存在风险,可能会丢失所有数据!建议在操作前做好备份。
- 在 /mnt/upgrade 环境中锁定 pkg 软件包,防止升级或修改:
# pkg -c /mnt/upgrade lock pkg # 在 /mnt/upgrade 环境中锁定 pkg 软件包
pkg-2.4.2_1: lock this package? [y/N]: y # 输入 y 按回车键确认锁定 pkg
Locking pkg-2.4.2_1- 下载 pkgbase 转换脚本
# fetch -o /mnt/upgrade https://raw.githubusercontent.com/FreeBSDFoundation/pkgbasify/main/pkgbasify.lua # 下载 pkgbase 转换脚本- 使用 pkgbasify 转换
警告
确认
Do you accept this risk and wish to continue? (y/n)风险提示后便无二次确认步骤!
# chroot /mnt/upgrade /usr/libexec/flua pkgbasify.lua # 使用 pkgbasify 转换
Running this tool will irreversibly modify your system to use pkgbase.
This tool and pkgbase are experimental and may result in a broken system.
It is highly recommended to backup your system before proceeding.
Do you accept this risk and wish to continue? (y/n) y # 这里是风险提示,确认
Updating FreeBSD repository catalogue...
……此处省略……
The following 370 package(s) will be affected (of 0 checked):
New packages to be INSTALLED:
FreeBSD-acct: 14.3p6 [FreeBSD-base]
FreeBSD-acct-man: 14.3p6 [FreeBSD-base]
FreeBSD-acpi: 14.3p6 [FreeBSD-base]
FreeBSD-acpi-man: 14.3p6 [FreeBSD-base]
……此处省略……
Conversion finished.
Please verify that the contents of the following critical files are as expected:
/etc/master.passwd
/etc/group
/etc/ssh/sshd_config
After verifying those files, restart the system.- 检查启动环境 15.0-RELEASE 中的系统版本
# chroot /mnt/upgrade freebsd-version -kru
14.3-RELEASE-p6
14.3-RELEASE
14.3-RELEASE-p616.7.2.4 使用 pkgbase 将启动环境中的系统版本更新到 15.0-RELEASE
转换为 pkgbase 后,即可使用 pkg 包管理器升级系统。下面配置 pkgbase 源并执行升级。
软件源结构:
/usr/local/etc/pkg/
└── repos/ # pkg 仓库配置目录
└── FreeBSD-base.conf # pkgbase 源配置文件- 创建 pkgbase 软件源目录
# mkdir -p /mnt/upgrade/usr/local/etc/pkg/repos/ # 创建 pkgbase 软件源目录- 编辑 /mnt/upgrade/usr/local/etc/pkg/repos/FreeBSD-base.conf 文件,添加 pkgbase 源
FreeBSD-base {
url = "https://pkg.freebsd.org/${ABI}/base_release_${VERSION_MINOR}";
enabled = yes;
}警告
请检查
FreeBSD-base.conf的内容,尤其是 不应该 在其中手动硬编码任何具体的版本(如base_release_3)。
技巧
需要切换软件源的用户可将
url这行改为url = "https://mirrors.ustc.edu.cn/freebsd-pkg/${ABI}/base_release_${VERSION_MINOR}";。注重安全性的读者应维持默认设置。
- 刷新软件源
# pkg -c /mnt/upgrade update -r FreeBSD-base # 刷新软件源- 使用 pkgbase 将 14.3-RELEASE 更新到 15.0-RELEASE(即将 ABI 指定为 15)
# env ABI=FreeBSD:15:amd64 pkg-static -c /mnt/upgrade upgrade -r FreeBSD-base # 在 /mnt/upgrade 环境中使用指定 ABI 升级 FreeBSD 基本系统包
pkg-static: Setting ABI requires setting OSVERSION, guessing the OSVERSION as: 1500000
pkg-static: Warning: Major OS version upgrade detected. Running "pkg bootstrap -f" recommended
Updating FreeBSD-base repository catalogue...
pkg-static: Repository FreeBSD-base has a wrong packagesite, need to re-create database
Fetching meta.conf: 100% 179 B 0.2kB/s 00:01
Fetching data.pkg: 100% 80 KiB 81.6kB/s 00:01
Processing entries: 0%
Newer FreeBSD version for package FreeBSD-zlib-dbg:
To ignore this error set IGNORE_OSVERSION=yes
- package: 1500068
- running userland: 1500000
Ignore the mismatch and continue? [y/N]: y # 此处输入 y 后继续
Processing entries: 100%
FreeBSD-base repository update completed. 496 packages processed.
FreeBSD-base is up to date.
Checking for upgrades (230 candidates): 100%
Processing candidates (230 candidates): 100%
The following 290 package(s) will be affected (of 0 checked):
New packages to be INSTALLED:
FreeBSD-atf: 15.0 [FreeBSD-base]
FreeBSD-atf-dev: 15.0 [FreeBSD-base]
FreeBSD-atf-lib: 15.0 [FreeBSD-base]
……此处省略一部分…
FreeBSD-zoneinfo: 14.3p6 -> 15.0 [FreeBSD-base]
Number of packages to be installed: 61
Number of packages to be upgraded: 229
The operation will free 100 MiB.
473 MiB to be downloaded.
Proceed with this action? [y/N]: y # 此处输入 y 后继续技巧
如果检查不到任何更新,请确认当前是否已成功转换为 pkgbase,并检查软件源配置是否正确。
- 检查启动环境 15.0-RELEASE 中的系统版本
# chroot /mnt/upgrade freebsd-version -kru
15.0-RELEASE
14.3-RELEASE
15.0-RELEASE其中 r 显示为 14.3-RELEASE 并无异常,表明当前运行的仍是 14.3-RELEASE。结合其他参数,可知重启后才会切换至 15.0-RELEASE。
- 解锁 pkg
# chroot /mnt/upgrade pkg unlock pkg # 解锁 pkg
pkg: Warning: Major OS version upgrade detected. Running "pkg bootstrap -f" recommended
pkg-2.4.2_1: unlock this package? [y/N]: y
Unlocking pkg-2.4.2_1- 将所有第三方软件包的 ABI 更新至 FreeBSD 15.0
# chroot /mnt/upgrade pkg upgrade # 将所有第三方软件包的 ABI 更新到 FreeBSD 15.0更新过程中需要多次确认才能完成。
16.7.2.5 启动到启动环境 15.0-RELEASE
完成所有更新操作后,启动到新的启动环境验证结果。
- 在下次启动时进入启动环境 15.0-RELEASE
# bectl activate -t 15.0-RELEASE # 在下次启动时进入启动环境 15.0-RELEASE
Successfully activated boot environment 15.0-RELEASE
for next boot- 验证设置是否成功。列出系统中所有 ZFS 启动环境:
$ bectl list
BE Active Mountpoint Space Created
15.0-RELEASE T /mnt/upgrade 8.75G 2025-12-05 23:22
default NR / 10.9G 2025-01-14 20:36注意,这是一次性的(T),此处仅用于验证其是否能够正常启动。还需要回到当前的主系统 14.3-RELEASE 来更新 ZFS。
- 重启以进入启动环境 15.0-RELEASE
# reboot # 重启以进入启动环境 15.0-RELEASE- 验证版本:
$ freebsd-version -kru
15.0-RELEASE
15.0-RELEASE
15.0-RELEASE
$ bectl list
BE Active Mountpoint Space Created
15.0-RELEASE N / 8.75G 2025-12-05 23:22
default R - 10.9G 2025-01-14 20:36由输出可知,已成功将启动环境 15.0-RELEASE 中的 FreeBSD 系统升级到 15.0-RELEASE,此时启动环境名称与实际版本一致。
R 意味着再次重启将回到启动环境 default(14.3-RELEASE)。
16.7.3 附录:永久性使用 15.0-RELEASE
前面已通过一次性启动环境完成验证。如果验证通过并且不需要再保留旧版本,可以将新环境设置为永久默认。
如果读者不需要多版本共存,并且验证过目前的环境满足需要,也可以将启动环境 15.0-RELEASE 设置为永久的:
# bectl activate 15.0-RELEASE随后,读者也可以销毁不再需要的启动环境:
# bectl destroy 要销毁的启动环境名称将参数 要销毁的启动环境名称 替换为命令 bectl list 输出中 BE 列对应的启动环境名称即可销毁。
16.7.4 将基本系统中的 ZFS 替换为 Ports 版本
在实现多版本 FreeBSD 共存时,一个重要的考虑因素是 ZFS 池版本的兼容性问题。不同版本的 FreeBSD 内置的 ZFS 版本可能不同,这可能导致无法互相访问存储池。
通常,在 FreeBSD 大版本之间,ZFS 池版本和特性都会发生变化,例如从 13 到 14 时 zpool 就有所变动。
可通过 Ports 中的 OpenZFS 实现 13、14、15 等多个系统版本的共存。
警告
如不按下方设置就强行升级 ZFS 池/特性,将无法访问旧版系统。
需实现多版本共存的读者可直接重启,进入启动环境 default(14.3-RELEASE)。
16.7.4.1 验证当前的系统版本
在开始操作之前,需确认已回到启动环境 default(14.3-RELEASE)中。
$ bectl list
BE Active Mountpoint Space Created
15.0-RELEASE - - 8.75G 2025-12-05 23:22
default NR / 10.9G 2025-01-14 20:36
$ freebsd-version -kru
14.3-RELEASE
14.3-RELEASE
14.3-RELEASE由输出可知,已回到默认启动环境。
16.7.4.2 查看内置的 OpenZFS 版本
首先查看当前系统内置的 ZFS 版本信息,以便确认待替换的版本。
显示当前 ZFS 工具和内核模块的版本信息:
# zfs --version
zfs-2.2.7-FreeBSD_ge269af1b3
zfs-kmod-2.2.7-FreeBSD_ge269af1b3目前 FreeBSD 基本系统内置的是 OpenZFS 2.2.7(即来自 https://github.com/openzfs/zfs/commit/e269af1b3)。
16.7.4.3 安装 filesystems/openzfs
Ports 中的 OpenZFS 提供了比基本系统更灵活的版本选择。可以使用 pkg 或 Ports 两种方式来安装它。
- 使用 pkg 安装
# pkg install openzfs- 使用 Ports 安装:
# cd /usr/ports/filesystems/openzfs/
# make install clean16.7.4.4 编辑 /boot/loader.conf 文件
安装完成后,需要配置系统启动时加载哪个 ZFS 模块。默认情况下,系统会加载基本系统内置的 ZFS 模块,需要修改这个行为。
为了防止系统加载基本系统内置的 ZFS 版本,需要在 zfs_load=YES 前加上注释 #,取消其开机自动加载。
形如:
# zfs_load=YES # 不加载内置 ZFS 内核模块再新增下列数行:
zfs_load=NO # 显式禁用内置 ZFS 内核模块加载
openzfs_load=YES # 启用 OpenZFS 模块加载完成后重启系统。
16.7.4.5 检查 ZFS 版本
配置完成并重启后,需要验证系统是否正确加载了 Ports 版本的 OpenZFS。
在重启后,检查 ZFS 版本:
# zfs --version
zfs-2.2.7-FreeBSD_ge269af1b3
zfs-kmod-2.3.5-1随后即可更新其他存储池或启用新的特性。
警告
考虑到基本系统中的 OpenZFS 版本不一定是最新的,建议所有版本均使用 Ports 中的 OpenZFS 以保持版本统一,包括 15.0-RELEASE 也应按照相同方法替换 ZFS。
16.7.5 附录:给 pkgbasify 脚本切换软件源
对于网络环境受限制的用户,可能需要为 pkgbasify 脚本配置国内镜像源以提高下载速度。下面介绍如何修改脚本中的源地址。
16.7.5.1 修改示例(使用 USTC)
中国科学技术大学(USTC)提供了 FreeBSD 的镜像服务,可以修改 pkgbasify 脚本来使用这个镜像源。首先需要找到脚本中的相关函数。
找到 Lua 脚本中的 create_base_repo_conf 函数:
local function base_repo_url()
local major, minor, branch = freebsd_version()
if math.tointeger(major) < 14 then
fatal("Unsupported FreeBSD version: " .. raw)
end
if branch == "RELEASE" or branch:match("^BETA") or branch:match("^RC") then
return "pkg+https://pkg.FreeBSD.org/${ABI}/base_release_" .. minor
elseif branch == "CURRENT" or
branch == "STABLE" or
branch == "PRERELEASE" or
branch:match("^ALPHA")
then
return "pkg+https://pkg.FreeBSD.org/${ABI}/base_latest"
else
fatal("Unsupported FreeBSD version: " .. raw)
end
end将这个函数修改如下,其中在 return 部分指定了镜像站:
local function base_repo_url()
local major, minor, branch = freebsd_version()
if math.tointeger(major) < 14 then
fatal("Unsupported FreeBSD version: " .. raw)
end
if branch == "RELEASE" or branch:match("^BETA") or branch:match("^RC") then
return "https://mirrors.ustc.edu.cn/freebsd-pkg/${ABI}/base_release_" .. minor
elseif branch == "CURRENT" or
branch == "STABLE" or
branch == "PRERELEASE" or
branch:match("^ALPHA")
then
return "https://mirrors.ustc.edu.cn/freebsd-pkg/${ABI}/base_latest"
else
fatal("Unsupported FreeBSD version: " .. raw)
end
end警告
请删除
return "pkg+https://"这行中的pkg+,否则会报错。
再找到下面的函数 create_base_repo_conf
local function create_base_repo_conf(path)
assert(os.execute("mkdir -p " .. path:match(".*/")))
local f <close> = assert(io.open(path, "w"))
if math.tointeger(freebsd_version()) >= 15 then
assert(f:write(string.format([[
%s: {
enabled: yes
}
]], options.repo_name)))
else
assert(f:write(string.format([[
%s: {
url: "%s",
mirror_type: "srv",
signature_type: "fingerprints",
fingerprints: "/usr/share/keys/pkg",
enabled: yes
}
]], options.repo_name, base_repo_url())))
end
end修改如下(删除了 srv 相关数行):
local function create_base_repo_conf(path)
assert(os.execute("mkdir -p " .. path:match(".*/")))
local f <close> = assert(io.open(path, "w"))
if math.tointeger(freebsd_version()) >= 15 then
assert(f:write(string.format([[
%s: {
enabled: yes
}
]], options.repo_name)))
else
assert(f:write(string.format([[
%s: {
url: "%s",
enabled: yes
}
]], options.repo_name, base_repo_url())))
end
end技巧
注重安全性的读者应保持默认设置。
16.7.5.2 南京大学开源镜像站 NJU
除了 USTC 镜像站外,南京大学也提供了 FreeBSD pkgbase 的镜像源,其地址如下。
https://mirrors.nju.edu.cn/freebsd-pkg/16.7.5.3 网易开源镜像站 163
网易开源镜像站同样提供了 FreeBSD pkgbase 的镜像服务,地址如下。
https://mirrors.163.com/freebsd-pkg/16.7.6 附录:配置软件源
为了帮助读者更好地配置 pkgbase 源,下面整理了 FreeBSD 官方源的 pkgbase 信息,包括各分支的更新频率和对应的 URL 地址。
| 分支 | 更新频率 | URL 地址 |
|---|---|---|
| main(16.0-CURRENT) | 每天两次:08:00、20:00 | https://pkg.freebsd.org/${ABI}/base_latest |
| main(16.0-CURRENT) | 每周一次:星期日 20:00 | https://pkg.freebsd.org/${ABI}/base_weekly |
| stable/14 | 每天两次:08:00、20:00 | https://pkg.freebsd.org/${ABI}/base_latest |
| stable/14 | 每周一次:星期日 20:00 | https://pkg.freebsd.org/${ABI}/base_weekly |
| releng/14.0(RELEASE) | 每天两次:08:00、20:00 | https://pkg.freebsd.org/${ABI}/base_release_0 |
| releng/14.1(RELEASE) | 每天两次:08:00、20:00 | https://pkg.freebsd.org/${ABI}/base_release_1 |
| releng/14.2(RELEASE) | 每天两次:08:00、20:00 | https://pkg.freebsd.org/${ABI}/base_release_2 |
| releng/14.3(RELEASE) | 每天两次:08:00、20:00 | https://pkg.freebsd.org/${ABI}/base_release_3 |
以上表格中的时间已转换为北京时间(东八区),对应 FreeBSD 官方镜像站的发布时间。
如果官方源下载速度慢,可以考虑改用国内镜像。只需要替换 https://pkg.freebsd.org 这部分。
16.7.7 参考文献
- vermaden. ZFS Boot Environments Explained[EB/OL]. [2026-03-25]. https://vermaden.wordpress.com/2025/11/25/zfs-boot-environments-explained/. 详细阐释 ZFS 启动环境的原理与实践,包含跨版本 ZFS 池兼容方案。
- FreeBSD Project. BootEnvironments[EB/OL]. [2026-03-25]. https://wiki.freebsd.org/BootEnvironments. FreeBSD 官方关于启动环境的 Wiki。
- FreeBSD Project. bectl(8)[EB/OL]. [2026-03-25]. https://man.freebsd.org/cgi/man.cgi?query=bectl&sektion=8. ZFS 启动环境管理工具的官方技术规范。
- FreeBSD Project. freebsd-version -- print the version and patch level of the installed FreeBSD[EB/OL]. [2026-04-17]. https://man.freebsd.org/cgi/man.cgi?query=freebsd-version&sektion=1. 系统版本查询命令手册页。
- FreeBSD Project. uname -- print operating system name[EB/OL]. [2026-04-17]. https://man.freebsd.org/cgi/man.cgi?query=uname&sektion=1. 系统信息查询命令手册页。