Home -- Michael's Blog :: Just Do IT -- Manuals

19.4. 重新编译 ``world''

只要你根据一定版本的FreeBSD (FreeBSD-STABLE, FreeBSD-CURRENT, 等等),已经同步了你本地的源码树,那么你就可以使用这些源码树来重建系统。

做好备份无需强调在行动 之前 备份整个系统是多么的重要。 尽管重新编译系统是 (如果您按照文档的指示做的话) 一件很容易完成的工作, 但出错也是在所难免的, 另外, 别人在源码里面引入的错误也可能造成系统无法引导。

请确信自己已经做过备份, 并且在手边有恢复软盘或可以引导的光盘。 您可能永远也不会用到它, 但安全第一嘛!

订阅恰当的邮件列表FreeBSD-STABLE 和 FreeBSD-CURRENT 分支自然是发展中的。为FreeBSD做贡献的都是人,偶尔也会犯错误。

有时这些错误没什么危害,只是引起你的系统生成新的诊断警告。有时是灾难性的,并导致你的系统不能惊动启动或破坏你的文件系统(甚至更糟)。

如果出现了类似的问题,贴一封``小心(heads up)''帖到相关的邮件列表里,讲清问题的本质以及受影响的系统。在问题解决后,再贴封``解除(all clear)'' 声明。

如可你想跟踪FreeBSD-STABLE 或 FreeBSD-CURRENT而又不阅读FreeBSD-STABLE 邮件列表FreeBSD-CURRENT 邮件列表各自的邮件列表,那么你是自找麻烦。

不要使用 make world许多较早的文档推荐使用 make world 来完成这项工作。 这样做会跳过一些必要的步骤, 因此只有在你知道自己在做什么的时候才可以这样做。 几乎所有的情况下 make world 都是不应该做的事情, 您应该使用这里描述的方法。

19.4.1. 更新系统的规范途径

要更新系统,就要使用下面的过程:

# make buildworld
# make buildkernel
# make installkernel
# reboot

你应该启动到单用户模式下(例如从启动提示符处使用boot -s)。然后执行:

# mergemaster -p
# make installworld
# mergemaster
# reboot

阅读进一步的说明上边描述的序列只是有助于你开始工作的简要。要清楚的理解每一不步,尤其是你想使用定制内核配置,你就应阅读下面的部分。

19.4.2. 阅读 /usr/src/UPDATING

在你做其它事之前,请阅读/usr/src/UPDATING (或在你的源码里的等效的文件)。这个文件要包含有关于你可能遇到的问题的重要信息,或指定了你可能使用到的命令的执行顺序。如果UPDATING 与你这里读到相矛盾,那就先依据UPDATING

重要: 正如先前所述,阅读UPDATING并不能替代订阅正确的邮件列表。两都是互补的,并不彼此排斥。

19.4.3. 检查 /etc/make.conf

检查 /usr/share/examples/etc/make.conf (在 FreeBSD   4.X 中叫做 /etc/defaults/make.conf) 以及 /etc/make.conf。 第一个文件包含了一些默认的定义 - 它们中的绝大多数都注释掉了。 为了在重新编译系统时能够使用它们, 请把这些选项加入到 /etc/make.conf。 请注意在 /etc/make.conf 中的任何设置同时也会影响每次运行 make 的结果, 因此设置一些适合自己系统的选项是一个好习惯。

一般的用户通常会从 /usr/share/examples/etc/make.conf (或者 FreeBSD 4.X 中的 /etc/defaults/make.conf) 复制 CFLAGSNOPROFILE 这样的设置到 /etc/make.conf 中并令它们生效。

请考虑其他的一些选项 (例如 COPTFLAGS, NOPORTDOCS 等等), 看看是否合用。

19.4.4. 更新/etc里边的文件

/etc目录包含有除了你的系统启动时执行的脚本外大部分的系统配置信息。有些脚本随FreeBSD的版本而不同。

有些配置文件在天天运行的系统里也是要使用到的。尤其是/etc/group

偶尔, 某些``make installworld''的安装需要特定的用户名或用户组存在。在升级时,有可能这些用户或组就不存在。这会在升级过程造成出错。有时,``make installworld''会首先检查这些用户或组是否存在。

最近就有个这样的例子,当时smmsp用户是被增加了的。当mtree(8)试着建立/var/spool/clientmqueue时,安装过程失败了。

解决办法是检查/usr/src/etc/group并把它的组列表与你的进行比较。如果在新文件里有而你的文件里没有的,就把它们复制过来。同样地,你把/etc/group里的任何这样的组进行更名---与/usr/src/etc/group中有相同GID,但不同名的那些。

自4.6-RELEASE开始,你可以通过-p选项以预建(pre-buildworld)模式运行mergemaster(8) 。这样只是比较那些对于成功执行buildworldinstallworld起关键作用的文件。在第一次时,如果早期的mergemaster版本不支持-p的话,就使用源码树中的新版本:

# cd /usr/src/usr.sbin/mergemaster
# ./mergemaster.sh -p

提示: 如果你是个偏执狂(paranoid),你可以检查你的系统看看哪个文件属于你已更名或删除了的那个组。

# find / -group GID -print

将显示所有GID组(可以是组名也可以是数字地组ID)所有的文件。

19.4.5. 改为单用户模式

你可能相在单用户模式下编译系统。除了对更快处理事情显然有好处外,重装系统将接触许多重要的系统文件,包括所有标准系统二进制文件、库文件、包含(include)文件等等。在运行的系统里(尤其是同时系统里有激活的用户)更改这些文件是自寻烦恼。

另一种模式是在多用户模式下编译系统,然后转换到单用户模式下安装。如果你喜欢这种方式,只需在建立(build)完成后才执行下边的步骤。你推迟转换到单用户模式下直到你必须installkernelinstallworld

从运行的系统里,以超级用户方式执行:

# shutdown now

这样就会转换到单用户模式。

另外也可以,重启系统,在启动提示符处,输入-s标识。系统就会启动单用户。再在shell提示符处执行:

# fsck -p
# mount -u /
# mount -a -t ufs
# swapon -a

这会检查文件系统,重新装载/为读/写,参考/etc/fstab装载其它所有的UFS文件系统,然后打开交换(swapping)开关。

注: 如果你的CMOS时钟是设置为本地时间,而不是GMT(如果date(1)命令输出不能显示正确的时间和地区也有确有其事),你可能也需要执行下边的命令:

# adjkerntz -i

这样可以确定你正确的本地时区设置--不这样做,你以后可能会碰到一些问题。

19.4.6. 删除/usr/obj

在重建部分系统时,它们被(默认地)放到了/usr/obj目录下边。这些目录影射到了/usr/src下边。

删除这个目录,你可以加快``make buildworld''的过程,并且省下与依赖关系有关的许多头痛的事情。

/usr/obj下的有些文件可能设置了不可改(immutable)属性(查看chflags(1) 了解更多),你必须先把这些标志去掉。

# cd /usr/obj
# chflags -R noschg *
# rm -rf *

19.4.7. 重编译源码

19.4.7.1. 保存输出

建议把执行make(1)后得到的输出存成一个文件。如果什么地方出了错,你就会有个错误信息的备份。尽管这样不能帮你分析哪里出了错,但如果你把你的问题贴到某个邮件列表里就能帮助其他的人。

这样做最简单的办法是使用script(1)命令,同是带上参数指定存放输出的文件名。你应在重建系统之前立即这样做,然后在过程完成时输入exit

# script /var/tmp/mw.out
Script started, output file is /var/tmp/mw.out
# make TARGET
... compile, compile, compile ...
# exit
Script done, ...

如果你这样做,就不要把文件存到/tmp里边。下次启动时,这个目录就会被清除掉。存放的最好地方是/var/tmp (如上个实例)或root的主目录。

19.4.7.2. 编译基本系统

你必须在/usr/src目录里边:

# cd /usr/src

(当然,除非你的源码是在其它地方,真是这样的话更换成那个目录就行了)。

使用make(1) 命令重建系统。这个命令会从Makefile(描述组成FreeBSD的程序应该怎样被重建,以什么样的顺序建立等等)里读取指令。

输入的一般命令格式如下:

# make -x -DVARIABLE target

这个例子里,-x是会传递给make(1)的一个选项。查看make(1)手册有你可用的选项例子。

-DVARIABLE传递一个变量给Makefile。这些变量控制了Makefile的行为。这些同/etc/make.conf设置的变量一样,只是提供了另一种设置它们的方法。

# make -DNOPROFILE target

是另一种指定不被建立(built)的先定库(profiled libraries)的方式,协同/etc/make.conf里的

NOPROFILE=    true     #    避免编译先定库

一起使用。

目标(target)告诉make(1) 什么该做。每个Makefile定义了一定数量不同的``目标(targets)'',然后你选择的目标就决定了什么会发生。

有些目标列在Makefile里的,但并不意味着你要执行。相反,建立过程(build process)利用它们把重建系统的一些必要的步骤分割成几个子步骤。

大部分的时间不需要向make(1)传递参数,因此你的命令看起来可能象这样:

# make target

从FreeBSD 的2.2.5版本开始(实际上,是先在FreeBSD-CURRENT 分支里第一次创建,然后在FreeBSD-STABLE的2.2.2 和 2.2.5两个版本间,进行了大翻新),world target已经分成了两个部分:buildworldinstallworld。 从 FreeBSD 的 5.3 版开始, world target 在默认时已经改为完全不动作, 因为它事实上对于许多用户都具有相当的危险性。

正如名字所暗示的,buildworld/usr/obj下边建立了一个全新的树,然后installworld 就在当前的机器里安装这个树。

因为两个原因,这点很有用。首先,它允许你安全地完成建立(build),而没有你运行的系统组成部分的影响。建立(build)是``自主的(self hosted)''。因为这样,你可以安全地在以多用户模式运行的机器里执行buildworld ,而不用当心不良影响。但是依然推荐你在单用户模式时运行installworld

第二,允许你使用NFS装载(NFS mounts)升级你网络里的多台计算机。如果你有三台A, BC想进行升级,在A执行make buildworldmake installworld。然后从ANFS装载(NFS mount)BC/usr/src/usr/obj,接着你就执行make installworldBC上安装建立(build)的结果。

尽管world target仍然存在,强烈建议你不要用它。

运行

# make buildworld

现在可能给make指定-j选项了,这样会使用产生出几个并发的进程来。这在多处理器(multi-CPU)机器里最有用。但是,由于大部分的编译过程是IO限制远胜CPU限制,它在单处理器(single-CPU)的机器里也是有用的。

在一般的单CPU机器里,你要运行:

# make -j4 buildworld

make(1) 然后会有至多4个进程在同一时刻执行。贴到邮件列表里的实验证据显示这样会收到最好的效果。

如果你有一台多CPU机器,那你就使用SMP配置内核,试试6到10之间的值,看这些值提速如何。

注意,这仍处在实验性阶段,如果提交到源码树上的话,可能会断送其前程(break this feature)。如果用这个参数编译的话,你报告错误前试试不用它。

19.4.7.3. 耗时

有许多因素影响build时间,但通常一台带有128 MB内存500 MHz的 Pentium® III要花费大约2 小时来build FreeBSD-STABLE 树,并且在整个过程中不带什么技巧或捷径。FreeBSD-CURRENT 树花的时间还要更长一点。

19.4.8. 编译和安装新内核

要充分利用你的新系统,你应该重新编译内核。这是很有必要的,因为特定的内存结构已经发生了改变,像ps(1)top(1) 这样的程序会不能工作,除非内核同源码树的版本是一样的。

最简单、最安全的方式是build 并安装一个基于GENERIC的内核。虽然GENERIC可能没有适合你的系统的所有必要的设备,但它包括了启动你的系统到单用户模式所必需的内容。这是个不错的检测新系统是否工作正常的测试。在从GENERIC启动、核实系统可以工作后,你就可以建立(build)一个基于你的正常内核配置文件的新的内核了。

在新的 FreeBSD 版本中, 首先完成 build world 然后再编译新内核非常重要。

注: 如果你想建立一个定制内核,而且已经有了配置文件,只需象这样使用KERNCONF=MYKERNEL

# cd /usr/src
# make buildkernel KERNCONF=MYKERNEL
# make installkernel KERNCONF=MYKERNEL

在FreeBSD 4.2或更早的版本里,你必须使用KERNEL=替换KERNCONF=。在2001年2月2号以前发行的4.2-STABLE并不识别KERNCONF=

注意,如果你已把内核安全级别(kern.securelevel)调高到了1以上,而且还设置了noschg或相似的标识到了你的内核二进制里边,你可能会发现转换到单用户模式里使用installkernel是很有必要的。另外你应该也能毫无问题地从多用户模式执行这两个命令。查看init(8)了解更多关于内核安全级(kern.securelevel)的信息;查看chflags(1) 了解更多关于不同文件标识的信息。

如果你升级到FreeBSD 4.0以前版本,你应旧的内核build程序。但还是推荐你使用新版的config(8),可以使用下边的命令行:

# /usr/obj/usr/src/usr.sbin/config/config KERNELNAME

19.4.9. 重启到单用户模式

你应该单用户模式测试新内核。照第 19.4.5 节处的说明去做。

19.4.10. 安装新的系统二进制(System Binaries)

如果你正建立一个足以使用make buildworld的FreeBSD版本,那么你现在应该使用installworld来安装新的系统二进制。

执行

# cd /usr/src
# make installworld

注: 如果在make buildworld的命令行指定了变量,你就必须在make installworld如命令行里指定同样的变量。对于其它的选项也不是必需的,如,-j就不能同installworld一起使用。

举例,你执行了:

# make -DNOPROFILE buildworld

你就必须使用:

# make -DNOPROFILE installworld

来安装结果,否则就要试着安装先定(profiled)的在make buildworld阶段没有建立(built)的二进制文件。

19.4.11. 不是由make installworld更新的更新文件

重新编译整个系统不会使用新的或改过的配置文件更新某些目录(尤其像/etc, /var/usr

更新这些文件最简单的方式就是使用mergemaster(8),手工去做也是可以的,只要你愿意。不管你选择哪一种,一定记得备份/etc以防出错。

19.4.11.1. mergemaster(合并主管)

贡献者: Tom Rhodes.

mergemaster(8) 工具是个有针对性的脚本(Bourne script),用于检测/etc/usr/src/etc源码树里边的配置文件的不同点。这是保持系统配置文件同源码树里的一起更新的推荐方式。

mergemaster 被集成到了3.3-RELEASE和3.4-RELEASE之间的FreeBSD基本系统里,这意味着自3.3版本起所有的-STABLE 和 -CURRENT系统都有。

在提示符里简单地输入mergemaster就可以开始,并观看它的开始过程。mergemaster会建立一个临时的根(root)环境,在/下,放置各种系统配置文件。这些文件然后同当前安装到你系统里的进行比较。此时,不同的文件会以diff(1)格式进行显示,使用+符号标识增加或修改的行,-标识将完全删除的行或将被替换成新行。查看diff(1) 手册可以得到更多关于diff(1)语法和文件不同点怎样显示的信息。

mergemaster(8) 会给你显示每个文件的不同处,这样你就可以选择是删除新文件(相对临时文件),是以未改状态安装临时文件,是以当前安装的文件合并临时文件,还是再看一次diff(1)结果。

“选择删除临时文件”将使mergemaster(8)知道我们希望保留我们当前的文件不改,并删除新的。并不推荐这个选择,除非你没有更改当前文件的理由。任何时候在mergemaster(8)提示符里输入?,你就会得到帮助。如果选择跳过文件,在其它文件处理完后再次进行。

“选择安装未修改临时文件”将会使新文件替换当前的。对大部分未改的文件,这是个最好的选择。

“选择合并文件”将为你打开一个文本编辑器,里边是两个文件的内容。你现在就可以一边合并它们,一边在屏幕里查看,同时从两者中选取部分生成最终文件。当两个文件一起比较时,l键会选择左边的内容,r会选择右边的。最终的输出是由两个部分组成的一个文件,用它就可以安装了。这个选项通常用于用户修改了设置的文件。

“选择再次查看diff(1)结果”将会在提供给选择之前,显示文件的不同处,就象mergemaster(8)所做的一样。

mergemaster(8)完成了对系统文件的处理后,你会得到其它的选项。mergemaster(8)可能会问你是否要重建密码文件,如果你的FreeBSD版本超过5.0,还会问你是否想要执行MAKEDEV(8),最后带上一个选项删除剩下的临时文件。

19.4.11.2. 手册更新

如果想要手工更新,但不要只是从/usr/src/etc把文件复制/etc就了事。有些文件是必须先``安装''的。这是因为/usr/src/etc目录并 不是想像的那样是/etc目录的一个复制。事实上,有些是文件是/etc有的,而/usr/src/etc里边没有。

如果你使用mergemaster(8) (作为推荐),你可以向前跳到下一节

手工做最简单的方式是安装这些文件到一个新的目录,完成后再来查找不同处。

备份你已有的/etc虽然,理论上,没有什么会自动访问这个目录,事情还是做稳操胜当一点。复制已有/etc不到一个安全的地方,如:

# cp -Rp /etc /etc.old

-R 完成递归复制(设者注:即可以复制目录以下的所有内容),-p保留文件的时间、所属等等。

你需要建立的个虚目录(a dummy set of directories )来安装新的/etc和其它文件。/var/tmp/root是个不错的选择,除此之外,还有一些子目录是需要的。

# mkdir /var/tmp/root
# cd /usr/src/etc
# make DESTDIR=/var/tmp/root distrib-dirs distribution

这样就建好了需要的目录结构,然后安装文件。在/var/tmp/root下建立的大部分子目录是空的,而且要删除掉。最简单的方式是:

# cd /var/tmp/root
# find -d . -type d | xargs rmdir 2>/dev/null

这样会删除所有的空目录。(标准的错误信息被重定向到了/dev/null,以防止关于非空目录的警告。

/var/tmp/root现在包含了应放在/下某个位置的所有文件。你现在必须仔细检查每一个文件,检测它们与你已有的文件有多大不同。

注意,有些已经安装在/var/tmp/root下的文件有个``.''在开头。在写的时候,像这样唯一的文件是/var/tmp/root//var/tmp/root/root/里shell启动文件,尽管可能有其它的(依赖于你什么时候读取这个)。 确信使用ls -a可以看到它们。

最简单的方式是使用diff(1) 去比较两个文件:

# diff /etc/shells /var/tmp/root/etc/shells

这会显示出/etc/shells 文件和新的/var/tmp/root/etc/shells文件的不同处。用这些来决定是合并你已做的变化还是复制你的旧文件过来。

使用日戳(Time Stamp)命名新的Root(根)目录(/var/tmp/root),这样你可以轻松地比较两个版本的不同: 频繁重建系统意味着必须频繁更新/etc,而这可能会有点烦琐。

在合并到/etc的文件里,最新更改的你可以做个复制,由此加快这个(指更新)过程。下边就给出了一个怎样做的主意。

  1. 像平常一样建立系统(Make the world)。当你想更新/etc 和其它目录里,给目标目录一个含有当前日期的名字。假如你是1998年2月14日做的,你可以执行下边的:

    # mkdir /var/tmp/root-19980214
    # cd /usr/src/etc
    # make DESTDIR=/var/tmp/root-19980214 \
        distrib-dirs distribution
    
  2. 如上边列出的,从这个目录合并变化。

    在你完成后,不要删除/var/tmp/root-19980214目录。

  3. 在你下载了最新版的源码并改过后,执行第一步。这样将得到一个新的目录,可能叫做/var/tmp/root-19980221(如果等了一周做的升级)。

  4. 你现在能看到两个目录间的不同了---在隔周的时间里使用diff(1)建立递归diff产生的不同。:

    # cd /var/tmp
    # diff -r root-19980214 root-19980221
    

    一般情况下,这两种间的不同处比/var/tmp/root-19980221/etc/etc之间的不同要小很多。因为不同点更小,也就更容易把这些变化移到你的/etc目录里边。

  5. 你现在可以删除早先的两个/var/tmp/root-*目录:

    # rm -rf /var/tmp/root-19980214
    
  6. 每次你需要合并这些变化到/etc里,就重复这个流程。

你可以使用date(1)自动产生目录的名称:

# mkdir /var/tmp/root-`date "+%Y%m%d"`

19.4.12. 更新/dev

注: 如果你正在运行FreeBSD 5.0 或更后的版本,你可以安全地跳过这部分。这些版本使用了devfs(5) 来透明地分配设备结点。

许多情况下,在有必要更新设备结点时,mergemaster(8) 工具就可以实现,并且可以自动地完成。这里的说明用于怎样手工更新设备结点。

考虑到安全,这里用的是多步流程。

  1. 复制/var/tmp/root/dev/MAKEDEV/dev

    # cp /var/tmp/root/dev/MAKEDEV /dev
    

    如果你使用mergemaster(8)去更新/etc,那么你的MAKEDEV脚本应该已经被更新过,虽然它不会影响检查(使用diff(1)),必要时手工复制一下。

  2. 现在,给当前的/dev做个快照。照的时候一定要注意每个文件名的许可(permissions)、所属(ownerships)、主从数字(major and minor numbers),不必包括日戳(time stamps)。最简单的方式是使用awk(1)提取信息:

    # cd /dev
    # ls -l | awk '{print $1, $2, $3, $4, $5, $6, $NF}' > /var/tmp/dev.out
    
  3. 重做设备结点:

    # sh MAKEDEV all
    
  4. 这时,把这个目录的另一个快照输出到/var/tmp/dev2.out。现在检查这两个文件,查找 任何你没建立的设备结点。就该不会很多,但是保险一点总是好的。

    # diff /var/tmp/dev.out /var/tmp/dev2.out
    

    你可能注意到磁盘分区(disk slice)的差别,它会使像:

    # sh MAKEDEV sd0s1
    

    那样的命令重新建立分区入口(slice entries)。 你的具体情况可能不同。

19.4.13. 更新/stand

注: 这一步只是为了收尾,可以安全省略。如果你在使用FreeBSD 5.2或更新的版本,/rescue目录会为用户进行自动更新,使用的是在make installworld期间静态编译地最新的二进制文件,因此也就不用废话更新/stand的必要性了。

为了完成,你可能想额外地更新/stand里的文件。这些文件由链接到/stand/sysinstall的二进制文件硬链接组成。这个文件要静态链接,以便没有其它文件系统时(尤其是/usr)被装载时也能工作。

# cd /usr/src/release/sysinstall
# make all install

19.4.14. 重启

现在完成了。在你检查所有内容都放置正确后,你可以重启系统了。 只是简单的shutdown(8)可以这样做:

# shutdown -r now

19.4.15. 结束

恭喜!你现在成功升级了你的FreeBSD系统。

如果还有轻微的错误,可以轻易地重建系统的选定部分。例如,在部分升级或合并/etc时,你不小心删除了/etc/magicfile(1)命令就会停止工作。这种情况下,执行下边进行修复:

# cd /usr/src/usr.bin/file
# make all install

19.4.16. 问题

19.4.16.1. 每个变化你都须要重建系统吗?
19.4.16.2. 我的编译失败,并伴随有许多11(或其它的数字信息)号错误。是怎么回事呀?
19.4.16.3. 我完成后可以删除/usr/obj吗?
19.4.16.4. 中断的build可以被恢复吗?
19.4.16.5. 我怎样加快建立系统的速度?
19.4.16.6. 如果出现了错误我该怎么办?

19.4.16.1. 每个变化你都须要重建系统吗?

这个不好说,因为要看变化的情况。如,如果你刚运行了CVSup,并得到下边更新的文件:

src/games/cribbage/instr.c
src/games/sail/pl_main.c
src/release/sysinstall/config.c
src/release/sysinstall/media.c
src/share/mk/bsd.port.mk

这就不必重建整个系统。你只需到相关的子目录里执行make all install,仅此而已。但是,如果有重大变化,如src/lib/libc/stdlib,那么你就要重建系统或至少静态链接的那些部分(除了你增加的部分都是静态链接的)。

在这天后,就是你的事了。要是说每两个星期重建一下系统的话,你可能会高兴。或者你可能只想重做改变过的部分,确信你能找出所有依赖关系。

当然,所有这些依赖于你想升级的频率,和你是否想跟踪FreeBSD-STABLE 或 FreeBSD-CURRENT。

19.4.16.2. 我的编译失败,并伴随有许多11(或其它的数字信息)号错误。是怎么回事呀?

这个通常表示硬件错误。(重)建系统是个强压测试系统硬件的有效地方式,并且常常产生内存错误。这些正好表示它们自已做为编译器离奇地死于收到的奇怪信息。

一个确信的指示器是如果重新开始make,并且整个过程中会死在不同的点上。

对于这种情况,你没有什么可做的,除了更换机器里的部件,看是哪一个坏了。

19.4.16.3. 我完成后可以删除/usr/obj吗?

简短地说,可以。

/usr/obj 包含了所有在编译阶段生成的目标文件。通常,在``make buildworld''过程中第一步之一就是删除这个目录重新开始。这种情况下,在你完成后,保留/usr/obj没有多大意义,还可释放一大堆磁盘空间(通常在340 MB左右)。

只是,如果你清楚你在干什么,你可以让``make buildworld''跳过这一步。这会让后继的build执行得更快,因为大部分的源码都不必再进行编译了。这个的另一面就在于敏感的依赖问题可以潜在,并以奇怪的方式引起build的失败。这在FreeBSD邮件列表里经常引起沸腾,当有人抱怨他们build失败时,并没意识到这是因为自已是想抄近路(意思是说少了些必要的步骤)。

19.4.16.4. 中断的build可以被恢复吗?

依赖于你在你找到问题之前整个过程进行了多远。

大体上 (这个并不是硬性规定),``make buildworld''过程会建立新版的基本工具(如gcc(1)make(1))以及系统二进制文件。这些工具和二进制文件然后被安装。新的工具和库然后用来重建它们自已,并再次被安装。整个系统(现在包括了常规的用户程序,如ls(1)grep(1))然后使用新的系统文件被重建。

如果你处在最后阶段,你就知道了(因为你已经看过你存储的输出),然后你可以做(相当安全):

... 问题修复 ...
# cd /usr/src
# make -DNOCLEAN all

这将不能取消 ``make buildworld''先前所做的工作。

在``make buildworld''的输出中如果看到如下信息:

--------------------------------------------------------------
Building everything..
--------------------------------------------------------------

那么这样做就是相当安全的。

如果你没有看到那个信息,或者你不能确定,那么安全第一,从头开始。

19.4.16.5. 我怎样加快建立系统的速度?

  • 以单用户模式运行

  • /usr/src/usr/obj目录放到不同磁盘里的独立文件系统里。如果可能,这些磁盘在不同的磁盘控制器里。

  • 更好的,是把这些文件系统放置到多个使用ccd(4)(连接磁盘驱动器--concatenated disk driver)设备的磁盘里。

  • 关掉profiling (在/etc/make.conf里设置 ``NOPROFILE=true'')。你差不多用不了它。

  • /etc/make.conf里也为CFLAGS设置上-O -pipe。最佳优化-O2会更慢,而且-O-O2之间的优化差别基本上可以忽略。 -pipe让编译器使用管道而不用临时文件进行通信,这样可以减少磁盘存取(以内存作为代价)。

  • 传递-jn选项给make(1) 以便并发运行多个进程。这样就不会考虑你的是否是单个或多个处理器机器。

  • 存放/usr/src的文件系统可以使用noatime选项被装载(或再装载)。这样会防止文件系统记录文件的存取时间。你可能并不需要这些信息。

    # mount -u -o noatime /usr/src
    

    警告这个例子里假定/usr/src是在它自已的文件系统里。如果不是(例如假设它是/usr的部分),那么你就需要那个文件系统装载点,而不是/usr/src

  • 存放/usr/obj的文件系统可以使用async选项被装载(或被再装载)。这会引起异步写盘。换句话说,写是立即完成了,而数据要延迟几秒才会写到盘里。这就允许写到一堆,如此产生戏剧性的性能提高。

    警告记住,这个选项会使你的文件系统更加脆弱。使用这个选项增大了这样一个机率:要是电源断了,在机器重启后,文件系统将处在不可恢复状态。

    如果在这个文件系统里/usr/obj是很关键的,这不是问题。如果你有其它有价值的数据在同一个文件系统,那么在你使用这个选项这前,确认备份一下。

    # mount -u -o async /usr/obj
    

    警告同上,如果/usr/obj不在自已的文件系统里,使用相关装载点的名字把它从例子里边替换掉。

19.4.16.6. 如果出现了错误我该怎么办?

绝对确信你的环境没有先前build留下的残余。这点够简单。

# chflags -R noschg /usr/obj/usr
# rm -rf /usr/obj/usr
# cd /usr/src
# make cleandir
# make cleandir

不错,make cleandir真的要执行两次。

然后重新开始整个过程,使用make buildworld开始。

如果你还有问题,就把错误和uname -a的输出发送到FreeBSD general questions 邮件列表邮件列表。准备回答其它关于你的设置的问题!

Michael's Blog :: Just Do IT -- manuals