23.2. FreeBSD更新

Written by Tom Rhodes.
Based on notes provided by Colin Percival.

随时套用安全性更新以及升级到新发布的操作系统版本对管理一个持续运作的系统是非常重要的任务,FreeBSD内含可以执行这两项任务的工具程序,叫做freebsd-update

这个工具程序支持使用Binary对FreeBSD做安全性与和错误更新,不需要手动编译和安装修补(Patch)或新核心。目前由安全性团队提供支持的Binary更新可用于所有的构架和发行版。支持的发行版清单及各自的支持期限列于https://www.FreeBSD.org/security/

这个工具程序也支持升级操作系统到次要的发布版以及升级到另一个发布版分支。在升级到新的发布版本前,需先查看该版本的发布公告,因为发行公告中包含了该发行版本的相关重要信息。发行公告可自https://www.FreeBSD.org/releases/取得。

注意:

如果有使用crontab来执行freebsd-update(8),则必须在升级操作系统前先关闭。

本节将说明freebsd-update使用的配置文件,示范如何套用安全性修补及如何升级到主要或次要的操作系统发行版,并讨论升级操作系统的需要考察的事项。

23.2.1. 配置文件

freebsd-update预设的配置文件不需变更即可运作。部份使用者可能会想要调校位于/etc/freebsd-update.conf的预设配置文件来对程序有更好的控制。该配置文件中的注释均有说明可用的选项,但以下几个项目可能需要进一步的说明:

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

这个参数控制FreeBSD要保持最新版本的部份。预设是更新整个基础系统(Base system)和核心。可指定个别元件,例如:src/basesrc/sys。虽然如此,最好的选项是维持预设值,因为更改指定特定项目时需列出每一个需要的项目。时间一久可能会因为源码和Binary档案没有更新而造成惨重的后果。

# 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应尝试合并的配置文件目录。档案合并程序是指一系列类似mergemaster(8)做的diff(1)修补动作,但是选项比较少。合并的动作包含接受、开启编辑器,或让freebsd-update中止。如果有疑虑,请先备份/etc,然后再接受合并。更多关于mergemaster的信息,参见mergemaster(8)

# 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清单中的档案。

23.2.2. 套用安全性修补

套用FreeBSD安全性修补的过程已经被简化,让系统管理员可使用freebsd-update来保持系统更新。更多有关FreeBSD安全性报告的信息可以参考第 13.11 节 “FreeBSD 安全公告”

FreeBSD安全性修补可以使用以下指令下载并安装。第一个指令会侦测是否有可用的修补,如果有,将列出若执行修补后会变更的档案清单。第二个指令将会套用修补。

# freebsd-update fetch
# freebsd-update install

如果更新套用了任何核心修补,系统将会需要重启以使用修补过的核心。如果修补套用在任何执行中的Binary,受影响的应用程序应重新启动来使用修补过的Binary版本。

注意:

通常情况下,用户需要准备重启系统。要知道内核更新是否需要重启,请执行freebsd-version -kuname -r命令,如果输出不同,则需要重启。

加入以下项目至/etc/crontab可设定系统每天自动检查更新一次:

@daily                                  root    freebsd-update cron

如果有新的修补,该程序会会自动下载,但不会执行。root使用者会收到电子邮件通知复查该修补并手动执行freebsd-update install安装。

如果有发生任何错误,freebsd-update可以使用以下指令还原最后所做的变更:

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

再次强调,若核心或任何核心模块有做过修改应重新启动系统,以及任何受影响的Binary应重新执行。

只有GENERIC内核可以通过 freebsd-update自动更新。如果安装了自定义内核,则必须在 freebsd-update完成安装更新后重新生成并重新安装该内核。默认内核名称为GENERICuname(1)命令可用于验证其安装。

注意:

随时在/boot/GENERIC保留一份GENERIC核心的复本将有助于诊断各种问题及执行版本升级。请参考第 23.2.3.1 节 “在FreeBSD 9.X及之后版本自定义核心”来了解有关如何取得GENERIC核心的复本说明。

除非在/etc/freebsd-update.conf的预设配置文件被修改,否则freebsd-update将会安装更新后的核心源码和其余的更新,可依平常的方式执行重新编译与重新安装核心。

freebsd-update发行的更新并非总是会更新核心。若核心的源码没有被freebsd-update install修改则不需要重新编译自定义的核心。虽然如此freebsd-update总是会更新/usr/src/sys/conf/newvers.sh,目前修补的版本如uname -r执行结果中的-p数字,便是由该档取得。即使没有做任何其他变更,重新编译自定义核心可让uname准确的回报系统目前的修补版本。当维护多个系统时这会特别有用,因其可让你快速评价每个系统安装的更新。

23.2.3. 执行主要及次要版号升级

从FreeBSD的次要版本升级到另一个版本,例如从FreeBSD 9.0到FreeBSD 9.1,叫作次要版本(Minor version)更新。主要版本(Major version)更新发生在当FreeBSD从一个主要版本升级到主要版本升级到另一个主要版本时,例如从FreeBSD 9.X到FreeBSD 10.X。两种更新都可以透过提供freebsd-update目标的发布版本来执行。

注意:

如果系统正在执行自定义的核心,请在开始升级前,确定有保留一份GENERIC核心的复本在/boot/GENERIC。请参考第 23.2.3.1 节 “在FreeBSD 9.X及之后版本自定义核心”关于如何取得GENERIC核心复本的说明。

在FreeBSD 9.0系统执行以下指令,将会把系统升级至FreeBSD 9.1:

# freebsd-update -r 9.1-RELEASE upgrade

收到这个指令后,freebsd-update会开始评价配置文件和目前的系统来收集升级所需的信息。屏幕会显示侦测到或没侦测到的元件清单。例如:

Looking up update.FreeBSD.org mirrors... 1 mirrors found.
Fetching metadata signature for 9.0-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 9.0-RELEASE.
This kernel will not be updated: you MUST update the kernel manually
before running "/usr/sbin/freebsd-update install"

这时的警告可以安全地忽略,升级过程将会使用更新过的GENERIC核心来进行。

所有的修补都下载到本地系统之后,将会开始套用更新。这个过程可能会花点时间,取决于机器的速度和工作量。配置文件将会被合并。合并的过程中当档案被合并或是手动合并画面上出现编辑器时需要使用者操作。每一个成功合并的结果将会显示给使用者并继续程序,失败或忽略合并将会使程序中断。使用者可能想要备份/etc并稍后手动合并重要的档案,例如:master.passwdgroup

注意:

所有的修补与合并动作会在另一个目录进行,并不会直接修改。当成功套用所有修补,所有配置文件已合并且过程顺利,使用者可使用以下指令将变更安装到磁盘:

# freebsd-update install

核心与核心模块会先修补,若系统正在执行自定义的核心,使用nextboot(8)来设定下次开机使用更新过的/boot/GENERIC

# nextboot -k GENERIC

警告:

若机器在远端进行更新,请在使用GENERIC核心重启前,请确定该核心含有所有系统所需的驱动程序以正常开机并联机至网络。特别是在执行的自定义核心有使用到由核心模块提供内置功能,请确定将这些模块已暂时使用/boot/loader.conf配置文件加载到GENERIC核心。建议关闭非必须的服务和磁盘与网络挂载直到升级程序完成。

机器现在应使用更新过的核心重启:

# shutdown -r now

一旦系统重新上线,使用以下指令继续freebsd-update。由于程序的状态已被储存,freebsd-update不会重头开始,但会进行下一个阶段并移除所有旧的共享程序库和目标档。

# freebsd-update install

注意:

取决于是否有任何程序库版本编号冲突,也可能只有两个而不是三个安装阶段。

升级程序现在完成了。如果所做的是主要的版本升级,则需依第 23.2.3.2 节 “主要版号升级后的套件升级”的说明重新安装所有的Port和套件。

23.2.3.1. 在FreeBSD 9.X及之后版本自定义核心

在使用freebsd-update前,请确定已有GENERIC核心的复本于/boot/GENERIC。若只编译过一次自定义核心,那么/boot/kernel.old就是GENERIC 核心,只需要将该目录重新命名为/boot/kernel

若有编译自定义核心过超过一次,或已经不晓得编译自定义核心的次数,则需取得与目前操作系统版本相符的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存在便可,因此不须重启进入GENERIC

23.2.3.2. 主要版号升级后的套件升级

一般来说,已安装的应用程序在次要版本升级仍可没问题的正常执行。但主要版本升级会采用不同的应用程序Binary界面(Application Binary Interfaces,ABIs),会导致大部份第三方应用程序无法正常执行。因此在主要版本升级后,需要升及所有已安装的套件和Port,套件可以使用pkg upgrade来升级,而Port则需使用ports-mgmt/portmaster工具。

强制升级所有已安装的套件会使用档案库中新版本的套件来取得目前套件,即使该版号没有增加。由于在升级FreeBSD主要版本时会变更ABI版本,因此这是必要动作。强制升级可以执行以下指令来完成:

# pkg-static upgrade -f

重新编译所有已安装的应用程序可以执行以下指令来完成:

# portmaster -af

这个指令会在安装每个应用程序有可设定选项时显示设定画面,并会等待使用者操作该画面,要避免这种情况并使用预设的设定选项,可在上述指令加上-G参数。

完成软件升级后,最后需执行freebsd-update来完成最后的升级动作:

# freebsd-update install

若有使用临时GENERIC核心,便应在此时依据第 8 章 配置 FreeBSD 内核的说明编译并安装新的自定义核心。

重启使用新的FreeBSD版本后,升级程序便正式完成。

23.2.4. 比对系统状态

已安装的FreeBSD版本状态可以使用freebsd-update IDS与另一个已知良好的复本来做比对测试。这个指令会评价目前版本的系统工具,程序库和配置文件,可做为内置的入侵侦测系统来使用(Intrusion Detection System,IDS)。

警告:

此命令不能替代真正的IDS,例如security/snort。由于freebsd update将数据存储在磁盘上,篡改的可能性显而易见。虽然使用kern.securelevel和在不使用时将freebsd update数据存储在只读文件系统上可以减少这种可能性,但更好的解决方案是将系统与安全磁盘进行比较,如DVD或安全存储的外部USB磁盘设备。使用内置实用程序提供IDS功能的另一种方法在第 13.2.6 节 “Binary检验”

要开始比对,需指定输出的档案来储存结果:

# 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选项。

本文档和其它文档可从这里下载: ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

如果对于FreeBSD有问题,请先阅读 文档,如不能解决再联系 <questions@FreeBSD.org>.

关于本文档的问题请发信联系 <doc@FreeBSD.org>.