26.2.更新 FreeBSD

及时应用安全补丁并升级操作系统到更新版本是持续系统管理的重要方面。FreeBSD 包含一个名为 freebsd-update 的实用程序,可用于执行这两项任务。

此实用程序支持对 FreeBSD 进行二进制安全性和勘误更新,无需手动编译和安装补丁或新内核。所有架构和当前安全团队支持的发行版均提供二进制更新。支持的发行版及其预计的生命周期结束日期列表在 https://www.FreeBSD.org/security/上列出。

此实用程序还支持将操作系统升级到次要点版本以及升级到另一个发行版分支。在升级到新版本之前,请查看其发布公告,因为其中包含与该版本相关的重要信息。发布公告可从 https://www.FreeBSD.org/releases/获取。

本节说明了 freebsd-update 使用的配置文件,演示了如何应用安全补丁以及如何升级到较小或较大的操作系统版本,并讨论了升级操作系统时的一些考虑因素。

26.2.1. 配置文件

freebsd-update 的默认配置文件可以直接使用。一些用户可能希望在 /etc/freebsd-update.conf 中微调默认配置,以更好地控制流程。该文件中的注释解释了可用选项,但以下内容可能需要更多解释:

# Components of the base system which should be kept updated.
Components world kernel

此参数控制哪些 FreeBSD 部分将保持最新。默认设置为更新整个基本系统和内核。也可以指定单独的组件,例如 src/base 或 src/sys。但是,最好的选择是将其保留为默认设置,因为将其更改以包括特定项目需要列出每个所需项目。随着时间的推移,这可能会导致灾难性后果,因为源代码和二进制文件可能不同步。

# Paths which start with anything matching an entry in an IgnorePaths
# statement will be ignored.
IgnorePaths /boot/kernel/linker.hints

要在更新过程中保留指定目录(例如/bin 或/sbin)不变,请将其路径添加到此语句中。此选项可用于防止 freebsd-update 覆盖本地修改。

# Paths which start with anything matching an entry in an UpdateIfUnmodified
# statement will only be updated if the contents of the file have not been
# modified by the user (unless changes are merged; see below).
UpdateIfUnmodified /etc/ /var/ /root/ /.cshrc /.profile

此选项仅会更新指定目录中未修改的配置文件。用户所做的任何更改将阻止这些文件的自动更新。还有另一个选项 KeepModifiedMetadata,它将指示 freebsd-update 在合并过程中保存更改。

# When upgrading to a new FreeBSD release, files which match MergeChanges
# will have any local changes merged into the version from the new release.
MergeChanges /etc/ /var/named/etc/ /boot/device.hints

freebsd-update 应尝试合并的配置文件目录列表。文件合并过程是一系列的 diff(1) 补丁。合并可以接受,打开编辑器,或导致 freebsd-update 中止。当有疑问时,请备份 /etc 目录并接受合并。

# Directory in which to store downloaded updates and temporary
# files used by FreeBSD Update.
# WorkDir /var/db/freebsd-update

此目录用于存放所有补丁和临时文件。在用户进行版本升级时,此位置应至少有 1GB 的磁盘空间可用。

# When upgrading between releases, should the list of Components be
# read strictly (StrictComponents yes) or merely as a list of components
# which *might* be installed of which FreeBSD Update should figure out
# which actually are installed and upgrade those (StrictComponents no)?
# StrictComponents no

当此选项设置为 yes 时,freebsd-update 将假定 Components 列表是完整的,并且不会尝试在列表外进行更改。实际上,freebsd-update 将尝试更新属于 Components 列表的每个文件。

请参考 freebsd-update.conf(5) 以获取更多详细信息。

26.2.2. 应用安全补丁

应用 FreeBSD 安全补丁的流程已经简化,管理员可以使用 freebsd-update 来保持系统完全补丁。有关 FreeBSD 安全公告的更多信息,请参阅 FreeBSD 安全公告。

FreeBSD 安全补丁可以使用以下命令进行下载和安装。第一条命令将确定是否有未完成的补丁可用,如果有,则将列出将在应用补丁时修改的文件。第二条命令将应用补丁。

# freebsd-update fetch
# freebsd-update install

如果更新应用了任何内核补丁,系统将需要重启以引导到打补丁的内核。如果补丁被应用于任何运行中的二进制文件,则应重启受影响的应用程序,以便使用二进制的打补丁版本。

系统可以通过将此条目添加到 /etc/crontab 来配置自动每天检查更新一次:

@daily                                  root    freebsd-update cron

如果存在补丁,它们将自动下载但不会被应用。用户将收到电子邮件,以便审查补丁并使用手动安装。

如果出现任何问题,freebsd-update 可以使用以下命令回滚最后一组更改:

# freebsd-update rollback
Uninstalling updates... done.

系统应在内核或任何内核模块被修改时重启,受影响的二进制文件应该重启。

只有通用内核可以被 freebsd-update 自动更新。如果安装了自定义内核,那么在 freebsd-update 完成更新安装后,必须重新构建和重新安装。默认内核名称为 GENERIC。uname(1) 命令可用于验证其安装。

除非/etc/freebsd-update.conf 中的默认配置已更改,否则 freebsd-update 将安装更新的内核源码以及其他所有更新。然后可以按照通常的方式重新构建和安装新的定制内核。

freebsd-update 分发的更新并不总是涉及内核。如果内核源码未被 freebsd-update install 修改,则无需重新构建定制内核。然而,freebsd-update 将始终更新/usr/src/sys/conf/newvers.sh。由 uname -r 报告的 -p 号所指示的当前补丁级别是从该文件中获取的。即使没有其他更改,重新构建定制内核也能让 uname 准确报告系统的当前补丁级别。这在维护多个系统时特别有帮助,因为它能让快速评估每个系统中安装的更新。

26.2.3. 执行次要和主要版本升级

从一个 FreeBSD 的次要版本升级到另一个称为次要版本升级。一个例子:

  • FreeBSD 13.1 到 13.2。

主要版本升级会增加主要版本号。一个例子:

  • 自 FreeBSD 13.2 到 14.0。

通过向 freebsd-update 提供一个发布版本目标,可以执行两种类型的升级。

在升级到新版本之前,请确保现有的 FreeBSD 安装在安全性和勘误补丁方面是最新的:

# freebsd-update fetch
# freebsd-update install

在 FreeBSD 13.1 系统上运行以下命令将其升级到 FreeBSD 13.2:

# freebsd-update -r 13.2-RELEASE upgrade

命令接收后,freebsd-update 将评估配置文件和当前系统,以尝试收集执行升级所需的信息。屏幕列表将显示已检测到和未检测到的组件。例如:

Looking up update.FreeBSD.org mirrors... 1 mirrors found.
Fetching metadata signature for 13.1-RELEASE from update1.FreeBSD.org... done.
Fetching metadata index... done.
Inspecting system... done.

The following components of FreeBSD seem to be installed:
kernel/smp src/base src/bin src/contrib src/crypto src/etc src/games
src/gnu src/include src/krb5 src/lib src/libexec src/release src/rescue
src/sbin src/secure src/share src/sys src/tools src/ubin src/usbin
world/base world/info world/lib32 world/manpages

The following components of FreeBSD do not seem to be installed:
kernel/generic world/catpages world/dict world/doc world/games
world/proflibs

Does this look reasonable (y/n)? y

在这一点上,freebsd-update 将尝试下载升级所需的所有文件。在某些情况下,用户可能会收到有关安装什么或如何继续的问题。

使用自定义内核时,上述步骤将会产生类似以下内容的警告:

WARNING: This system is running a "MYKERNEL" kernel, which is not a
kernel configuration distributed as part of FreeBSD 13.1-RELEASE.
This kernel will not be updated: you MUST update the kernel manually
before running "/usr/sbin/freebsd-update install"

此警告可以在此时安全地忽略。更新后的 GENERIC 内核将被用作升级过程中的中间步骤。

如所有补丁都已下载到本地系统,它们将被应用。这个过程可能需要一段时间,取决于机器的速度和工作负载。然后将合并配置文件。合并过程需要一些用户干预,因为文件可能被合并,或者编辑器可能会出现在屏幕上进行手动合并。每次成功合并的结果都会显示给用户,随着过程的继续。失败或被忽略的合并将导致过程中止。用户可能希望备份 /etc 并在以后的某个时间手动合并重要文件,如 master.passwd 或 group。

# freebsd-update install

首先将对内核和内核模块进行打补丁。如果系统正在运行自定义内核,请使用 nextboot(8) 将下一次引导的内核设置为更新的 /boot/GENERIC:

# nextboot -k GENERIC

现在应重启带有更新内核的机器:

# shutdown -r now

系统恢复在线状态之后,使用以下命令重启 freebsd-update。由于进程状态已保存,freebsd-update 将不会从头开始,而是继续进行下一阶段并删除所有旧的共享库和目标文件。

# freebsd-update install

升级现在已经完成。如果这是一个主版本升级,请重新安装所有 ports 和包,如在主版本升级后升级包中所述。

26.2.3.1. 使用 FreeBSD 9.X 及更高版本的自定义内核

在使用 freebsd-update 之前,请确保 /boot/GENERIC 中存在 GENERIC 内核的副本。如果自定义内核只构建过一次,/boot/kernel.old 中的内核就是 GENERIC 内核。只需将此目录重命名为 /boot/GENERIC。

如果已经构建了定制内核超过一次,或者不知道定制内核已经构建了多少次,请获取与当前操作系统版本匹配的 GENERIC 内核的副本。如果可以访问系统物理设备,则可以从安装媒体安装 GENERIC 内核:

# mount /cdrom
# cd /cdrom/usr/freebsd-dist
# tar -C/ -xvf kernel.txz boot/kernel/kernel

或者,可以从源代码重新构建并安装 GENERIC 内核:

# cd /usr/src
# make kernel __MAKE_CONF=/dev/null SRCCONF=/dev/null

为了使该内核被 freebsd-update 识别为 GENERIC 内核,GENERIC 配置文件不能以任何方式被修改。建议构建内核时不使用任何其他特殊选项。

重启到通用内核不需要,因为 freebsd-update 只需要/boot/GENERIC 存在。

26.2.3.2. 在主版本升级后升级软件包

通常,在次要版本升级后,已安装的应用程序将继续正常工作。主要版本使用不同的应用程序二进制接口(ABIs),这将破坏大多数第三方应用程序。在主要版本升级后,所有已安装的软件包和ports都需要升级。可以使用 pkg upgrade 来升级软件包。要升级已安装的ports,请使用像ports-mgmt/portmaster 这样的实用程序。

所有已安装软件包的强制升级将使用存储库中的新版本替换软件包,即使版本号未增加。这是因为在 FreeBSD 主要版本之间升级时 ABI 版本发生变化。可以通过执行以下操作来完成强制升级:

# pkg-static upgrade -f

可以使用此命令重新构建所有已安装的应用程序:

# portmaster -af

此命令将显示每个具有可配置选项的应用程序的配置屏幕,并等待用户与这些屏幕进行交互。为了防止这种行为,并仅使用默认选项,请在上述命令中包含 -G。

软件升级完成后,通过最终调用 freebsd-update 来完成升级过程,以便处理升级过程中的所有细节:

# freebsd-update install

如果临时使用了通用内核,则现在是使用“配置 FreeBSD 内核”中的说明构建和安装新的自定义内核的时候。

将计算机重启到新的 FreeBSD 版本。升级过程现在已经完成。

26.2.4. 系统状态比较

安装的 FreeBSD 版本状态可以使用 freebsd-update IDS 进行测试。该命令评估系统实用程序、库和配置文件的当前版本,并可用作内置入侵检测系统(IDS)。

开始比较之前,请指定要保存结果的输出文件:

# freebsd-update IDS >> outfile.ids

系统现在将被检查,将会列出大量文件,以及发布版本中已知值和当前安装中的 SHA256 哈希值,这些值将被发送到指定的输出文件。

列表中的条目非常长,但输出格式可以很容易地解析。例如,要获得与发布中的文件不同的所有文件的列表,请发出以下命令:

# cat outfile.ids | awk '{ print $1 }' | more
/etc/master.passwd
/etc/motd
/etc/passwd
/etc/pf.conf

此示例输出已被截断,因为还有很多其他文件。一些文件具有自然修改。例如,如果用户已添加到系统中,则/etc/passwd 将被修改。内核模块可能会有所不同,因为 freebsd-update 可能已将其更新。要排除特定的文件或目录,请将它们添加到/etc/freebsd-update.conf 中的 IDSIgnorePaths 选项。

最后更新于

FreeBSD 中文社区