第二十六章 更新和升级FreeBSD26.1. 简介26.2. FreeBSD更新26.2.1. 配置文件26.2.2. 应用安全补丁26.2.3. 执行次要和主要版本升级26.2.3.1. FreeBSD 9.X及更高版本的自定义内核26.2.3.2. 主要版本升级后升级软件包26.2.4. 系统状态比较26.3. 正在更新启动代码26.4. 更新文档集26.4.1. 从源更新文档26.5. 跟踪开发分支26.5.1. 使用FreeBSD-CURRENT26.5.2. 使用FreeBSD-STABLE26.5.3. N-number26.6. 从源代码更新FreeBSD26.6.1. 快速启动26.6.2. 准备源代码更新26.6.3. 更新源26.6.4. 从源代码构建26.6.4.1. 执行干净的构建26.6.4.2. 设置作业数量26.6.4.3. 只构建内核26.6.4.4. 构建自定义内核26.6.5. 安装编译代码26.6.6. 完成更新26.6.6.1. 将配置文件与 etcupdate(8) 合并26.6.6.2. 检查过时的文件和库26.6.6.3. 更新后重新启动26.7. 用基本系统包更新FreeBSD26.7.1. 将主机转换为使用pkgbase26.7.2. 使用pkgbase升级主机26.7.2.1. 执行主要版本升级26.7.3. 手动构建pkgbase并将其发布到本地网络26.8. 多台机器的跟踪26.9. 在非FreeBSD主机上构建
FreeBSD在两个版本之间不断开发。有些人更喜欢使用官方发布的版本,而另一些人则更喜欢与最新发展保持同步。然而,即使是官方版本也经常更新安全和其他关键修复程序。无论使用哪个版本,FreeBSD都提供了所有必要的工具来保持系统更新,并允许在版本之间轻松升级。本章描述了如何跟踪开发系统和保持FreeBSD系统最新的基本工具。
阅读本章后,你会知道:
• 如何使用FreeBSD更新或Git使FreeBSD系统保持最新。 • 如何将已安装系统的状态与已知的原始副本进行比较。 • 如何使用Git或文档端口保持已安装文档的最新状态。 • 两个开发分支之间的区别:FreeBSD-STABLE和FreeBSD-CURRENT。 • 如何重建和重新安装整个基础系统。
在阅读本章之前,您应该:
• 正确设置网络连接(【34. 高级网络】)。 • 知道如何安装其他第三方软件(【4. 安装应用程序:软件包和端口】)。
xxxxxxxxxx在本章中,git用于获取和更新FreeBSD源代码。可选地,可以使用devel/git端口或包。及时应用安全补丁并升级到较新版本的操作系统是持续系统管理的重要方面。FreeBSD包含一个名为 freebsd-update 的实用程序,可用于执行这两项任务。
此实用程序支持FreeBSD的二进制安全和勘误表更新,无需手动编译和安装补丁或新内核。二进制更新可用于安全团队目前支持的所有架构和版本。受支持的释放清单及其估计寿命终止日期列于 https://www.FreeBSD.org/security/ 。
此实用程序还支持操作系统升级到次要版本,以及升级到另一个版本分支。在升级到新版本之前,请查看其发布公告,因为其中包含与该版本相关的重要信息。发布公告可从以下网址获得 https://www.FreeBSD.org/releases/ 。
xxxxxxxxxx如果存在利用freebsd-update(8)功能的crontab(5),则必须在升级操作系统之前将其禁用。本节介绍 freebsd-update 使用的配置文件,演示如何应用安全补丁以及如何升级到次要或主要操作系统版本,并讨论升级操作系统时的一些注意事项。
freebsd-update 的默认配置文件按原样工作(works as-is)。一些用户可能希望调整 /etc/freebsd-update.conf 中的默认配置,以便更好地控制进程。此文件中的注释解释了可用选项,但以下内容可能需要更多解释:
xxxxxxxxxx# Components of the base system which should be kept updated.Components world kernel此参数控制FreeBSD的哪些部分将保持最新。默认情况下是更新整个基础系统和内核。可以指定单个组件,例如 src/base 或 src/sys 。但是,最好的选择是将其保留为默认值,因为将其更改为包含特定项目需要列出每个所需的项目。随着时间的推移,这可能会产生灾难性的后果,因为源代码和二进制文件可能会不同步。
xxxxxxxxxx# Paths which start with anything matching an entry in an IgnorePaths# statement will be ignored.IgnorePaths /boot/kernel/linker.hints要在更新过程中保持指定目录(如 /bin 或 /sbin )不变,请将它们的路径添加到此语句中。此选项可用于防止 freebsd-update 覆盖本地修改。
xxxxxxxxxx# 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此选项将仅更新指定目录中未修改的配置文件。用户所做的任何更改都将阻止这些文件的自动更新。还有另一个选项 KeepModifiedMatadata ,它将指示 freebsd-update 在合并过程中保存更改。
xxxxxxxxxx# 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.hintsfreebsd-update 应尝试合并的包含配置文件的目录列表。文件合并过程是一系列 diff(1) 补丁。合并被接受、打开编辑器或导致 freebsd-update 中止。如有疑问,备份 /etc 并接受合并。
xxxxxxxxxx# Directory in which to store downloaded updates and temporary# files used by FreeBSD Update.# WorkDir /var/db/freebsd-update此目录是放置所有补丁和临时文件的位置。在用户进行版本升级的情况下,此位置应至少有1GB的可用磁盘空间。
xxxxxxxxxx# 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) 。
应用FreeBSD安全补丁的过程已经简化,允许管理员使用 freebsd-update 来保持系统完全修补。有关FreeBSD安全公告的更多信息,请参阅 【16.16. FreeBSD安全公告】。
FreeBSD安全补丁可以使用以下命令下载和安装。第一个命令将确定是否有任何未完成的补丁可用,如果有,将列出应用补丁后将被修改的文件。第二个命令将应用补丁。
xxxxxxxxxx# freebsd-update fetch# freebsd-update install如果更新应用了任何内核补丁,系统将需要重新启动才能引导到补丁内核。如果修补程序应用于任何正在运行的二进制文件,则应重新启动受影响的应用程序,以便使用修补后的二进制文件版本。
xxxxxxxxxx通常,用户需要准备重新启动系统。要知道系统是否因内核更新而需要重新启动,请执行命令freebsd-version -k 和 uname -r。如果输出不同,请重新启动系统。通过将此条目添加到 /etc/crontab ,可以将系统配置为每天自动检查一次更新:
xxxxxxxxxx@daily root freebsd-update cron如果存在补丁,它们将自动下载,但不会应用。root用户将收到一封电子邮件,以便可以查看补丁并使用freebsd更新安装手动安装。
如果出现任何问题,freebsd-update 可以使用以下命令回滚最后一组更改:
xxxxxxxxxx# freebsd-update rollbackUninstalling updates... done.同样,如果内核或任何内核模块被修改,则应重新启动系统,并应重新启动任何受影响的二进制文件。
只有GENERIC内核可以通过 freebsd-update 自动更新。如果安装了自定义内核,则必须在 freebsd-update 完成安装更新后重新构建并重新安装。默认内核名称为GENERIC。uname(1) 命令可用于验证其安装。
xxxxxxxxxx始终在/boot/GENERIC中保留GENERIC内核的副本。它将有助于诊断各种问题和执行版本升级。有关如何获取GENERIC内核副本的说明,请参阅【26.2.3.1. FreeBSD 9.X及更高版本的自定义内核】。除非 /etc/freebsd-update.conf 中的默认配置已更改,否则 freebsd-update 将安装更新的内核源代码以及其余更新。然后,可以按照通常的方式重建和重新安装新的自定义内核。
freebsd-update 分发的更新并不总是涉及内核。如果内核源代码没有被 freebsd-update install 修改,则没有必要重建自定义内核。但是, freebsd-update 将始终更新 /usr/src/sys/conf/newvers.sh 。当前补丁级别,如 uname -r 报告的 -p 编号所示,是从该文件中获得的。重建自定义内核,即使没有其他更改,也允许 uname 准确报告系统的当前补丁级别。这在维护多个系统时特别有用,因为它允许快速评估每个系统中安装的更新。
从FreeBSD的一个次要版本升级到另一个版本称为次要版本(minor version)升级。举个例子:
主要版本(major version)升级会增加主要版本号。举个例子:
通过提供带有发布版本目标的 freebsd-update ,可以执行这两种类型的升级。
xxxxxxxxxx在每次新的RELEASE之后,FreeBSD包构建服务器将在有限的时间内不使用较新版本的操作系统。这为许多在发布公告后没有立即升级的用户提供了连续性。例如: • 13.1和13.2用户的软件包将构建在运行13.1的服务器上,直到13.1达到生命周期结束--并且,批判性地: • 基于13.1构建的内核模块可能不适合13.2。因此,对于任何次要或主要的操作系统升级,如果您的软件包要求包括任何内核模块: • 准备从源代码构建模块。xxxxxxxxxx如果系统正在运行自定义内核,请在开始升级之前确保/boot/GENERIC中存在GENERIC内核的副本。有关如何获取GENERIC内核副本的说明,请参阅FreeBSD 9.X及更高版本的自定义内核。在升级到新版本之前,请确保现有的FreeBSD安装在安全和勘误补丁方面是最新的:
xxxxxxxxxx# freebsd-update fetch# freebsd-update install以下命令在FreeBSD 13.1系统上运行时,会将其升级到FreeBSD 13.2:
xxxxxxxxxx# freebsd-update -r 13.2-RELEASE upgrade收到命令后,freebsd-update 将评估配置文件和当前系统,以尝试收集执行升级所需的信息。屏幕列表将显示已检测到和未检测到的组件。例如:
xLooking 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/gamessrc/gnu src/include src/krb5 src/lib src/libexec src/release src/rescuesrc/sbin src/secure src/share src/sys src/tools src/ubin src/usbinworld/base world/info world/lib32 world/manpagesThe following components of FreeBSD do not seem to be installed:kernel/generic world/catpages world/dict world/doc world/gamesworld/proflibsDoes this look reasonable (y/n)? y此时,freebsd-update 将尝试下载升级所需的所有文件。在某些情况下,用户可能会被提示有关安装什么或如何继续的问题。
使用自定义内核时,上述步骤将产生类似于以下内容的警告:
xxxxxxxxxxWARNING: This system is running a "MYKERNEL" kernel, which is not akernel configuration distributed as part of FreeBSD 13.1-RELEASE.This kernel will not be updated: you MUST update the kernel manuallybefore running "/usr/sbin/freebsd-update install"【警告:此系统正在运行“MYKERNEL”内核,该内核不是作为FreeBSD 13.1-RELEASE的一部分分发的内核配置。此内核将不会更新:在运行“/usr/sbin/freebsd-update install”之前,您必须手动更新内核】此时可以安全地忽略此警告。更新的GENERIC内核将用作升级过程中的中间步骤。
一旦所有补丁都下载到本地系统,它们将被应用。此过程可能需要一段时间,具体取决于机器的速度和工作负载。然后将合并配置文件。合并过程需要一些用户干预,因为文件可能会被合并,或者屏幕上可能会出现编辑器进行手动合并。随着过程的继续,每次成功合并的结果都会显示给用户。失败或被忽略的合并将导致进程中止。用户可能希望备份 /etc ,并在以后手动合并重要文件,如 master.passwd 或 group 。
xxxxxxxxxx系统尚未更改,因为所有修补和合并都发生在另一个目录中。一旦所有补丁都成功应用,所有配置文件都已合并,过程似乎会顺利进行,用户可以使用以下命令将更改提交到磁盘: # freebsd-update install内核和内核模块将首先进行修补。如果系统使用自定义内核运行,请使用 nextboot(8) 将下一次启动的内核设置为更新的 /boot/GENERIC :
xxxxxxxxxx# nextboot -k GENERICxxxxxxxxxx在使用GENERIC内核重新启动之前,如果正在更新的机器是远程访问的,请确保它包含系统正确启动并连接到网络所需的所有驱动程序。特别是,如果正在运行的自定义内核包含通常由内核模块提供的内置功能,请确保使用/boot/loader.conf工具将这些模块临时加载到GENERIC内核中。建议在升级过程完成之前禁用非必要服务以及任何磁盘和网络装载。现在应该使用更新的内核重新启动机器:
xxxxxxxxxx# shutdown -r now系统重新联机后,使用以下命令重新启动 freebsd-update 。由于进程的状态已保存, freebsd-update 将不会从头开始,而是将进入下一阶段并删除所有旧的共享库和对象文件。
xxxxxxxxxx# freebsd-update installxxxxxxxxxx根据是否有任何库版本号被碰撞(bumped),可能只有两个安装阶段,而不是三个。升级现已完成。如果这是一次主要版本升级,请按照【26.2.3.2. 主要版本升级后升级软件包】中的说明重新安装所有端口和软件包。
在使用 freebsd-update 之前,请确保 /boot/GENERIC 中存在GENERIC内核的副本。如果自定义内核只构建过一次,那么 /boot/kernel.old 中的内核就是 GENERIC 内核。只需将此目录重命名为 /boot/GENERIC 。
如果自定义内核已经构建了多次,或者不知道自定义内核构建了多少次,请获取与当前操作系统版本匹配的 GENERIC 内核副本。如果可以物理访问系统,则可以从安装介质安装 GENERIC 内核的副本:
xxxxxxxxxx# mount /media# cd /media/usr/freebsd-dist# tar -C/ -xvf kernel.txz boot/kernel/kernel或者,可以从源代码重新构建和安装 GENERIC 内核:
xxxxxxxxxx# cd /usr/src# make kernel __MAKE_CONF=/dev/null SRCCONF=/dev/null为了通过 freebsd-update 将此内核标识为 GENERIC 内核,GENERIC配置文件不得以任何方式进行修改。还建议在构建内核时不使用任何其他特殊选项。
不需要重新启动到GENERIC内核,因为 freebsd-update 只需要 /boot/GENERIC 存在。
一般来说,安装的应用程序在小版本升级后将继续正常工作。主要版本使用不同的应用程序二进制接口(Application Binary Interfaces,ABIs),这将破坏大多数第三方应用程序。在主要版本升级后,所有安装的软件包和端口都需要升级。可以使用 pkg upgrade 升级软件包。要升级已安装的端口,请使用 ports-mgmt/portmaster 等实用程序。
即使版本号没有增加,强制升级所有已安装的软件包也会用存储库中的新版本替换这些软件包。这是必需的,因为在FreeBSD的主要版本之间升级时,ABI版本会发生变化。强制升级可以通过执行以下操作来实现:
xxxxxxxxxx# pkg-static upgrade -f使用以下命令可以重建从端口集合安装的所有应用程序:
xxxxxxxxxx# portmaster -af此命令将显示每个具有可配置选项的应用程序的配置屏幕,并等待用户与这些屏幕进行交互。为了防止这种行为,并且只使用默认选项,请在上述命令中包含 -G 。
软件升级完成后,最后调用 freebsd-update 完成升级过程,以解决升级过程中的所有问题:
xxxxxxxxxx# freebsd-update install如果临时使用了GENERIC内核,现在是使用【10. 配置FreeBSD内核】中的说明构建和安装新的自定义内核的时候了。
将计算机重新启动到新的FreeBSD版本。升级过程现已完成。
可以使用 freebsd-update IDS 测试已安装的FreeBSD版本与已知良好副本的状态。此命令评估系统实用程序、库和配置文件的当前版本,可以用作内置的入侵检测系统(Intrusion Detection System,IDS)。
xxxxxxxxxx此命令不能替代真正的IDS,如security/snort。由于freebsd-update将数据存储在磁盘上,因此篡改的可能性是显而易见的。虽然使用kern.securelevel并在不使用时将freebsd-update数据存储在只读文件系统上可以降低这种可能性,但更好的解决方案是将该系统与安全磁盘(如DVD或安全存储的外部USB磁盘设备)进行比较。二进制验证中描述了一种使用内置实用程序提供IDS功能的替代方法要开始比较,请指定输出文件以将结果保存到:
xxxxxxxxxx# freebsd-update IDS >> outfile.ids现在将检查系统,并将一长串文件以及版本和当前安装中已知值的SHA256哈希值发送到指定的输出文件。
列表中的条目非常长,但输出格式可能很容易解析。例如,要获取与版本中不同的所有文件的列表,请发出以下命令:
xxxxxxxxxx# 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 选项中。
以下手册描述了引导代码和引导加载程序的升级过程:gpart(8) 、gptboot(8) 和 loader.efi(8) 。
文档是FreeBSD操作系统不可或缺的一部分。虽然FreeBSD网站(文档门户)上始终提供最新版本的FreeBSD文档,但拥有FreeBSD网站、手册、常见问题解答和文章的最新本地副本会很方便。
本节介绍如何使用源代码或FreeBSD Ports Collection来保持FreeBSD文档的本地副本最新。
有关编辑和提交文档更正的信息,请参阅新贡献者FreeBSD文档项目入门(新贡献者的FreeBSD文档项目初级)。
从源代码重建FreeBSD文档需要一组不属于FreeBSD基础系统的工具。可以按照FreeBSD文档项目入门中的这些步骤安装所需的工具。
安装后,使用 git 获取文档源的干净副本:
xxxxxxxxxx# git clone https://git.FreeBSD.org/doc.git /usr/doc文档源的初始下载可能需要一段时间。让它运行直到完成。
可以通过运行以下命令获取文档源的未来更新:
xxxxxxxxxx# git pull一旦将文档源的最新快照提取到 /usr/doc ,就可以更新已安装的文档了。
可以通过键入以下命令来执行完整更新:
xxxxxxxxxx# cd /usr/doc# makeFreeBSD有两个开发分支:FreeBSD-CURRENT 和 FreeBSD-STABLE。
本节解释了每个分支及其目标受众,以及如何使系统与每个分支保持最新状态。
FreeBSD-CURRENT是FreeBSD开发的“前沿”(bleeding edge),FreeBSD-CURRENT用户需要具备高度的技术技能。希望跟踪开发分支的技术较少的用户应该跟踪FreeBSD-STABLE。
FreeBSD-CURRENT是FreeBSD的最新源代码,包括正在进行的工作、实验性更改和过渡机制,这些可能会也可能不会出现在下一个官方版本中。虽然许多FreeBSD开发人员每天编译FreeBSD-CURRENT源代码,但有时源代码可能无法构建。这些问题会尽快得到解决,但FreeBSD-CURRENT是否会带来灾难或新功能可能取决于源代码何时同步。
FreeBSD CURRENT提供给三个主要关注组:
FreeBSD-CURRENT不应被视为在下一个版本之前获得新功能的快速通道,因为预发布功能尚未经过充分测试,很可能包含错误。这不是一种快速修复bug的方法,因为任何给定的提交都可能引入新的bug,也可能修复现有的bug。FreeBSD-CURRENT在任何方面都不受“官方支持”。
要跟踪FreeBSD-CURRENT:
git 用于从FreeBSD Git存储库的主分支中检出-CURRENT代码(有关详细信息,请参阅【A.2. 使用git】)。FreeBSD-STABLE是主要版本发布的开发分支。更改进入此分支的速度较慢,并且通常假设它们首先在FreeBSD-CURRENT中进行了测试。这仍然是一个开发分支,在任何时候,FreeBSD-STABLE的源代码可能适合也可能不适合一般使用。它只是另一个工程开发轨道,而不是最终用户的资源。没有资源进行测试的用户应该运行最新版本的FreeBSD。
那些有兴趣跟踪或参与FreeBSD开发过程的人,特别是当它与FreeBSD的下一个版本相关时,应该考虑遵循FreeBSD-STABLE。
虽然FreeBSD-STABLE分支应该始终编译和运行,但这并不能保证。由于运行FreeBSD-STABLE的人比运行FreeBSD-CURRENT的人多,因此不可避免的是,有时会在FreeBSD-STABLE中发现一些在FreeBSD-CURRENT中不明显的错误和极端情况。因此,不应该盲目地跟踪FreeBSD-STABLE。特别重要的是,在没有在开发或测试环境中彻底测试代码的情况下,不要将任何生产服务器更新到FreeBSD-STABLE。
追踪FreeBSD-STABLE:
git 查看所需分支的源代码。分支名称,如 stable/13 ,列在 www.freebsd.org/releng 上。在追踪bug时,了解哪些版本的源代码用于创建出现问题的系统非常重要。FreeBSD提供编译到内核中的版本信息。uname(1) 检索此信息,例如:
xxxxxxxxxx% uname -vFreeBSD 14.0-CURRENT #112 main-n247514-031260d64c18: Tue Jun 22 20:43:19 MDT 2021 fred@machine:/usr/home/fred/obj/usr/home/fred/git/head/amd64.amd64/sys/FRED最后一个字段提供了有关内核名称、构建它的人以及编译它的位置的信息。查看第四个字段,它由几个部分组成:
xxxxxxxxxxmain-n247514-031260d64c18main ①n247514 ②031260d64c18 ③④ ① Git分支名称。注:n-numbers的比较仅适用于项目发布的分支(main、stable/XX 和 releng/XX)。本地分支将有n-numbers,这些数字将与其父分支的提交重叠。
② n-number是从行中包含的Git哈希开始,返回Git存储库开头的提交的线性计数。
③ 检出树的Git哈希值
④ 有时,当内核构建在具有未提交更改的树中时,会出现后缀 -dirty 。在这个例子中没有它,因为FRED内核是从原始的签出构建的。
git rev-list 命令用于查找与Git哈希对应的n-number。例如:
xxxxxxxxxx% git rev-list --first-parent --count 031260d64c18 ①247514 ②① 要转换的git哈希(重用上述示例中的哈希) ② n-number。
通常,这个数字并不那么重要。然而,当提交错误修复时,这个数字可以很容易地快速确定当前运行的系统中是否存在修复。开发人员通常会参考提交的哈希值(或提供具有该哈希值的URL),但不会参考n-number,因为哈希值是更改的易见标识符,而n号则不是。安全公告和勘误通知也会注明一个n-number,可以直接与您的系统进行比较。当你需要使用浅层Git克隆时,你无法可靠地比较年数,因为 git rev-list 命令会计算浅层克隆遗漏的存储库中的所有修订。
通过从源代码编译来更新FreeBSD比二进制更新有几个优点。代码可以通过选项构建,以利用特定的硬件。基础系统的某些部分可以使用非默认设置构建,也可以在不需要或不需要的地方完全省略。构建过程更新系统比安装二进制更新需要更长的时间,但允许完全定制以生成定制版本的FreeBSD。
这是通过从源代码构建来更新FreeBSD的典型步骤的快速参考。后面的部分将更详细地描述该过程。
xxxxxxxxxx当从mergemaster(8)切换到etcupdate(8)时,第一次运行可能会错误地合并更改,从而产生虚假冲突。为防止这种情况,请在更新源和构建新世界之前执行以下步骤: # etcupdate extract ① # etcupdate diff ②① 引导存储/etc文件的数据库;有关更多信息,请参阅etcupdate(8)。② 引导后检查差异。修剪不再需要的任何本地更改,以减少未来更新中发生冲突的可能性。更新和构建
xxxxxxxxxx# git -C /usr/src pull ①check /usr/src/UPDATING ②# cd /usr/src ③# make -j4 buildworld ④# make -j4 kernel ⑤# shutdown -r now ⑥# etcupdate -p ⑦# cd /usr/src ⑧# make installworld ⑨# etcupdate -B ⑩# shutdown -r now ⑪① 获取源代码的最新版本。有关获取和更新源的更多信息,请参阅【26.6.3.更新源】。
② 在从源代码构建之前或之后,请查看 /usr/src/UPDATING 以了解所需的任何手动步骤。
③ 转到源目录。
④ 编译世界,除了内核之外的一切。
⑤ 编译并安装内核。这相当于 make buildkernel installkernel 。
⑥ 将系统重新引导到新内核。
⑦ 在installworld之前更新并合并 /etc/required 中的配置文件。
⑧ 转到源目录。
⑨ 安装world。
⑩ 更新并合并 /etc/ 中的配置文件。
⑪ 重新启动系统以使用新建的world和内核。
阅读 /usr/src/UPDATING 。本文件描述了更新之前或之后必须执行的任何手动步骤。
FreeBSD源代码位于 /usr/src/ 。更新此源代码的首选方法是通过Git版本控制系统。验证源代码是否受版本控制:
xxxxxxxxxx# cd /usr/src# git remote --vorigin https://git.freebsd.org/src.git (fetch)origin https://git.freebsd.org/src.git (push)这表示 /usr/src/ 受版本控制,可以用 git(1) 更新:
xxxxxxxxxx# git -C /usr/src pull如果目录最近没有更新,更新过程可能需要一些时间。完成后,源代码是最新的,下一节中描述的构建过程可以开始。
xxxxxxxxxx获取来源:如果输出显示【fatal: not a git repository】,则那里的文件丢失或以不同的方法安装。需要重新检查源。表39. FreeBSD版本和存储库分支
| uname -r输出 | 存储库路径 | 描述 |
|---|---|---|
| X.Y-RELEASE | releng/X.Y | Release版本加上关键的安全和错误修复补丁。建议大多数用户使用此分支。 |
| X.Y-STABLE | stable/X | Release版本以及该分支上的所有其他开发。STABLE是指应用程序二进制接口(ABI)不变,因此为早期版本编译的软件仍然可以运行。例如,编译为在FreeBSD 10.1上运行的软件仍将在稍后编译的FreeBSD 10-STABLE上运行。 STABLE分支偶尔会出现可能影响用户的错误或不兼容,尽管这些问题通常会很快得到修复。 |
| X-CURRENT | main | FreeBSD最新未发布的开发版本。CURRENT分支可能存在重大错误或不兼容,建议仅对高级用户使用。 |
确定哪个版本的FreeBSD正在与 uname(1) 一起使用:
xxxxxxxxxx# uname -r13.2-RELEASE基于FreeBSD版本和存储库分支,用于更新 13.2-RELEASE 的源代码的存储库路径为 releng/13.2 。检出源时使用该路径:
xxxxxxxxxx# mv /usr/src /usr/src.bak ①# git clone --branch releng/13.2 https://git.FreeBSD.org/src.git /usr/src ②① 把旧目录移开。如果此目录中没有本地修改,则可以将其删除。 ② FreeBSD版本和存储库分支的路径将添加到存储库URL中。第三个参数是本地系统上源代码的目标目录。
world 或除内核之外的所有操作系统都是编译的。首先这样做是为了提供构建内核的最新工具。然后构建内核本身:
xxxxxxxxxx# cd /usr/src# make buildworld# make buildkernel编译后的代码被写入 /usr/obj 。
这些是基本步骤。下面描述了控制构建的其他选项。
某些版本的FreeBSD构建系统将以前编译的代码保留在临时对象目录 /usr/obj 中。这可以通过避免重新编译未更改的代码来加快以后的构建速度。要强制对所有内容进行彻底重建,请在开始构建之前使用 cleanworld :
xxxxxxxxxx# make cleanworld增加多核处理器上的构建作业数量可以提高构建速度。使用 sysctl hw.ncpu 确定内核数量。处理器各不相同,不同版本的FreeBSD使用的构建系统也是如此,因此测试是了解不同数量的作业如何影响构建速度的唯一可靠方法。作为起点,考虑内核数量的一半到两倍之间的值。作业数用 -j 指定。
示例39. 增加构建工作数量
用四个作业构建世界和内核:
xxxxxxxxxx# make -j4 buildworld buildkernel如果源代码已更改,则必须完成 buildworld 。之后,可以随时运行构建内核的 buildkernel 。只构建内核:
xxxxxxxxxx# cd /usr/src# make buildkernel标准的FreeBSD内核基于一个名为GENERIC的内核配置文件。GENERIC内核包括最常用的设备驱动程序和选项。有时,构建自定义内核、添加或删除设备驱动程序或选项以满足特定需求是有用或必要的。
例如,开发RAM严重受限的小型嵌入式计算机的人可以删除不需要的设备驱动程序或选项,使内核稍微变小。
内核配置文件位于 /usr/src/sys/arch/conf/ 中,其中 arch 是 uname -m 的输出。在大多数计算机上,即 amd64 上,配置文件目录为 /usr/src/sys/amd64/conf/ 。
xxxxxxxxxx/usr/src可以删除或重新创建,因此最好将自定义内核配置文件保存在单独的目录中,如/root。将内核配置文件链接到conf目录。如果该目录被删除或覆盖,则可以将内核配置重新链接到新目录中。可以通过复制GENERIC配置文件来创建自定义配置文件。在这个例子中,新的自定义内核是用于存储服务器的,因此被命名为STORAGESERVER:
xxxxxxxxxx# cp /usr/src/sys/amd64/conf/GENERIC /root/STORAGESERVER# cd /usr/src/sys/amd64/conf# ln -s /root/STORAGESERVER .然后编辑 /root/STORAGESERVER ,添加或删除设备或选项,如 config(5) 所示。
通过在命令行上将 KERNCONF 设置为内核配置文件来构建自定义内核:
xxxxxxxxxx# make buildkernel KERNCONF=STORAGESERVER在 buildworld 和 buildkernel 步骤完成后,安装新的内核和world:
xxxxxxxxxx# cd /usr/src# make installkernel# shutdown -r now# cd /usr/src# make installworld# shutdown -r now如果构建了自定义内核,则还必须将 KERNCONF 设置为使用新的自定义内核:
xxxxxxxxxx# cd /usr/src# make installkernel KERNCONF=STORAGESERVER# shutdown -r now# cd /usr/src# make installworld# shutdown -r now最后几项任务完成了更新。任何修改过的配置文件都会与新版本合并,过时的库会被定位并删除,然后系统会重新启动。
etcupdate(8) 合并etcupdate(8) 是一个工具,用于管理未作为安装世界的一部分更新的文件的更新,例如位于 /etc/ 中的文件。它通过将对这些文件所做的更改与本地版本进行三方合并来管理更新。 etcupdate(8) 旨在最大限度地减少用户干预量。
xxxxxxxxxx一般来说,etcupdate(8)的工作不需要任何具体的参数。然而,在第一次使用etcupdate(8)时,有一个方便的中间命令用于健全性检查: # etcupdate diff此命令允许用户审核配置更改。如果 etcupdate(8) 无法自动合并文件,则可以通过发出以下命令进行手动交互来解决合并冲突:
xxxxxxxxxx# etcupdate resolvexxxxxxxxxx当从mergemaster(8)切换到etcupdate(8)时,第一次运行可能会错误地合并更改,从而产生虚假冲突。为防止这种情况,请在更新源和构建新世界之前执行以下步骤: # etcupdate extract ① # etcupdate diff ②① 引导/etc文件的数据库;有关更多信息,请参阅etcupdate(8)。② 引导后检查差异。修剪不再需要的任何本地更改,以减少未来更新中发生冲突的可能性。更新后,一些过时的文件或目录可能会保留。这些文件可以在以下位置找到:
xxxxxxxxxx# make check-old然后删除:
xxxxxxxxxx# make delete-old一些过时的库也可以保留。这些可以通过以下方式检测到:
xxxxxxxxxx# make check-old-libs然后删除:
xxxxxxxxxx# make delete-old-libs删除库后,仍在使用这些旧库的程序将停止工作。删除旧库后,必须重建或替换这些程序。
xxxxxxxxxx当已知所有旧文件或目录都可以安全删除时,可以通过在命令中设置BATCH_DELETE_OLD_FILE来避免按y和Enter键删除每个文件。例如: # make BATCH_DELETE_OLD_FILES=yes delete-old-libs更新后的最后一步是重新启动计算机,以便所有更改生效:
xxxxxxxxxx# shutdown -r now从14.0-RELEASE开始,FreeBSD项目使用 pkg(8) 发布了一组内核和基础系统的包。这些可以以用户习惯的同样方便的方式使用,用于添加和升级移植的软件,但用于内核和用户区本身。这些包及其用法通常被称为pkgbase。
软件包自 2023年10月 以来一直可用,被认为是FreeBSD 14版本的实验性软件包。
从15.0-RELASE开始,基本系统包将成为默认和官方支持的方式,用于安装新的FreeBSD实例,以及在次要和主要版本之间进行更新和升级。
xxxxxxxxxx从15.0-RELASE开始,长时间运行的freebsd-update(8)工具将仅在早期的13和14版本分支上受支持。基本系统包替换:
• tarball分发集,如 base.txz 或 kernel.txz ,历史上用于安装带有 bsdinstall(8) 的操作系统。
• freebsd-update(8) 用于操作系统的更新。
基础系统包补充了从源代码构建和安装,对于那些希望构建自己的自定义内核或用户空间的人来说,仍然可以使用源代码。也可以从本地来源构建自定义基础系统包,也可以仅依赖官方提供的包。
安装了FreeBSD 14.0-RELEASE或更高版本的系统可以转换为使用基本系统包。对于早期版本,建议先升级到最新版本,然后再转换。
FreeBSD基金会赞助了一种名为 pkgbasify 的工具的开发,对于大多数用户来说,这将是将系统转换为使用Base System软件包的最简单、最安全的方法。
xxxxxxxxxx请注意,此迁移需要高达5GiB的额外可用空间,以下载、解压缩和重新定位任何冲突的文件。pkgbasify工具不会检查这一点,用户有责任在运行迁移之前确保有足够的可用空间。pkgbasify(8) (或 D51594 或端口请求的任何结果)执行6个主要任务:
• 使用 bectl(8) 创建备份引导环境(仅限ZFS)
• 创建新的包存储库配置文件
• 升级现有的系统组件,如基础、内核、lib32、调试
• 合并现有和新的配置文件
• 更新密码和功能数据库
• 立即重新启动sshd
xxxxxxxxxx# cd /tmp# fetch https://github.com/FreeBSDFoundation/pkgbasify/raw/refs/heads/main/pkgbasify.lua# chmod +x pkgbasify.lua# ./pkgbasify.luaxxxxxxxxxx这仍在开发中,因此在将现有系统转换为使用pkgbase时请特别小心。如果还没有自定义pkg存储库配置文件,请为其创建一个文件夹。
xxxxxxxxxx# mkdir -p /usr/local/etc/pkg/repos/要使用pkgbase存储库,请创建一个名为 FreeBSD-base.conf 的pkg存储库配置文件:
xxxxxxxxxxFreeBSD-base { url = "pkg+https://pkg.freebsd.org/${ABI}/base_release_${VERSION_MINOR}"; mirror_type = "srv"; signature_type = "fingerprints"; fingerprints = "/usr/share/keys/pkg"; enabled = yes;}有关特定配置选项的更多信息,请参阅 pkg.conf(5) 。
有不同的分支可供选择(通过相应地更改网址):
| 分支 | 频率 | URL |
|---|---|---|
| main | 每天两次-12:00和00:00 UTC | https://pkg.freebsd.org/${ABI}/base_latest |
| main | 每周-周日12:00 UTC | https://pkg.freebsd.org/${ABI}/base_weekly |
| stable/14 | 每天两次-12:00和00:00 UTC | https://pkg.freebsd.org/${ABI}/base_latest |
| stable/14 | 每周-周日12:00 UTC | https://pkg.freebsd.org/${ABI}/base_weekly |
| releng/14.2 | 每天两次-12:00和00:00 UTC | https://pkg.freebsd.org/${ABI}/base_release_2 |
| releng/14.3 | 每天两次-12:00和00:00 UTC | https://pkg.freebsd.org/${ABI}/base_release_3 |
要升级系统,请根据所需的版本更改配置文件,然后运行:
xxxxxxxxxx# pkg update -r FreeBSD-base# pkg upgrade -r FreeBSD-base检查这些包是否正确,并接受更改。
执行以下命令重新启动操作系统:
xxxxxxxxxx# shutdown -r now运行ZFS时,请考虑在升级到较新版本之前创建引导环境。要使用 bectl(8) 工具创建新的启动环境,请运行:
xxxxxxxxxx# bectl create 14.2-RELEASE-p4如果出现问题,请使用此引导环境像更新前一样启动系统。
保存非基本包列表,以备以后需要:
xxxxxxxxxxpkg prime-origins | sort -u > /var/tmp/pkg-prime-origins.txt将 /usr/local/etc/pkg/repos/FreeBSD-base.conf 更改为 base_latest 等正确的主要版本,如下所示:
xxxxxxxxxxFreeBSD-base { url = "pkg+https://pkg.freebsd.org/${ABI}/base_latest"; mirror_type = "srv"; signature_type = "fingerprints"; fingerprints = "/usr/share/keys/pkg"; enabled = yes;}下一步将把您的系统升级到指定版本。
xxxxxxxxxx此步骤可能会删除非基本包,其中可能包括您正在运行的桌面环境。小心。设置环境变量ABI以升级主版本(用您的架构替换amd64,用目标版本替换15)。
xxxxxxxxxx# env ABI=FreeBSD:15:amd64 pkg-static upgrade -r FreeBSD-base将出现一个提示,询问您是否要忽略版本不匹配,如下所示:
xxxxxxxxxxNewer FreeBSD version for package FreeBSD-zoneinfo:To ignore this error set IGNORE_OSVERSION=yes- package: 1500058- running userland: 1500000Ignore the mismatch and continue? [y/N]:检查并确认。
要检查是否成功,请运行 freebsd-version -kru 。
然后重新启动。
升级到新的主要版本后,可能需要更新和升级已安装的软件包以匹配ABI版本。
xxxxxxxxxx# pkg update# pkg upgrade如果出现故障,请返回并激活之前创建的备份引导环境。
xxxxxxxxxx# bectl activate 14.2-RELEASE-p4重新启动,系统将恢复到升级前的状态。
如果你还没有创建引导环境,你可能想考虑从FreeBSD支持部门获得帮助。
如果你想开始构建自己的pkgbase包,请克隆FreeBSD源代码树:
xxxxxxxxxx# cd /usr/src# git clone https://github.com/freebsd/freebsd-src.git /usr/src查看分支以获取构建包的版本:
xxxxxxxxxx# git checkout releng/14.3根据可用资源的不同,启动构建过程可能需要一些时间。根据CPU核数设置并行进程。
此示例是为8核CPU编写的:
xxxxxxxxxx# make -j8 buildworld && make -j8 buildkernel && make -j8 packages在频繁构建时,考虑使用 devel/ccache 来加速缓存中的后续构建。
构建完成后,这些包将保存到 /usr/obj/usr/src/report/FreeBSD:14:amd64/14.3p2 或类似位置,具体取决于构建的版本。
要将这些包发布到网络,请设置nginx服务并在http服务器配置中使用此位置:
xxxxxxxxxxlocation /FreeBSD:14:amd64 { alias /usr/obj/usr/src/repo/FreeBSD:14:amd64/; autoindex on;}并重新加载nginx服务。
不使用https时,在客户端上使用一个小配置文件来定位刚刚通过编辑 /usr/local/etc/pkg/repos/upgrade.conf 构建的pkgbase版本:
xxxxxxxxxxupgrade: { url = http://ip.of.the.server/FreeBSD:14:amd64/14.3p2 enabled = yes}并按照上面的说明使用它(但使用 -r upgrade 而不是FreeBSD-base)。
当多台机器需要跟踪同一个源树时,让每个系统下载源并重建所有内容会浪费磁盘空间、网络带宽和CPU周期。解决方案是让一台机器完成大部分工作,而其他机器通过NFS挂载。本节概述了一种方法。有关使用NFS的更多信息,请参阅【32.3. 网络文件系统(NFS)】。
首先,确定一组将运行同一组二进制文件的机器,称为构建集。每台机器都可以有一个自定义内核,但将运行相同的用户空间二进制文件。从该集合中,选择一台机器作为构建世界和内核的构建机器。理想情况下,这是一台快速的机器,有足够的空闲CPU来运行 make buildworld 和 make buildkernel 。
选择一台机器作为测试机器,它将在软件更新投入生产之前对其进行测试。这台机器 必须 能够承受长时间停机。它可以是构建机器,但不一定是。
此构建集中的所有计算机都需要通过NFS从构建计算机装载 /usr/obj 和 /usr/src 。对于多个构建集, /usr/src 应该位于一台构建机器上,NFS挂载在其余机器上。
确保构建集中所有机器上的 /etc/make.conf 和 /etc/src.conf 与构建机器一致。这意味着构建机器必须构建构建集中任何机器将要安装的基础系统的所有部分。此外,每个构建机器都应该在 /etc/make.conf 中使用 KERNCONF 设置其内核名称,并且构建机器应该在其 KERNCONF 中列出所有这些名称,首先列出自己的内核。构建机器的 /usr/src/sys/arch/conf 目录中必须包含每台机器的内核配置文件。
在构建机上,按照【26.6. 从源代码更新FreeBSD】中的描述构建内核和世界,但不要在构建机中安装任何东西。相反,在测试机器上安装构建的内核。在测试机器上,通过NFS挂载 /usr/src 和 /usr/obj 。然后,立即运行 shutdown now 进入单用户模式,以安装新的内核和world,并像往常一样运行 etcupdate 。完成后,重新启动以恢复正常的多用户操作。
在验证测试机器上的所有内容都正常工作后,使用相同的程序在构建集中的其他每台机器上安装新软件。
同样的方法也可用于端口树。第一步是通过NFS将 /usr/ports 共享给构建集中的所有计算机。要配置 /etc/make.conf 以共享distfiles,请将 DISTDIR 设置为一个公共共享目录,该目录可由NFS挂载映射到的任何用户根写入。如果要在本地构建端口,每台机器都应该将 WRKDIRPREFIX 设置为本地构建目录。或者,如果构建系统要构建包并将其分发到构建集中的机器,请将构建系统上的 PACKAGES 设置为类似于 DISTDIR 的目录。
从历史上看,构建需要FreeBSD主机。如今,FreeBSD可以在Linux和macOS上构建。
要在非FreeBSD主机上构建,建议使用 tools/build/make.py 脚本。此脚本充当 bmake 的包装器, bmake 是FreeBSD使用的 make 实现。它确保了必要的工具(包括实际的FreeBSD make(1) )被引导,并且构建环境被正确配置。特别是,它设置外部工具链变量,如XCC、XLD等。此外,该脚本可以将任何其他命令参数传递给 bmake ,例如用于并行构建或特定 make 目标的 -j 4 。
xxxxxxxxxx也可以使用最新版本的bmake来代替tools/build/make.py脚本。然而,在这种情况下,需要手动设置所需的环境变量(获取它们列表的最简单方法是运行tools/build/make.py --debug)。否则,构建FreeBSD的先决条件列表相当短。事实上,它归结为安装几个依赖项。
在macOS上,唯一的依赖项是LLVM。可以使用包管理器(例如 Homebrew )安装必要的依赖项:
xxxxxxxxxxbrew install llvm在Linux发行版上,安装Clang 10.0或更高版本以及libarchive和libbz2的头文件(通常打包为libarchive-dev和libbz-2-dev)。
安装依赖项后,主机应该能够构建FreeBSD。
例如,以下 tools/build/make.py 调用构建世界:
xxxxxxxxxxMAKEOBJDIRPREFIX=/tmp/obj tools/build/make.py -j 8 TARGET=arm64 TARGET_ARCH=aarch64 buildworld它在8个CPU上为目标 aarch64:arm64 构建世界,并使用 /tmp/obj 作为对象文件。请注意,在非FreeBSD主机上构建时,变量 MAKEOBJDIRPREFIX 、TARGET 和 TARGET_ARCH 是必需的。此外,请确保创建 MAKEOBJDIRPREFIX 环境变量指向的对象目录。
更多细节请参 arch(7) 和 build(7) 。