24.5. 从源代码更新 FreeBSD
通过从源代码编译来更新 FreeBSD 与二进制更新相比有几个优点。可以使用选项构建代码,便于利用特定的硬件。基本系统的某些部分可以使用非默认设置构建,或者在不需要它们的地方完全省略。更新系统的编译构建过程比安装二进制更新需要更长的时间,但允许完全定制便于生成定制版本的 FreeBSD。
24.5.1.快速开始
这是从原始码编译来更新 FreeBSD 的标准步骤快速的参考,稍后的章节会更详细的说明这个程序。
- 编译并更新
# git pull /usr/src #1
check /usr/src/UPDATING #2
# cd /usr/src #3
# make -j4 buildworld #4
# make -j4 kernel #5
# shutdown -r now #6
# etcupdate -p #7
# cd /usr/src #8
# make installworld #9
# etcupdate -B #10
# shutdown -r now #11
- 获取最新版本的源代码。关于获取和更新源代码的更多信息,请参见更新源代码。
- 检查 /usr/src/UPDATING,了解从源码构建之前或之后需要的任何手动步骤。
- 转到源码目录。
- 编译基本系统(World),除了内核(Kernel)以外的一切。
- 编译并安装内核。这等同于
make buildkernel installkernel
。- 重新启动系统到新的内核。
- 更新并合并安装基本系统之前需要的 /etc/ 配置文件。
- 转到源代码目录。
- 安装基本系统。
- 更新并合并 /etc/ 中的配置文件。
- 重新启动系统,使用新建立的基本系统和内核。
24.5.2.准备源代码更新
阅读 /usr/src/UPDATING ,从原代码编译之前与之后任何需要手动操作步骤会在此文件中说明。
24.5.3.更新源代码
FreeBSD 的源代码位于 /usr/src/ 。更新这个源代码的首选方法是通过 Git 版本控制系统。验证源代码是否在版本控制之下:
# cd /usr/src
# git remote --v
origin https://git.freebsd.org/src.git (fetch)
origin https://git.freebsd.org/src.git (push)
这表明 /usr/src/ 处于 Git 版本控制之下,可以用 git(1) 更新:
# git pull /usr/src
若该目录最近没有更新过,可能会需要一些时间来完成更新动作。在更新完成之后,原代码便为最新版本,并可开始依下一节的说明来编译程序。
注意:
获取源代码
如果输出显示
fatal: not a git repository
,说明那里的文件缺失或用不同的方法安装。需要重新签出 (checkout) 该源。表1. FreeBSD 版本和存储库分支
uname -r
的输出结果存储库路径 描述 X.Y-RELEASE releng/X.Y 发布版本加上关键的安全性与错误修正,较建议大多数使用者使用这个分支。 X.Y-STABLE stable/X 发布版本加上所有在该分支上开发中的程序,STABLE 指的是应用程序二进制接口 (ABI) 没有改变,因此为早期版本编译的软件仍然可以运行。例如,在FreeBSD 10.1 上编译的软件仍然可以在后来编译的 FreeBSD 10-STABLE 上运行。STABLE 分支偶尔会有可能影响用户的错误或不兼容,但是这些问题通常会很快被修复。 X-CURRENT main 最新的未发布的 FreeBSD 开发版本。CURRENT 分支可能会有重大的错误或不兼容,因此只推荐给高阶用户。 查看 FreeBSD 目前使用的版本可使用 uname(1):
# uname -r
10.3-RELEASE
根据 FreeBSD 版本和版本库分支,用于更新 10.3-RELEASE 的源代码的版本库路径是
releng/10.3
。这个路径在签出源代码时被使用:
# mv /usr/src /usr/src.bak #1
# git clone --branch releng/10.3 https://git.FreeBSD.org/src.git /usr/src #2
- 移除旧的目录。如果这个目录中没有本地的修改,就可以删除它。
- FreeBSD 版本和存储库分支的路径会被添加到版本库的 URL 中。第三个参数是本地系统上源代码的目标目录。
24.5.4.从源码编译
编译世界(world),或者说编译除了内核(Kernel)以外的所有操作系统。这样做首先是为了提供最新的工具来构建内核。接着便可编译内核:
# cd /usr/src
# make buildworld
# make buildkernel
编译后的代码被写到 /usr/obj 。
以上这些均为基本的步骤,用来控制编译的其他选项在以下章节会说明。
24.5.4.1.执行清除编译
某些版本的 FreeBSD 编译系统会将先前编译的代码留在临时对象目录 /usr/obj 中。这可以通过避免重新编译没有变化的代码来加快之后的编译速度。若要强制重新编译所有东西可在开始编译前使用 cleanworld
:
# make cleanworld
.24.5.4.2.设置工作核心数量
在多核处理器上增加编译工作核心的数量可增加编译速度,可使用 sysctl hw.ncpu
来查看有多少核心,不同处理器使用不同版本的 FreeBSD 编译系统,所以唯一能了解不同工作数量对编译速度影响的方式便是测试。在一开始可考虑选择一个介于 1/2 到 2 倍核心数之间的数值,工作的数量可使用 -j
来指定。
例 1. 增加编译工作核心数
使用四个工作核心来编译世界(world)与核心:
# make -j4 buildworld buildkernel
24.5.4.3.只编译内核
如果源代码有变化,必须完成 buildworld
。之后,可以在任何时候运行 buildkernel
来编译内核。要想只编译内核:
# cd /usr/src
# make buildkernel
24.5.4.4.编译自定义内核
标准的 FreeBSD 内核是以一个名为 GENERIC 的内核配置文件 (Kernel config file) 为基础,GENERIC 内核中内含了所有最常用的设备驱动程序与选项,有时这个文件对编译自定义内核也非常有用,可根据其来加入或移除设备驱动程序或选项来满足特定需求。
例如,要开发一个 RAM 受到严重限制的小型嵌入式电脑,便可移除不需要的设备驱动程序或选项来缩小内核。
内核配置文件位于 /usr/src/sys/arch/conf/,其中 arch 是 uname -m 的输出。大多数计算机是 amd64 的,因此配置文件的目录是 /usr/src/sys/amd64/conf/ 。
技巧:
/usr/src 可以被删除或重新创建,所以最好把自定义的内核配置文件放在一个单独的目录下,比如 /root 。将内核配置文件链接到
conf
目录中。如果该目录被删除或覆盖,内核配置文件可以被重新链接到新目录中。
通过复制 GENERIC 配置文件可以创建一个自定义的配置文件。在这个例子中,新的自定义内核是用于存储服务器的,所以被命名为 STORAGESERVER 。
# cp /usr/src/sys/amd64/conf/GENERIC /root/STORAGESERVER
# cd /usr/src/sys/amd64/conf
# ln -s /root/STORAGESERVER .
接着编译 /root/STORAGESERVER,要加入或移除装置或选项,参考 config(5) 。
通过在命令行上将 KERNCONF 设置为内核配置文件来建立自定义内核:
# make buildkernel KERNCONF=STORAGESERVER
24.5.5.安装编译好的程序
在完成 buildworld
与 buildkernel
两个步骤之后,便可安装新的核心与世界:
# cd /usr/src
# make installkernel
# shutdown -r now
# cd /usr/src
# make installworld
# shutdown -r now
若使用自定义内核,则同样须设置 KERNCONF 来使用新的自定义内核:
# cd /usr/src
# make installkernel KERNCONF=STORAGESERVER
# shutdown -r now
# cd /usr/src
# make installworld
# shutdown -r now
24.5.6.完成更新
最后几项任务完成了更新。任何修改过的配置文件都将与新版本合并,过时的库被定位并删除,然后系统被重新启动。
24.5.6.1.使用 etcupdate(8) 合并配置文件
etcupdate(8) 是一个管理更新文件的工具,有些文件没有作为安装世界的一部分被更新,比如位于 /etc/ 的文件。它通过对这些文件的修改与本地版本进行三方合并来管理更新。与 mergemaster(8) 的交互式提示相比,它还被设计为尽量减少用户的干预。
注意:
一般来说,etcupdate(8) 在运行时不需要任何特殊的参数。然而,有一个很方便的中间命令,用于检查第一次使用 etcupdate(8) 时会做什么。
# etcupdate diff
该命令允许用户检查配置的变化。
如果 etetcupdate(8) 不能自动合并文件,可以通过发布手动交互来解决合并冲突。
# etcupdate resolve
警告:
当从
mergemaster(8)
切换到etcupdate(8)
时,第一次运行可能会不正确地合并变化,产生虚假的冲突。为了防止这种情况,在更新源代码和构建新的世界之前,请执行以下步骤:
# etcupdate extract #1
# etcupdate diff #2
- 引导 /etc 文件的数据库,有关更多信息,请参阅 etcupdate(8) 。
- 引导后检查差异。修剪不再需要的任何本地更改,以减少未来更新中发生冲突的可能性。
24.5.6.2.使用 mergemaster(8) 合并配置文件
mergemaster(8) 提供了一种将对系统配置文件的修改与这些文件的新版本进行合并的方法。mergemaster(8) 是首选的 etcupdate(8) 的替代方案。使用 -Ui
,mergemaster(8) 自动更新未被用户修改的文件,并安装尚未存在的新文件。
# mergemaster -Ui
如果必须手动合并文件,则交互式显示允许用户选择保留文件的哪些部分。有关详细信息,请参阅 mergemaster(8) 。
24.5.6.3.检查过时的文件和库
部份废弃的文件或目录可能在更新之后保留,可使用以下指令找出这些文件:
# make check-old
然后删除:
# make delete-old
一些过时的库也可能保留下来。这些可以用以下方法检测:
# make check-old-libs
用下面的命令删除:
# make delete-old-libs
当库被删除时,仍在使用这些旧库的程序将停止工作。删除旧库后必须重建或替换这些程序。
技巧:
当已知所有旧文件或目录都可以安全删除时,可以通过在命令中设置
BATCH_DELETE_OLD_FILES
来避免按y
和Enter
删除每个文件。例如:
# make BATCH_DELETE_OLD_FILES=yes delete-old-libs
24.5.6.4.更新后重启
更新后的最后一步是重新启动计算机,使所有更改生效:
# shutdown -r now