aboutsummaryrefslogtreecommitdiff
path: root/zh_CN.UTF-8/articles
diff options
context:
space:
mode:
authorXin LI <delphij@FreeBSD.org>2013-11-14 00:20:51 +0000
committerXin LI <delphij@FreeBSD.org>2013-11-14 00:20:51 +0000
commit797a990cf709e43fdcfa0f1b0b8b8e0127076002 (patch)
tree38ebab2823385023d1fa54018fceb14262c4cf93 /zh_CN.UTF-8/articles
parent8ff93b9827e6bfbbae625ff0d45eb2ce00ebe029 (diff)
downloaddoc-797a990cf709e43fdcfa0f1b0b8b8e0127076002.tar.gz
doc-797a990cf709e43fdcfa0f1b0b8b8e0127076002.zip
Convert zh_CN from GB2312 to UTF-8. While I'm there, also
fix a bunch of font issues when rendering PDF.
Notes
Notes: svn path=/head/; revision=43188
Diffstat (limited to 'zh_CN.UTF-8/articles')
-rw-r--r--zh_CN.UTF-8/articles/Makefile16
-rw-r--r--zh_CN.UTF-8/articles/Makefile.inc8
-rw-r--r--zh_CN.UTF-8/articles/contributing/Makefile22
-rw-r--r--zh_CN.UTF-8/articles/contributing/article.xml488
-rw-r--r--zh_CN.UTF-8/articles/cvs-freebsd/Makefile22
-rw-r--r--zh_CN.UTF-8/articles/cvs-freebsd/article.xml588
-rw-r--r--zh_CN.UTF-8/articles/linux-users/Makefile19
-rw-r--r--zh_CN.UTF-8/articles/linux-users/article.xml572
-rw-r--r--zh_CN.UTF-8/articles/nanobsd/Makefile28
-rw-r--r--zh_CN.UTF-8/articles/nanobsd/article.xml468
-rw-r--r--zh_CN.UTF-8/articles/rc-scripting/Makefile33
-rw-r--r--zh_CN.UTF-8/articles/rc-scripting/article.xml1219
-rw-r--r--zh_CN.UTF-8/articles/remote-install/Makefile28
-rw-r--r--zh_CN.UTF-8/articles/remote-install/article.xml512
14 files changed, 4023 insertions, 0 deletions
diff --git a/zh_CN.UTF-8/articles/Makefile b/zh_CN.UTF-8/articles/Makefile
new file mode 100644
index 0000000000..a0821cb7e0
--- /dev/null
+++ b/zh_CN.UTF-8/articles/Makefile
@@ -0,0 +1,16 @@
+#
+# The FreeBSD Simplified Chinese Project
+# Original Revision: 1.52
+#
+# $FreeBSD$
+
+SUBDIR =
+SUBDIR+= contributing
+SUBDIR+= cvs-freebsd
+SUBDIR+= linux-users
+SUBDIR+= nanobsd
+SUBDIR+= rc-scripting
+SUBDIR+= remote-install
+
+DOC_PREFIX?= ${.CURDIR}/../..
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_CN.UTF-8/articles/Makefile.inc b/zh_CN.UTF-8/articles/Makefile.inc
new file mode 100644
index 0000000000..6f1cac5e29
--- /dev/null
+++ b/zh_CN.UTF-8/articles/Makefile.inc
@@ -0,0 +1,8 @@
+#
+# The FreeBSD Simplified Chinese Project
+# Original Revision: 1.4
+#
+# $FreeBSD$
+#
+
+DESTDIR?= ${DOCDIR}/zh_CN.UTF-8/articles/${.CURDIR:T}
diff --git a/zh_CN.UTF-8/articles/contributing/Makefile b/zh_CN.UTF-8/articles/contributing/Makefile
new file mode 100644
index 0000000000..917c12fe11
--- /dev/null
+++ b/zh_CN.UTF-8/articles/contributing/Makefile
@@ -0,0 +1,22 @@
+#
+# The FreeBSD Simplified Chinese Project
+#
+# Original Revision: 1.6
+# $FreeBSD$
+#
+# Article: Contributing to FreeBSD
+
+DOC?= article
+
+FORMATS?= html
+WITH_ARTICLE_TOC?= YES
+
+INSTALL_COMPRESSED?=gz
+INSTALL_ONLY_COMPRESSED?=
+
+SRCS= article.xml
+
+URL_RELPREFIX?= ../../../..
+DOC_PREFIX?= ${.CURDIR}/../../..
+
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_CN.UTF-8/articles/contributing/article.xml b/zh_CN.UTF-8/articles/contributing/article.xml
new file mode 100644
index 0000000000..7a0437e965
--- /dev/null
+++ b/zh_CN.UTF-8/articles/contributing/article.xml
@@ -0,0 +1,488 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
+<!--
+ The FreeBSD Documentation Project
+ The FreeBSD Chinese (Simplified) Documentation Project
+
+ Original Revision: 1.511
+-->
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_cn">
+ <info><title>为 FreeBSD 提供帮助</title>
+
+
+ <abstract>
+ <para>无论是作为个人还是组织机构,如果您希望为FreeBSD项目提供帮助,
+ 都可以在本文中找到合适的方法。</para>
+ </abstract>
+
+ <authorgroup>
+ <author><personname><firstname>Jordan</firstname><surname>Hubbard</surname></personname><contrib>原著</contrib></author>
+ </authorgroup>
+
+ <legalnotice xml:id="trademarks" role="trademarks">
+ &tm-attrib.freebsd;
+ &tm-attrib.ieee;
+ &tm-attrib.general;
+ </legalnotice>
+
+ <pubdate>$FreeBSD$</pubdate>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+
+ </info>
+
+ <indexterm><primary>贡献 </primary></indexterm>
+
+ <para>您希望给 FreeBSD 项目做点什么吗? 太好了, 我们欢迎您。 FreeBSD 正是
+ <emphasis>依靠</emphasis> 广大用户的贡献才得以发展壮大的。
+ 我们不仅非常感谢您所做的贡献,而且,这些工作对于 FreeBSD 的持续发展也至关重要。</para>
+
+ <para>也许与您想象的不同, 您既不必是一名出色的程序员, 也无须和
+ FreeBSD 核心团队成员有很好的私交, 我们会一视同仁的对待您的工作。
+ FreeBSD 的开发人员遍布全球, 大家技术专长各异, 年龄分布也非常广泛。
+ 每天, 我们都在面对持续增长的工作而苦于没有足够的人手,
+ 因此我们随时欢迎您的帮助。</para>
+
+ <para>FreeBSD 项目处理的是一个完整的操作系统环境,
+ 而不只是一个内核或是一些零散的工具包。 因此, 我们的
+ <filename>TODO</filename> 任务列表里包含各种各样的工作,
+ 从文档、用户测试、演示, 到系统安装程序和高度专业的内核开发。
+ 因此无论您的技术水平如何, 从事何种领域, 都可以帮助这个项目。</para>
+
+ <para>我们鼓励从事和 FreeBSD 相关工作的企业和我们联系。
+ 您需要一些特殊的扩展来使您的产品运转起来么?
+ 您会发现我们很乐意答应您的请求, 除非是特别稀奇古怪的。
+ 您是否正从事相关的增值业务? 让我们来帮助您吧,
+ 我们也许可以在其中的某些方面相互协作。
+ 自由软件世界正在努力打破旧有的关于软件开发、 销售和维护的框框,
+ 我们希望恳请您至少能给它一次机会。</para>
+
+ <sect1 xml:id="contrib-what">
+ <title>我们的需求</title>
+
+ <para>下面列出了一些需要完成的任务和子项目,
+ 它们基本上可以被等同于 <filename>TODO</filename>(任务列表)
+ 列表, 以及用户的要求。</para>
+
+ <sect2 xml:id="non-programmer-tasks">
+ <title>正在进行中的非开发任务</title>
+
+ <para>很多参加FreeBSD项目的人不是程序员。
+ 这个项目里有文档撰写者、 网页设计师、 以及技术支持人员。
+ 对于这些志愿者来说, 他们只需要贡献一些时间,
+ 并且具有学习的意愿。</para>
+
+ <orderedlist>
+ <listitem>
+ <para>您可以经常通读FAQ和手册, 如果您发现了繁琐的解释,
+ 或者是过时的知识, 甚至完全不正确的地方, 都请告诉我们。
+ 如果您能顺手把他们改过来那就更好了
+ (SGML其实并不难学, 但我们也不反对您直接提交
+ ASCII 的版本)。</para>
+ </listitem>
+
+ <listitem>
+ <para>帮助我们把 FreeBSD 文档翻译成您的母语。
+ 如果您的母语版本已经存在了,
+ 您也可以翻译一些其他的文档或者检查那些已有的文档是否是最新更新过的。
+ 您可以先简单看看 FreeBSD 文档计划中有关 <link xlink:href="&url.books.fdp-primer;/translations.html">翻译的常见问题</link>。
+ 参加翻译工作并不是说您要孤军奋战翻译所有的 FreeBSD 文档。
+ 作为一个志愿者, 做多少工作完全取决于您的意愿。 一旦某个人开始翻译了,
+ 其他人几乎一定会参与到这些工作中来。
+ 如果您只有有限的时间或者精力去翻译部分文档,
+ 您可以首先去翻译安装指南。</para>
+ </listitem>
+
+ <listitem>
+ <para>阅读 &a.questions; 并偶尔看一看 &ng.misc;
+ (甚至有规律地这样做)。 与别人分享您的专业知识,
+ 并帮助他们解决问题是一件令人愉悦的事情;
+ 有些时候您甚至可以在这个过程中学到一些新东西!
+ 这些论坛有时也会为您提供一些有价值的主意。</para>
+ </listitem>
+ </orderedlist>
+ </sect2>
+
+ <sect2 xml:id="ongoing-programmer-tasks">
+ <title>正在进行的开发任务</title>
+ <para>列在这里的大部分任务都需要您投入可观的时间,
+ 或者需要您在 FreeBSD 内核方面有丰富的知识, 或者两者都要。
+ 当然这里也有很多重要的任务也许您一个
+ <quote>周末开发人员</quote> 就可以干完。</para>
+
+ <orderedlist>
+ <listitem>
+ <para>如果您正在运行 FreeBSD-CURRENT 版本并且有一条高速的
+ Internet接入线路, 您可以访问 <systemitem class="fqdomainname">current.FreeBSD.org</systemitem>,
+ 这里每天会有一个新版本 &mdash; 如果您有空,
+ 您可以隔三岔五地下载一份并且安装它,
+ 其间如果出了什么问题,请告诉我们。</para>
+ </listitem>
+
+ <listitem>
+ <para>阅读 &a.bugs;。 您可能会为这些问题提供具有建设性意义的评论,
+ 或者帮忙测试一些补丁。 此外,
+ 您甚至可以尝试修正其中的一些问题。</para>
+ </listitem>
+
+ <listitem>
+ <para>如果您知道有一些修正已经在 -CURRENT 上成功地进行,
+ 但在经过一段时间之后仍然没有合并到 -STABLE
+ (通常是 2周左右), 给相关的 committer 发一封礼貌的提示信。</para>
+ </listitem>
+
+ <listitem>
+ <para>将第三方软件加入到源代码中的
+ <filename>src/contrib</filename> 目录。</para>
+ </listitem>
+
+ <listitem>
+ <para>确保 <filename>src/contrib</filename>
+ 中的代码是最新的</para>
+ </listitem>
+
+ <listitem>
+ <para>以更高的警告级别构建源代码 (或一部分源代码)
+ 并清理这些警告。</para>
+ </listitem>
+
+ <listitem>
+ <para>更新那些在 ports 中使用过时的东西,
+ 例如 <function>gets()</function> 或包含
+ <filename>malloc.h</filename> 所产生的警告。</para>
+ </listitem>
+
+ <listitem>
+ <para>如果您制作了 ports, 并进行了一些针对
+ &os; 的改动, 将您的补丁发回给原作者
+ (这样下次升级时您的工作会变得轻松一些)。</para>
+ </listitem>
+
+ <listitem>
+ <para>获取一份正式的标准, 如 &posix; 的副本。
+ 您可以在 <link xlink:href="&url.base;/projects/c99/index.html">FreeBSD
+ C99 &amp; POSIX 标准顺应项目</link> 网站上得到相关的链接。
+ 将 FreeBSD 的行为同标准进行比较。 如果与标准不同,
+ 特别是那些细节地方的微小差异, 请发送一个关于它的 PR (问题报告)。
+ 如果可能, 请指出如何修正它, 并随 PR 提交补丁。
+ 如果您认为标准有问题,
+ 请向标准化团体要求对其进行重新的考虑。</para>
+ </listitem>
+
+ <listitem>
+ <para>为这份列表建议更多的内容!</para>
+ </listitem>
+ </orderedlist>
+ </sect2>
+
+ <sect2>
+ <title>查看整个 PR 数据库</title>
+
+ <indexterm><primary>问题报告数据库</primary></indexterm>
+
+ <para><link xlink:href="http://www.FreeBSD.org/cgi/query-pr-summary.cgi">FreeBSD
+ PR 列表</link> 展示了所有当前处于活跃状态的问题报告, 以及由
+ FreeBSD 用户提交的改进建议。 PR
+ 数据库同时包括了开发人员和非开发人员的任务。
+ 查看那些尚未解决的 PR, 并看看是否有您感兴趣的任务。
+ 这其中可能有一些是非常简单的问题,
+ 只需要看一看并确认 PR 是正确的。 另外一些可能会非常复杂,
+ 或者完全没有包括任何修正。</para>
+
+ <para>首先看一看那些还没有人接手的 PR。
+ 如果 PR 已经分配给了其它人, 但看起来是您能够处理的,
+ 您可以给那个人发信, 并询问您是否可以提供帮助 &mdash;
+ 他们可能已经有了可供测试的补丁, 或有一些可供讨论的意见。</para>
+ </sect2>
+
+ <sect2>
+ <title>从 <quote>点子</quote> 网页上认领项目</title>
+
+ <para><link xlink:href="&url.base;/projects/ideas/">&os;
+ 志愿者项目和点子清单</link> 也是提供给愿意为
+ &os; 项目做出贡献的人们的。
+ 这张清单一直在被定期更新着,
+ 包含了对程序员和非程序员有用的每个项目的信息。</para>
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="contrib-how">
+ <title>如何提供帮助</title>
+
+ <para>帮助改进系统基本上可以分为 5 类:</para>
+
+ <sect2 xml:id="contrib-general">
+ <title>错误报告和一般的注解</title>
+
+ <para>通常, <emphasis>一般意义上的</emphasis>
+ 技术想法和建议应该发到 &a.hackers;。
+ 同样地, 对于这些东西有兴趣的人 (当然,
+ 他们同时还要能够容忍 <emphasis>大量的</emphasis> 邮件!)
+ 可以考虑订阅 &a.hackers;。
+ 参见 <link xlink:href="&url.books.handbook;/eresources.html#ERESOURCES-MAIL">FreeBSD
+ 使用手册</link> 以了解关于这个邮件列表,
+ 以及其它邮件列表的详细情况。</para>
+
+ <para>如果您发现了 bug 或者想要提交某些修改,
+ 请通过 &man.send-pr.1; 程序或使用
+ <link xlink:href="&url.base;/send-pr.html">基于 WEB
+ 的提交页面</link> 来提交。 请试着填写 bug 报告的每一项。
+ 一般来说, 我们建议在 bug 报告中直接附上补丁, 除非它超过了 65KB。
+ 如果补丁可以直接应用到源代码上, 则建议您在报告的
+ synopsis 一栏写上 <literal>[PATCH]</literal>。
+ 在附带补丁时, 请 <emphasis>不要</emphasis>
+ 通过复制和粘贴来进行, 因为这样做会把 tab 变成空格,
+ 结果补丁很可能就不能用了。 如果补丁超过 20KB 很多,
+ 应考虑将其压缩 (例如使用 &man.gzip.1; 或 &man.bzip2.1;)
+ 之后用 &man.uuencode.1; 进行编码之后再放进您的问题报告中。</para>
+
+ <para>一旦报告被存档, 您会收到一封确认邮件以及一个事件追踪编号。
+ 请保留这个编号, 因为您可以在之后使用这个编号,
+ 发邮件到 &a.bugfollowup;
+ 来提供关于该事件的进一步信息。 您需要做的是将编号放到邮件的标题中,
+ 例如 <literal>"Re:
+ kern/3377"</literal>。
+ 关于同一问题更进一步的情况应该通过这种方式来提交。</para>
+
+ <para>如果您在一段时间之后仍然没有收到确认信 (超过 3
+ 天甚至 1 周, 这取决于您的邮件服务)
+ 或者由于某种原因无法使用 &man.send-pr.1; 命令,
+ 则可以发信给 &a.bugs; 要求别人代您发送它。</para>
+
+ <para>请参见 <link xlink:href="&url.articles.problem-reports;/article.html">这篇文章</link>
+ 了解如何撰写好的问题报告。</para>
+ </sect2>
+
+ <sect2>
+ <title>对于文档的修订</title>
+
+ <indexterm><primary>提交文档</primary></indexterm>
+
+ <para>对于文档的修改由 &a.doc; 来审查。
+ 请参见 <link xlink:href="&url.books.fdp-primer;/index.html">FreeBSD
+ 文档计划初级读本</link> 来获得完整的指导。
+ 请按照 <xref linkend="contrib-general"/> 中介绍的方法使用 &man.send-pr.1;
+ 来发送新的文档或者对于现有文档的完善 (哪怕是很小的改进也是欢迎的!)。</para>
+ </sect2>
+
+ <sect2>
+ <title>对于现有源代码的修改</title>
+
+ <indexterm><primary>FreeBSD-CURRENT</primary></indexterm>
+
+ <para>在现有代码上进行修改或增加功能在某种程度上是需要更多技巧的事情,
+ 并且还和您对于目前 FreeBSD 的开发现状的了解有关。
+ 有多种方式可以得到被称作 <quote>FreeBSD-CURRENT</quote>
+ 的 FreeBSD 开发版本, 您可以通过它来了解最近的开发情况。
+ 请参见 <link xlink:href=" &url.books.handbook;/current-stable.html">FreeBSD
+ 使用手册</link> 来了解使用 FreeBSD-CURRENT 的进一步详情。</para>
+
+ <para>在旧的代码上进行修改, 则通常可能由于代码已经过时,
+ 或与新的开发版本差异太大而无法被重新集成到 FreeBSD 中。
+ 如果您订阅了 &a.announce; 以及 &a.current; 邮件列表,
+ 则可以通过它们来大体了解目前的开发状态。</para>
+
+ <para>假如说您能够基于尽可能新的代码来完成您的修改,
+ 则下一步要做的事情就是生成您所进行的修改的差异文件,
+ 并将它发给 FreeBSD 的维护人员。 这项工作可以通过 &man.diff.1;
+ 命令来完成。</para>
+
+ <para>提交补丁时推荐的 &man.diff.1; 格式是一致差异 (unified diff),
+ 它可以通过 <command>diff
+ -u</command> 来生成。 不过, 如果您修改了大量的代码,
+ 则使用 <command>diff -c</command> 来生成的上下文格式 (context diff)
+ 的差异可能更容易阅读, 因而推荐使用。</para>
+
+ <indexterm>
+ <primary><command>diff</command></primary>
+ </indexterm>
+
+ <para>例如:</para>
+
+ <screen>&prompt.user; <userinput>diff -c oldfile newfile</userinput></screen>
+
+ <para>或者</para>
+
+ <screen>&prompt.user; <userinput>diff -c -r olddir newdir</userinput></screen>
+
+ <para>将分别生成给定文件或目录结构的 context diff。</para>
+
+ <para>类似地,</para>
+
+ <screen>&prompt.user; <userinput>diff -u oldfile newfile</userinput></screen>
+
+ <para>或</para>
+
+ <screen>&prompt.user; <userinput>diff -u -r olddir newdir</userinput></screen>
+
+ <para>的作用与前面的类似, 但采用的格式是 unified diff。</para>
+
+ <para>请参见 &man.diff.1; 联机手册了解更多细节。</para>
+
+ <para>一旦您使用 &man.diff.1; 生成了差异集 (可以使用
+ &man.patch.1; 命令来测试一下), 就可以提交它们,
+ 以便被 FreeBSD 收录。 通过使用 <xref linkend="contrib-general"/>
+ 中所介绍的 &man.send-pr.1; 程序就可以完成这项工作。
+ <emphasis>不要</emphasis> 只是把差异集发到 &a.hackers;,
+ 否则它们可能会被丢掉! 我们会非常感激您提交的修改
+ (这是一个志愿者项目!); 因为我们都很忙,
+ 因此有时不一定能够立即修正问题, 但 PR
+ 数据库将一直保持着这些记录,
+ 因此只要有人有了时间它们就能被改正了。
+ 如果您的问题报告中包括补丁, 一定不要忘了在标题上用
+ <literal>[PATCH]</literal> 来强调一下。</para>
+
+ <indexterm>
+ <primary><command>uuencode</command></primary>
+ </indexterm>
+
+ <para>如果您认为合适 (例如您添加、 删除或重命名了文件),
+ 还可以考虑使用
+ <command>tar</command> 来将文件打包, 然后用 &man.uuencode.1;
+ 来编码。 我们也欢迎用 &man.shar.1; 创建的包。</para>
+
+ <para>如果您的修改可能存在潜在的争议, 例如,
+ 您不确定与之相关的版权问题, 或者感觉需要经过更严格的复审才可以发布它们,
+ 则应直接发给 &a.core;, 而不是通过 &man.send-pr.1; 来发送。
+ &a.core; 是一个小组, 其成员更多的从事 FreeBSD 的日常工作。
+ 需要注意的是, 这个小组也因此 <emphasis>很忙</emphasis>,
+ 因此只有在非常必要的时候才应给他们写信。</para>
+
+ <para>请参考 &man.intro.9; 和 &man.style.9; 以了解关于编码习惯和约定的详情。
+ 如果您了解这些约定, 则对我们来说将是极大的帮助。</para>
+ </sect2>
+
+ <sect2>
+ <title>新代码或重要的增值软件包</title>
+
+ <para>如果您打算提供规模较大的代码, 或者为 FreeBSD 增加重要的新功能,
+ 则可能必须将它们通过 uuencode 进行编码, 或传到某个 Web 或
+ FTP 站点, 以便更多的人能够得到它。 如果您没有这样的服务器,
+ 请到相关的 FreeBSD 邮件列表提出, 看看是否有人愿意帮您放置它们。</para>
+
+ <para>对于大量的代码而言, 关于版权的问题肯定会被提出。
+ FreeBSD 基本系统中能够使用的版权声明包括:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>BSD<indexterm><primary>BSD 版权声明</primary></indexterm> 版权。 我们倾向于使用这类授权的代码,
+ 因为它 <quote>不附加多余的条件</quote>, 因而更能够吸引商业企业使用。
+ FreeBSD 并不反对商业公司使用它的代码, 相反,
+ 我们积极地鼓励商业公司使用我们的代码,
+ 当然, 如果它们最终把一部分代码重新捐赠给 FreeBSD
+ 就更好了。</para>
+ </listitem>
+
+ <listitem>
+ <para>GNU General Public License,<indexterm><primary>GPL</primary><see>GNU General Public License</see></indexterm><indexterm><primary>GNU General Public License</primary></indexterm> 或简称 <quote>GPL</quote>。
+ 我们并不很欢迎使用这样授权的代码,
+ 因为商业公司使用它需要做更多的工作。 不过, 由于很多使用
+ GPL 授权的代码目前是无法避免的 (编译器、 汇编器,
+ 文本排版程序等等), 拒绝使用所有采用这样授权的软件是很不明智的。
+ 采用 GPL 授权的代码会被放到源代码的一些专门的位置, 例如
+ <filename>/sys/gnu</filename> 或
+ <filename>/usr/src/gnu</filename>,
+ 以方便那些使用 GPL 代码可能会给他们带来问题的人识别。</para>
+ </listitem>
+ </orderedlist>
+
+ <para>使用其它授权的代码在进入 FreeBSD 之前必须经过慎重的复审和考虑。
+ 采用包含严厉限制的商业授权的代码, 一般来说会被拒绝,
+ 但我们鼓励这些代码的作者通过自己的渠道来发布它们。</para>
+
+ <para>要在您的成果上加入 <quote>BSD式</quote> 的版权,
+ 请把下列文本放到每一个源文件的最开始部分,
+ 并用适当的文字替换 <literal>%%</literal> 之间的文字。</para>
+
+ <programlisting>Copyright (c) %%proper_years_here%%
+ %%your_name_here%%, %%your_state%% %%your_zip%%.
+ All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer as
+ the first lines of this file unmodified.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY %%your_name_here%% ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL %%your_name_here%% BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ &#36;Id&#36;</programlisting>
+
+ <para>为了方便您的使用, 在
+ <filename>/usr/share/examples/etc/bsd-style-copyright</filename>
+ 也可以找到此授权的副本。</para>
+ </sect2>
+
+ <sect2>
+ <title>资金、 硬件或 Internet 接入</title>
+
+ <para>我们非常愿意接受各种形式的捐赠, 以进一步拓展 FreeBSD
+ Project 的事业, 因为有您的支持,
+ 像我们这样的志愿者努力才能够有更大的成就!
+ 捐赠硬件也非常重要, 因为这样能够帮助我们增加可以支持的硬件种类,
+ 而我们中的很多人并没有足够的资金来购置这些硬件。</para>
+
+ <sect3 xml:id="donations">
+ <title>捐款</title>
+
+ <para>FreeBSD 基金会是一个非营利的、 有课税豁免权的基金会,
+ 建立这个基金会的目标是为了让 FreeBSD Project 能够达成更加长远的目标。
+ 作为 501(c)3 实体, 一般而言基金会可以免予上缴美国联邦收入税,
+ 以及科罗拉多州收入税。 通常对于课税豁免的实体进行捐赠,
+ 可以折抵联邦收入中应课税部分的金额。</para>
+
+ <para>您可以把支票寄往:
+ <address>
+ The FreeBSD Foundation
+ <street>7321 Brockway Dr.</street>
+ <city>Boulder</city>, <state>CO</state> <postcode>80303</postcode>
+ <country>USA</country>
+ </address>
+ </para>
+
+ <para>FreeBSD 基金会现在可以通过 PayPal 从网上接受捐款。
+ 如果您想向基金会捐款, 请访问它的 <link xlink:href="http://www.freebsdfoundation.org">web
+ 站点</link>。</para>
+
+ <para>关于 FreeBSD 基金会的更多详情, 可以在 <link xlink:href="http://people.FreeBSD.org/~jdp/foundation/announcement.html">FreeBSD
+ 基金会 -- 介绍</link> 找到。 要联络基金会,
+ 请发送电子邮件到
+ <email>bod@FreeBSDFoundation.org</email>。</para>
+ </sect3>
+
+ <sect3>
+ <title>捐赠硬件</title>
+ <indexterm><primary>捐赠</primary></indexterm>
+
+ <para>FreeBSD 计划欢迎任何人捐赠可以使用的硬件。
+ 如果您有兴趣捐赠硬件, 请联系 <link xlink:href="&url.base;/donations/">捐赠联络人办公室</link>。</para>
+ </sect3>
+
+ <sect3>
+ <title>捐赠 Internet 接入</title>
+
+ <para>我们欢迎新的 FTP、 WWW 或
+ <command>cvsup</command> 镜像。 如果您希望成为这样的镜像,
+ 请参见 <link xlink:href="&url.articles.hubs;/index.html">如何架设 FreeBSD 镜像</link>
+ 一文, 以了解进一步的情况。</para>
+ </sect3>
+ </sect2>
+ </sect1>
+
+ <index/>
+
+</article>
diff --git a/zh_CN.UTF-8/articles/cvs-freebsd/Makefile b/zh_CN.UTF-8/articles/cvs-freebsd/Makefile
new file mode 100644
index 0000000000..ce7b36b13f
--- /dev/null
+++ b/zh_CN.UTF-8/articles/cvs-freebsd/Makefile
@@ -0,0 +1,22 @@
+# The FreeBSD Simplified Chinese Project
+#
+# Original Revision: 1.5
+# $FreeBSD$
+#
+# Article: Setting up a CVS repository - the FreeBSD way
+
+MAINTAINER= stijn@win.tue.nl
+
+DOC?= article
+
+FORMATS?= html
+
+INSTALL_COMPRESSED?= gz
+INSTALL_ONLY_COMPRESSED?=
+
+SRCS= article.xml
+
+URL_RELPREFIX?= ../../../..
+DOC_PREFIX?= ${.CURDIR}/../../..
+
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_CN.UTF-8/articles/cvs-freebsd/article.xml b/zh_CN.UTF-8/articles/cvs-freebsd/article.xml
new file mode 100644
index 0000000000..70d53be1aa
--- /dev/null
+++ b/zh_CN.UTF-8/articles/cvs-freebsd/article.xml
@@ -0,0 +1,588 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
+<!--
+ The FreeBSD Documentation Project
+ The FreeBSD Chinese (Simplified) Documentation Project
+
+ From FreeBSD: doc/zh_TW.Big5/articles/cvs-freebsd/article.xml,v 1.2 2006/01/31 01:30:59 vanilla
+ Original Revision: 1.17
+-->
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_cn">
+ <info><title>建立 CVS 储存库 (repository) - 以 FreeBSD 的方式</title>
+
+
+ <author><personname><firstname>Stijn</firstname><surname>Hoop</surname></personname><affiliation>
+ <address><email>stijn@win.tue.nl</email></address>
+ </affiliation></author>
+
+ <pubdate>$FreeBSD$</pubdate>
+
+ <copyright>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <holder role="mailto:stijn@win.tue.nl">Stijn Hoop</holder>
+ </copyright>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+
+ <legalnotice xml:id="trademarks" role="trademarks">
+ &tm-attrib.freebsd;
+ &tm-attrib.general;
+ </legalnotice>
+
+ <abstract>
+ <para>这份文件描述了使用和 FreeBSD 项目相同的命令脚本来建立 CVS 储存库的步骤。
+ 这和标准 CVS 建立的储存库相较之下有许多优点,
+ 它提供了更多对于源代码树的细粒度访问控制,
+ 并能够为每一次的提交生成和发出易读的电子邮件。</para>
+ </abstract>
+ </info>
+
+ <sect1 xml:id="introduction">
+ <title>简介</title>
+
+ <para>大多数的开放源代码软件项目都使用 <application>CVS</application>
+ 作为它们的源代码控制系统。 尽管 <application>CVS</application> 有许多的优点,
+ 但它也有部份的瑕疵和缺点。
+ 其中之一的原因是和其它的开发者分享源代码树可能会迅速成为系统管理的恶梦,
+ 特别是当有人希望保护部份的源代码树免受于一般的存取时。</para>
+
+ <para>FreeBSD 是众多使用 <application>CVS</application> 的项目之一,
+ 因为基于它进行开发的开发人员遍布于全世界。
+ 他们撰写了一些命令脚本使得管理储存库变得更加容易。
+ 最近这些命令脚本由 &a.joe; 重新整理过且更标准化,
+ 使得在其它的项目上再次使用这些命令脚本会更加容易。
+ 本文件将描述使用这些新的命令脚本的方法。</para>
+
+ <para>为了使本文件中的信息对您有用, 您需要首先熟悉 <application>CVS</application>
+ 的基本操作方式。</para>
+ </sect1>
+
+ <sect1 xml:id="first-setup">
+ <title>基本配置</title>
+
+ <warning>
+ <para>最好的方式是在一个全新的储存库中执行这些步骤,
+ 并确定你了解所有的后果。 同时, 请确定你有最新且可读的资料备份!</para>
+ </warning>
+
+ <sect2>
+ <title>初始化储存库</title>
+
+ <para>首先要做的是建立一个新的储存库, 执行下列命令告诉
+ <application>CVS</application> 建立并初始化:</para>
+
+ <screen>&prompt.user; <userinput>cvs -d path-to-repository init</userinput></screen>
+
+ <para>这命令告诉 <application>CVS</application> 建立
+ <filename>CVSROOT</filename> 的目录,
+ 这个目录里放置了所有的配置文件。</para>
+ </sect2>
+
+ <sect2>
+ <title>配置储存库的用户组</title>
+
+ <para>现在我们将建立一个拥有该储存库的用户组,
+ 所有的开发者必须加入这个用户组, 这样他们才能够存取该储存库。
+ 我们假设用户组名称是以 FreeBSD 内部所采用的
+ <literal>ncvs</literal>。</para>
+
+ <screen>&prompt.root; <userinput>pw groupadd ncvs</userinput></screen>
+
+ <para>接着你需要使用 &man.chown.8; 将目录所有者指定给刚刚新增的用户组:</para>
+
+ <screen>&prompt.root; <userinput>chown -R :ncvs path-to-your-repository</userinput></screen>
+
+ <para>如此一来, 没有适当的用户组许可的用户, 就不再能够写入该储存库。</para>
+ </sect2>
+
+ <sect2>
+ <title>取回源文件</title>
+
+ <para>现在你需要从 FreeBSD 储存库中取回 <filename>CVSROOT</filename> 目录,
+ 从 FreeBSD 匿名的 CVS 镜像站来取回会是最简单的方法。请查阅 <link xlink:href="&url.books.handbook;/anoncvs.html">在 使用手册 中的相关章节</link>
+ 来获得更多信息。 我们假设取回的文件存放在相同目录下的
+ <filename>CVSROOT-freebsd</filename> 目录中。</para>
+ </sect2>
+
+ <sect2>
+ <title>复制 FreeBSD 的命令脚本</title>
+
+ <para>接下来我们要复制 FreeBSD <filename>CVSROOT</filename>
+ 里的文件到你的储存库中。 如果你熟悉 <application>CVS</application>,
+ 你也许会想你可以直接汇入 (import) 这些命令脚本,
+ 从而更容易地在未来有新版时进行版本同步; 不过,事实是
+ <application>CVS</application> 在这个部份有缺点: 当汇入文件到
+ <filename>CVSROOT</filename> 时, 它并不会更新配置文件。
+ 为了要认出这些文件, 你还需要在汇入它们后一一重新提交, 这就失去了
+ <literal>cvs import</literal> 的价值。 因此, 推荐的方法是直接将这些命令脚本复制过去。</para>
+
+ <para>如果您不了解这些操作也没有关系 &mdash; 因为最后的结果都是一样的。
+ 首先汇出 (checkout) 你的 <filename>CVSROOT</filename>,
+ 然后复制刚刚取回的 FreeBSD 文件到本地的目录中(尚未变动过):</para>
+
+ <screen>&prompt.user; <userinput>cvs -d path-to-your-repository checkout CVSROOT</userinput>
+&prompt.user; <userinput>cd CVSROOT</userinput>
+&prompt.user; <userinput>cp ../CVSROOT-freebsd/* .</userinput>
+&prompt.user; <userinput>cvs add *</userinput></screen>
+
+ <para>注意: 你很可能会得到一段关于某些目录没有被复制的警告,这是正常的,
+ 你并不需要用到这些目录。</para>
+ </sect2>
+
+ <sect2>
+ <title>命令脚本说明</title>
+
+ <para>现在你的工作目录中有了完整 FreeBSD 项目在他们的储存库中使用的命令脚本的副本,
+ 以下是每个文件简单的介绍。</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><filename>access</filename> - 此文件在预设的安装中没有被用到。
+ 它是在 <link linkend="freebsdspecific">FreeBSD 的专用配置</link>
+ 中用来控制储存库的存取的。 如果你不希望使用这个配置的话,
+ 则可以删除这个文件。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>avail</filename> - 此文件控制储存库的存取。
+ 在此文件中你可以指定允许存取储存库的用户组,
+ 也可以针对目录或文件来拒绝提交。
+ 你应该调整为在你的储存库中将包含的用户组和目录。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>cfg.pm</filename> - 此文件说明了配置内容,并提供预设的配置。
+ 你 <emphasis>不</emphasis> 应修改此文件, 而应将修改的配置放到
+ <filename>cfg_local.pm</filename>。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>cfg_local.pm</filename> - 此文件包含所有的系统配置值。
+ 你应该配置所有列在此的配置, 例如提交的邮件要寄到哪、
+ 在哪些主机上的使用者可以提交等等。 更多的相关信息在稍后会提到。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>checkoutlist</filename> - 此文件列出所有在
+ <application>CVS</application> 控制下此目录中的文件, 除了标准在
+ <literal>cvs init</literal> 建立出的文件。 你可以删除某些不需要的
+ FreeBSD 专用的文件。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>commit_prep.pl</filename> - 此命令脚本执行各种提交前的检查,
+ 这些检查是否启用, 取决于您在 <filename>cfg_local.pm</filename>
+ 中所进行的配置。 你不应更动此文件。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>commitcheck</filename> - 此命令脚本会直接影响
+ <application>CVS</application>。 首先它会使用
+ <filename>cvs_acls.pl</filename> 来检查提交者是否可以存取指定的源代码树,
+ 然后执行 <filename>commit_prep.pl</filename> 来确认各种提交前的检查。
+ 如果一切正常,<application>CVS</application> 将允许此次提交继续执行。
+ 你不应更动此文件。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>commitinfo</filename> - 此文件是
+ <application>CVS</application> 用来定义在提交前所要执行的程序 &mdash;
+ 在此例中是 <filename>commitcheck</filename>。你不应更动此文件。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>config</filename> - 储存库的配置选项。
+ 你可以修改为你想要的, 但大多数的管理者可能会保留默认值。
+ 更多关于可以在此配置的选项信息可以查阅 <application>CVS</application> 手册。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>cvs_acls.pl</filename> - 此命令脚本定义提交者的身分,
+ 以及他/她是否允许存取源代码树, 这些判断基于 <filename>avail</filename>
+ 中的配置。 你不应更动此文件。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>cvsignore</filename> - 此文件列出哪些文件
+ <application>CVS</application> 不用处理到储存库中,
+ 你可以修改成你想要的。 更多关于可以此文件的说明可以查阅 <application>CVS</application>
+ 手册。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>cvswrappers</filename> - 此文件是
+ <application>CVS</application> 用来启用或停用关键词展开,
+ 或者是否应将文件视为二进制文件。 你可以修改成你想要的。
+ 更多关于可以此文件的说明可以查阅 <application>CVS</application> 手册。
+ 注意 <literal>-t</literal> 和 <literal>-f</literal> 选项在
+ <application>CVS</application> 客户端/服务器 并不能够正确地运作。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>edithook</filename> - 此文件已经不再使用了,
+ 仅为历史原因保留。 你可以安全地删除此文件。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>editinfo</filename> - <application>CVS</application>
+ 使用这个文件来强迫你使用特定的编辑器。 FreeBSD 没有使用这个功能,
+ 而对输入的日志信息的检查, 则由 <filename>verifymsg</filename> 和
+ <filename>logcheck</filename> 来完成。 这是因为
+ <filename>editinfo</filename> 功能在从远程提交或是使用
+ <literal>-m</literal> 或 <literal>-F</literal> 选项时不会执行。
+ 你不应更动此文件。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>exclude</filename> - 此文件列出被
+ <filename>commit_prep.pl</filename> 定义不能包含修正版标头的文件。
+ 在 FreeBSD 版本的配置中, 所有在修正版控制下的文件需有一个修正版标头,
+ (类似 &dollar;FreeBSD&dollar; 这样)。
+ 此文件逐行列出不应进行检查的文件名字。
+ 你可以在此文件中为不需要修正版标头的文件新增一个正则表达式。
+ 为了安装这些命令脚本, 最好的方法是将
+ <filename>CVSROOT/</filename> 从标头检查中排除。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>log_accum.pl</filename> - 此命令脚本会处理由
+ <filename>logcheck</filename> 所提供的日志信息,
+ 并且将之为备份目的附加于储存库中的记录文件。
+ 同时也执行要将邮件寄到你提供的信箱中的程序 (在 <filename>cfg_local.pm</filename> 中)。
+ 它和 <application>CVS</application> 之间是由 <filename>loginfo</filename>
+ 负责沟通。 你不应更动此文件。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>logcheck</filename> - 此文件分析提交者提供的日志信息,
+ 并试图对其作清理动作。 它和 <application>CVS</application>
+ 之间是由 <filename>verifymsg</filename> 负责沟通。 你不应更动此文件。</para>
+
+ <note><para>此命令脚本依赖于经过 FreeBSD 修改的 <application>CVS</application>:
+ FreeBSD 版本在此命令脚本修改过后才读取日志信息; 标准的
+ <application>CVS</application> 版本虽然能够检查语法上是否正确,
+ 但并不会清理日志信息。<application>CVS</application> 1.11.2 可以通过在
+ <filename>config</filename> 配置 <literal>RereadLogAfterVerify=always</literal>
+ 来和 FreeBSD 版本有相同的作用。</para></note>
+ </listitem>
+
+ <listitem>
+ <para><filename>loginfo</filename> - 此文件是
+ <application>CVS</application> 用来控制日志信息要寄到哪里,而
+ <filename>log_accum.pl</filename> 负责处理。你不应更动此文件。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>modules</filename> - 此文件保留了
+ <application>CVS</application> 原始的意义。 你应该删除新增的 FreeBSD
+ 模块, 并修改为你想要的内容。 更多关于可以此文件的说明可以查阅
+ <application>CVS</application> 手册。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>notify</filename> - 此文件为
+ <application>CVS</application> 用来控制监看某个文件。
+ 在 FreeBSD 的储存库中没有用到此文件,
+ 你可以修改成你想要的。 更多关于可以此文件的说明,
+ 可以查阅 <application>CVS</application> 手册。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>options</filename> - 此文件仅限使用于 FreeBSD 和 Debian
+ 的 <application>CVS</application> 版本。
+ 它包含了需要在修正版标头中展开的关键词。
+ 你可以修改为符合你在 <filename>cfg_local.pm</filename> 中指定的关键词。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>rcsinfo</filename> - 此文件定义提交时,
+ 储存库所要使用的日志信息样式模板, 如 <filename>rcstemplate</filename>。
+ FreeBSD 预设为所有的储存库使用同一个样式模板,
+ 你可以加入其它你想要的。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>rcstemplate</filename> - 此文件是提交者在提交时会看到的日志信息样式模板,
+ 你应该修改为你在 <filename>cfg_local.pm</filename>
+ 中定义的各种参数。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>tagcheck</filename> - 此文件控制在储存库中贴上标签的存取。
+ 标准的 FreeBSD 版本拒绝名为 RELENG* 的标签,因为这是 交付工程组 的工作。
+ 你可以根据需要来修改此文件。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>taginfo</filename> - 此文件控制执行在储存库中贴上标签的存取的命令脚本,
+ 如 <filename>tagcheck</filename>。你不应更动此文件。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>unwrap</filename> - 此命令脚本可以用来在汇出时自动 <quote>解开</quote>
+ 二进制文件 (请见 <filename>cvswrappers</filename>)。 目前 FreeBSD
+ 并没有使用此配置, 因为此功能在远程提交时执行的并不十分完善。
+ 你不应更动此文件。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>verifymsg</filename> - 此文件用来执行和日志信息相关的命令脚本,
+ 如 <filename>logcheck</filename>。你不应更动此文件。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>wrap</filename> - 此命令脚本可以用来在提交时自动 <quote>包裹</quote>
+ 二进制文件 (请见 <filename>cvswrappers</filename>)。 目前 FreeBSD
+ 并没有使用此配置, 因为此功能在远程提交时执行的并不十分完善。
+ 你不应更动此文件。</para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+
+ <sect2>
+ <title>定制命令脚本</title>
+
+ <para>接下来的步骤要配置这些命令脚本使得它们可以在你的环境中运作。
+ 你应该检查所有在目录中的文件, 并修改为符合你的配置。
+ 尤其, 你会想要修改下列的文件:</para>
+
+ <procedure>
+ <step>
+ <para>如果你不希望使用 <link linkend="freebsdspecific">FreeBSD 的专用配置</link>,
+ 你可以安全地删除 <filename>access</filename>:</para>
+
+ <screen>&prompt.user; <userinput>cvs rm -f access</userinput></screen>
+ </step>
+
+ <step>
+ <para>编辑 <filename>avail</filename> 来包含你想控制存取的各种储存库目录,
+ 请确定你有保留 <literal>avail||CVSROOT</literal> 这一行,
+ 否则你将会在下一步把你自己锁在外面。</para>
+
+ <para>另外你可以在此文件中新增开发者的用户组,FreeBSD 预设使用
+ <filename>access</filename> 来列出所有的开发者,
+ 但你可以使用任何你想要用的文件。 如果你想的话也可以新增用户组 (请使用指定在
+ <filename>cvs_acls.pl</filename> 前面所介绍的语法)。</para>
+ </step>
+
+ <step>
+ <para>编辑 <filename>cfg_local.pm</filename> 来包含你需要的选项。
+ 你应该特别检视一下下列的配置项目:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>%TEMPLATE_HEADERS</literal> - 这是用来取得日志信息内容的程序,
+ 并加入将呈现的邮件项目和提供非空值的信息。
+ 你可以删除 <literal>PR</literal> 和 <literal>MFC after</literal>
+ 叙述,当然也可以加入你想要的。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>$MAIL_BRANCH_HDR</literal> - 如果你想要在每一封提交的邮件中加入描述是在哪一个分支中提交的标头,
+ 那么请定义为符合你的配置。 如果你不想使用这样的标头, 那么请配置为空值。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>@COMMIT_HOSTS</literal> - 定义使用者能够提交的主机。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>$MAILADDRS</literal> - 配置应该收到提交邮件的邮件地址。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>@LOG_FILE_MAP</literal> - 以你所需要的来修改这个数组,
+ 每个配置值应该符合被提交的目录,而提交的日志信息会以
+ <filename>commitlogs</filename> 的名称储存在每个被配置的目录下。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>$COMMITCHECK_EXTRA</literal> - 如果你不想使用
+ <link linkend="freebsdspecific">FreeBSD 专用的存取控制</link>
+ 功能, 你可以在此文件中删除对 <literal>$COMMITCHECK_EXTRA</literal>
+ 的定义。</para>
+ </listitem>
+ </itemizedlist>
+
+ <note><para>修改 <literal>$IDHEADER</literal> 的功能只有在 FreeBSD
+ 平台上可以运作, 它依赖于 FreeBSD 专用的 <application>CVS</application>
+ 配置。</para></note>
+
+ <para>你可以检查 <filename>cfg.pm</filename> 是否有其它的参数可以修改,
+ 但是修改最好是有原因的。</para>
+ </step>
+
+ <step>
+ <para>删除 <filename>exclude</filename> 中关于FreeBSD 的专用配置的叙述
+ (如以 <literal>^ports/</literal> 为开头的每一行等)。 此外,
+ 注释掉以 <literal>^CVSROOT/</literal> 为开头的行列, 然后新增一行只有
+ <literal>^CVSROOT/</literal>。 等到关键词展开的命令脚本安装好后,
+ 你可以在 <filename>CVSROOT</filename> 目录中的文件里加上标头,
+ 然后再恢复刚刚注释的行列, 但在你还没有提交前则只保持这样。</para>
+ </step>
+
+ <step>
+ <para>编辑 <filename>modules</filename>, 并删除所有 FreeBSD 的模块。
+ 加入你需要的模块。</para>
+ </step>
+
+ <step>
+ <note><para>此步骤只有在你于 <filename>cfg_local.pm</filename> 中指定了
+ <literal>$IDHEADER</literal> 才有必要配置 (只有在 FreeBSD 专用的
+ <application>CVS</application> 配置上才能够执行)。</para></note>
+
+ <para>编辑 <filename>options</filename> 以符合你在
+ <filename>cfg_local.pm</filename> 中配置的标签名称。
+ 在所有的文件中搜寻 <literal>FreeBSD</literal>
+ 并替换为你配置的标签名称。</para>
+ </step>
+
+ <step>
+ <para>修改 <filename>rcstemplate</filename> 为和在
+ <filename>cfg_local.pm</filename> 中相同的配置。</para>
+ </step>
+
+ <step>
+ <para>选择性的删除在 <filename>tagcheck</filename> 中针对 FreeBSD
+ 检查的配置。你可以仅仅在文件的最上层加上 <literal>exit 0</literal>
+ 来取消所有标签的检查。</para>
+ </step>
+
+ <step>
+ <para>在你完成前的最后一件事是确认 commitlogs 可以正确储存。
+ 预设会储存在储存库中 <filename>CVSROOT</filename> 里的
+ <filename>commitlogs</filename> 子目录中,
+ 而这个目录需要事先建立:</para>
+
+ <screen>&prompt.user; <userinput>mkdir commitlogs</userinput>
+&prompt.user; <userinput>cvs add commitlogs</userinput></screen>
+ </step>
+ </procedure>
+
+ <para>现在, 在细心的检视过后, 你可以提交你的修改了。 确定你先前有在
+ <filename>avail</filename> 中允许你自己存取 <filename>CVSROOT</filename>
+ 目录, 因为如果没有这样做的话你会把你自己锁在外面。
+ 完整确认过后请执行下列命令:</para>
+
+ <screen>&prompt.user; <userinput>cvs commit -m '- Initial FreeBSD scripts commit'</userinput></screen>
+ </sect2>
+
+ <sect2>
+ <title>测试配置</title>
+
+ <para>你已经准备好做基本的测试了: 强制提交 <filename>avail</filename>
+ 以确认每件事都如预期的运作。</para>
+
+ <screen>&prompt.user; <userinput>cvs commit -f -m 'Forced commit to test the new CVSROOT scripts' avail</userinput></screen>
+
+ <para>如果一切正常, 那么恭喜了! 你现在已经为你的储存库建立好 FreeBSD
+ 的命令脚本了。 如果 <application>CVS</application> 仍然有警告什么,
+ 回头检视上述的步骤是否有正确的执行。</para>
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="freebsdspecific">
+ <title>FreeBSD 的专用配置</title>
+
+ <para>FreeBSD 项目自己使用一个有点不同的配置,那就是同时也使用 FreeBSD
+ <filename>CVSROOT</filename> 中的 <filename>freebsd</filename> 子目录。
+ 因为大量的 committer 必须在相同的用户组中, 因此项目写了一个简单的 wrapper
+ 来确保 committer 可以正确的提交, 并配置储存库的用户组名称。</para>
+
+ <para>如果你的储存库也需要这样的功能,那么下面就会介绍如何建立,
+ 不过首先要先来看一段复杂的概述。</para>
+
+ <sect2>
+ <title>FreeBSD 配置中使用的文件</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><filename>access</filename> - 此文件用来控制储存库的存取。
+ 你应该编辑并加入所有在项目中的成员。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>freebsd/commitmail.pl</filename> -
+ 此文件已经不再使用了,
+ 只是因为历史原因而保留。 你不应更动此文件。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>freebsd/cvswrap.c</filename> - 此 CVS wrapper
+ 源代码是用来建立检查所有存取的工作。更多的信息在稍后会提出。
+ 你应该编辑 <literal>ACCESS</literal> 和 <literal>REALCVS</literal>
+ 的路径以符合你的配置。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>freebsd/mailsend.c</filename> - 此文件是 FreeBSD 设定
+ mailing lists 需要的, 你不应更动此文件。</para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+
+ <sect2>
+ <title>步骤</title>
+
+ <procedure>
+ <step>
+ <para>只把你的用户名加到 <filename>access</filename> 中。</para>
+ </step>
+
+ <step>
+ <para>编辑 <filename>cvswrap.c</filename> 的路径以符合你的配置,
+ 定义在大写的 <literal>ACCESS</literal> 中。
+ 同时如果默认值不符合你的情况的话也应该修改本地实际的 <command>cvs</command>
+ 程序所在位置。 原始的 <filename>cvswrap.c</filename>
+ 希望替代服务器端的 CVS 程序,
+ 例如将其改名为 <filename>/usr/bin/ncvs</filename>。</para>
+
+ <para>我的 <filename>cvswrap.c</filename> 是这样:</para>
+
+ <programlisting>#define ACCESS "/local/cvsroot/CVSROOT/access"
+#define REALCVS "/usr/bin/ncvs"</programlisting>
+ </step>
+
+ <step>
+ <para>接下来是建立 wrapper 来确认你在提交时是在正确的用户组中。
+ 在你的 <filename>CVSROOT</filename> 中的
+ <filename>cvswrap.c</filename> 要能够使用。</para>
+
+ <para>在你完成编辑并加入正确的路径后我们要来编译源代码:</para>
+
+ <screen>&prompt.user; <userinput>cc -o cvs cvswrap.c</userinput></screen>
+
+ <para>然后进行需要配置(此步骤需要 root 权限):</para>
+
+ <screen>&prompt.root; <userinput>mv /usr/bin/cvs /usr/bin/ncvs</userinput>
+&prompt.root; <userinput>mv cvs /usr/bin/cvs</userinput>
+&prompt.root; <userinput>chown root:ncvs /usr/bin/cvs /usr/bin/ncvs</userinput>
+&prompt.root; <userinput>chmod o-rx /usr/bin/ncvs</userinput>
+&prompt.root; <userinput>chmod u-w,g+s /usr/bin/cvs</userinput></screen>
+
+ <para>这会将 wrapper 安装成预设的 <command>cvs</command> 程序,
+ 请确定任何要使用储存库的人应该有正确的存取权限。</para>
+ </step>
+
+ <step>
+ <para>现在你可以删除所有在储存库用户组中的使用者,所有的存取控制会经由
+ wrapper 完成,同时 wrapper 会配置存取的正确用户组。</para>
+ </step>
+ </procedure>
+ </sect2>
+
+ <sect2>
+ <title>测试配置</title>
+
+ <para>你的 wrapper 现在应该已经安装好了,你当然也可以强制提交
+ <filename>access</filename> 来测试是否正常:</para>
+
+ <screen>&prompt.user; <userinput>cvs commit -f -m 'Forced commit to test the new CVSROOT scripts' access</userinput></screen>
+
+ <para>同样地,如果有错误,检查是否上述所有步骤都有正确的执行。</para>
+ </sect2>
+ </sect1>
+</article>
diff --git a/zh_CN.UTF-8/articles/linux-users/Makefile b/zh_CN.UTF-8/articles/linux-users/Makefile
new file mode 100644
index 0000000000..7655a1e45c
--- /dev/null
+++ b/zh_CN.UTF-8/articles/linux-users/Makefile
@@ -0,0 +1,19 @@
+#
+# $FreeBSD$
+# Original Revision: 1.1
+# Article: FreeBSD Quickstart for Linux Users
+
+DOC?= article
+
+FORMATS?= html
+WITH_ARTICLE_TOC?= YES
+
+INSTALL_COMPRESSED?= gz
+INSTALL_ONLY_COMPRESSED?=
+
+SRCS= article.xml
+
+URL_RELPREFIX?= ../../../..
+DOC_PREFIX?= ${.CURDIR}/../../..
+
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_CN.UTF-8/articles/linux-users/article.xml b/zh_CN.UTF-8/articles/linux-users/article.xml
new file mode 100644
index 0000000000..01f4c45b5b
--- /dev/null
+++ b/zh_CN.UTF-8/articles/linux-users/article.xml
@@ -0,0 +1,572 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
+<!--
+ The FreeBSD Documentation Project
+ The FreeBSD Chinese (Simplified) Documentation Project
+
+ Original Revision: r39170
+-->
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_cn">
+ <info><title>&linux; 用户的 FreeBSD 快速入门向导</title>
+
+
+ <authorgroup>
+ <author><personname><firstname>John</firstname><surname>Ferrell</surname></personname></author>
+ </authorgroup>
+
+ <pubdate>$FreeBSD$</pubdate>
+
+ <copyright>
+ <year>2008</year>
+ <holder>The FreeBSD Documentation Project</holder>
+ </copyright>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+
+ <legalnotice xml:id="trademarks" role="trademarks">
+ &tm-attrib.freebsd;
+ &tm-attrib.linux;
+ &tm-attrib.intel;
+ &tm-attrib.redhat;
+ &tm-attrib.unix;
+ &tm-attrib.general;
+ </legalnotice>
+
+ <abstract>
+ <para>本文档旨在快速使那些高级 &linux;
+ 用户熟悉FreeBSD的一些基础知识。</para>
+ </abstract>
+ </info>
+
+ <sect1 xml:id="intro">
+ <title>简介</title>
+
+ <para>本文档将突出介绍 &os; 与 &linux; 的差别,
+ 以使得那些 &linux; 高级用户能自己快速熟悉 &os;
+ 的基础内容。这只是份技术上的快速入门,
+ 并非是试图描绘这两种操作系统之间的"哲学"上的差异。</para>
+
+ <para>此文档假定认为你已经安装好了 &os;。
+ 如果你还没有安装 &os; 或者对 &os;
+ 的安装过程方面需要帮助,请参考 &os; 手册的
+ <link xlink:href="&url.base;/doc/en_US.ISO8859-1/books/handbook/install.html">
+ 安装 FreeBSD</link>一章。</para>
+ </sect1>
+
+ <sect1 xml:id="shells">
+ <title>Shell程序:没有Bash吗?</title>
+
+ <para>那些从 &linux; 转过来的用户经常会惊讶于
+ <application>Bash</application> 不是 &os; 的默认 Shell。
+ 事实上,<application>Bash</application> 甚至没有包括在
+ &os; 的默认安装中。代替的是,&os; 使用 &man.tcsh.1;
+ 作为自己的默认 Shell,尽管如此,<application>Bash</application>
+ 和其他你喜爱的 Shell 程序在 &os; 的
+ <link xlink:href="article.html#SOFTWARE">Packages 和 Ports 套件</link>
+ 里都可以找到。</para>
+
+ <para>如果你安装了其他的 Shell 你可以使用 &man.chsh.1;
+ 来设置一个用户的默认 Shell。 通常情况下,
+ 强烈建议不要去更改 <systemitem class="username">root</systemitem>
+ 用户的默认 Shell。原因是这些 Shell
+ 没有包括在基本系统中,正常情况下它们会被安装到
+ <filename>/usr/local/bin</filename> 和
+ <filename>/usr/bin</filename> 目录下。万一某天
+ <filename>/usr/local/bin</filename> 和
+ <filename>/usr/bin</filename> 的文件系统不能被挂载,
+ 这样情况下 <systemitem class="username">root</systemitem>
+ 将不能进入自己默认的 Shell,从而
+ <systemitem class="username">root</systemitem> 将不能够登录进去。
+ 鉴于这个原因,第二个系统管理员帐户
+ <systemitem class="username">toor</systemitem> 创建时使用的是非默认的
+ Shell。在安全 FAQ 可以查阅到关于 <link xlink:href="&url.base;/doc/en_US.ISO8859-1/books/faq/security.html#TOOR-ACCOUNT">toor 帐户</link>
+ 的信息。</para>
+ </sect1>
+
+ <sect1 xml:id="software">
+ <title>Packages和Ports:在 &os; 中添加软件</title>
+
+ <para>除了经典的 &unix; 安装软件的方法
+ (下载源码包,解压,编辑源码,编译)外,&os;
+ 还提供了另外两种方法来安装应用程序:packages 和 ports。
+ 你可以在 <link xlink:href="http://www.freebsd.org/ports/master-index.html">这里</link>
+ 到一份完整可用的 ports 和 packages 的软件清单。</para>
+
+ <sect2 xml:id="packages">
+ <title>Packages</title>
+
+ <para>Packages 是预编译好的应用程序,在 &os;
+ 中等价于基于 Debian/Ubuntu 的系统中的
+ <filename>.deb</filename> 软件包以及基于
+ Red&nbsp;Hat/Fedora 的系统中的
+ <filename>.rpm</filename> 软件包。
+ Packages使用 &man.pkg.add.1; 来进行安装。
+ 例如,下面的命令将用来安装
+ <application>Apache 2.2</application>:</para>
+
+ <screen>&prompt.root; <userinput>pkg_add /tmp/apache-2.2.6_2.tbz</userinput></screen>
+
+ <para>使用 <option>-r</option> 操作将告诉 &man.pkg.add.1;
+ 来自动获取并安装一个软件包,以及解决所有的依赖关系:</para>
+
+ <screen>&prompt.root; <userinput>pkg_add -r apache22</userinput>
+Fetching ftp://ftp.freebsd.org/pub/FreeBSD/ports/i386/packages-6.2-release/Latest/apache22.tbz... Done.
+Fetching ftp://ftp.freebsd.org/pub/FreeBSD/ports/i386/packages-6.2-release/All/expat-2.0.0_1.tbz... Done.
+Fetching ftp://ftp.freebsd.org/pub/FreeBSD/ports/i386/packages-6.2-release/All/perl-5.8.8_1.tbz... Done.
+[snip]
+
+To run apache www server from startup, add apache22_enable="YES"
+in your /etc/rc.conf. Extra options can be found in startup script.</screen>
+
+ <note>
+ <para>如果你正运行着 release 版本的 &os; (6.2,6.3,7.0等,
+ 通常从 CD-ROM 被安装的)<command>pkg_add -r</command>
+ 会为其下载专门为这些特定版本构建好的软件包。
+ 这些软件包 <emphasis>可能</emphasis> 不是当前最新的程序。
+ 你可以使用 <envar>PACKAGESITE</envar> 变量来覆盖默认的动作。
+ 例如,把 <envar>PACHAGESITE</envar> 设置成
+ <uri xlink:href="ftp://ftp.freebsd.org/pub/FreeBSD/ports/i386/packages-6-stable/Latest/">ftp://ftp.freebsd.org/pub/FreeBSD/ports/i386/packages-6-stable/Latest/</uri>
+ 来下载 6.X 系列最新的包。</para>
+ </note>
+
+ <para>想了解更多的 packages 信息请查阅 &os;
+ 手册的 4.4 小节:<link xlink:href="&url.base;/doc/en_US.ISO8859-1/books/handbook/packages-using.html">使用 Packages 系统</link>。</para>
+ </sect2>
+
+ <sect2 xml:id="ports">
+ <title>Ports</title>
+
+ <para>&os; 的第二种安装应用程序的方法就是使用 Ports 套件了。
+ Ports 套件是 &os; 上的一个利用 <filename>Makefile</filename>
+ 和一些补丁文件来特定从源码定制安装各种软件程序的框架。
+ 当安装一个 port 时系统会获取程序源码,
+ 应用任何所需要的补丁,编译源码,
+ 并安装应用程序(并针对依赖关系以同样的方式安装解决)。</para>
+
+ <para>Ports 套件,常被称作 ports 树,可以在
+ <filename>/usr/ports</filename> 下找到。
+ 假设Ports套件已经在安装 &os; 时安装过了。
+ 如果 Ports 套件还没有被安装可以通过 &man.sysinstall.8;
+ 来进行安装,或者使用 &man.csup.1; 或 &man.portsnap.8;
+ 来从 &os; 的服务器上面拉下来。在手册的 <link xlink:href="&url.base;/doc/en_US.ISO8859-1/books/handbook/ports-using.html">4.5.1 小节</link>
+ 可以找到安装 Ports 套件的详细介绍。</para>
+
+ <para>安装一个 port 就像进入 port
+ 的目录并开始构建过程一样简单(通常情况下),
+ 下面是从 Ports 套件安装
+ <application>Apache 2.2</application> 的例子:</para>
+
+ <screen>&prompt.root; <userinput>cd /usr/ports/www/apache22</userinput>
+&prompt.root; <userinput>make install clean</userinput></screen>
+
+ <para>使用 ports 安装软件的最大好处就是能够自定义安装选项。
+ 例如,从 ports 安装 <application>Apache 2.2</application>
+ 时你可以通过设置 <varname>WITH_LDAP</varname> &man.make.1;
+ 变量来启用 <application>mod_ldap</application>:</para>
+
+ <screen>&prompt.root; <userinput>cd /usr/ports/www/apache22</userinput>
+&prompt.root; <userinput>make WITH_LDAP="YES" install clean</userinput></screen>
+
+ <para>请查看 &os; 手册的 4.5 小节,<link xlink:href="&url.base;/doc/en_US.ISO8859-1/books/handbook/ports-using.html">
+ 使用 Ports&nbsp;Collection</link>,
+ 以获取更多关于Ports&nbsp;Collection 的信息。</para>
+ </sect2>
+
+ <sect2 xml:id="which">
+ <title>Ports还是packages,我应该使用哪个?</title>
+
+ <para>Packages 就是预编译好的 ports,
+ 所以从源码(ports)安装与从二进制 packages
+ 安装这两者间确实有很大关联。每种方法各有自己的优点:</para>
+
+ <itemizedlist>
+ <title>Packages(二进制)</title>
+
+ <listitem><simpara>更快速的安装
+ (比较大的应用程序编译起来会花很长时间)。</simpara></listitem>
+
+ <listitem><simpara>你不需要知道如何编译软件。</simpara></listitem>
+
+ <listitem><simpara>不需要在操作系统上安装编译器。</simpara></listitem>
+ </itemizedlist>
+
+ <itemizedlist>
+ <title>Ports(源码)</title>
+
+ <listitem><simpara>能够定制安装选项。
+ (Packages通常都是使用标准选项构建的。使用 ports
+ 你能够定义各种各样的选项,
+ 比如类似构建附加的模块或是更改安装路径之类的。)</simpara></listitem>
+
+ <listitem><simpara>如果你喜欢的话还可以使用自己的补丁。</simpara></listitem>
+ </itemizedlist>
+
+ <para>如果你没有一些特别的需求, packages
+ 可能刚好最适合你的情况。如果你需要进一步定制,
+ ports 是最适合的方法了。(请记得,
+ 如果你需要定制而自己又更倾向于使用 packages,
+ 你可以使用 <command>make</command>
+ <buildtarget>package</buildtarget> 从 ports
+ 构建一个定制的 package,然后复制到其他的服务器。)</para>
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="startup">
+ <title>系统启动:运行级别在哪里?</title>
+
+ <para>&linux; 使用 Sysv init 初始化系统,而 &os;
+ 使用的是传统的 BSD 风格的 &man.init.8;。在 BSD 风格的
+ &man.init.8; 中没有运行级别和 <filename>/etc/inittab</filename>,
+ 代替控制启动的是 &man.rc.8; 实用程序。
+ <filename>/etc/rc</filename> 脚本读取
+ <filename>/etc/defaults/rc.conf</filename> 和
+ <filename>/etc/rc.conf</filename> 文件来决定哪个服务将被启动。
+ 特殊服务在此后由处于 <filename>/etc/rc.d/</filename> 和
+ <filename>/usr/local/etc/rc.d/</filename>
+ 下的相应服务初始化脚本文件所启动。
+ 这些脚本类似于位于 &linux; 系统中的
+ <filename>/etc/init.d/</filename> 目录下的脚本。</para>
+
+ <sidebar>
+ <para><emphasis>为何会有两个服务初始化脚本的目录呢?</emphasis>
+ <filename>/etc/rc.d/</filename> 下的脚本是属于
+ <quote>基本</quote> 系统一部分的应用程序所使用的。
+ (&man.cron.8;,&man.sshd.8;,&man.syslog.3;,以及其他。)
+ <filename>/usr/local/etc/rc.d/</filename>
+ 下的脚本是用户安装的应用程序如 <application>Apache</application>,
+ <application>Squid</application> 等使用的。</para>
+
+ <para><emphasis><quote>基本</quote>
+ 系统和用户安装的应用程序之间的区别是什么?</emphasis> FreeBSD
+ 是一套开发出来的完整的操作系统,也就是说,内核,系统类库,
+ 还有实用应用程序(如 &man.ls.1;,&man.cat.1;,&man.cp.1; 等)
+ 全部被做为一个整体一起开发并释出。这就是被认为归属于
+ <quote>基本</quote>系统的程序。用户安装的程序并不是
+ <quote>基本</quote>系统的一部分,如
+ <application>Apache</application>,<application>X11</application>,
+ <application>Moazilla&nbsp;Firefox</application>,等等。这
+ 些用户安装的应用程序通常是使用 &os; 的 Packages 和 Ports
+ 套件安装上去的。为了将这些程序和 <quote>基本</quote>
+ 系统区分开来,用户安装的应用程序通常被安装到
+ <filename>/usr/local/</filename>下。
+ 因此用户安装的二进制执行文件存在于
+ <filename>/usr/local/bin</filename>下,配置文件在
+ <filename>/usr/local/etc</filename>下,以此类推。</para>
+ </sidebar>
+
+ <para>您可以通过在
+ <filename>/etc/rc.conf</filename>(&man.rc.conf.5;)
+ 文件中增加与之对应的
+ <literal>ServiceName_enable="YES"</literal>
+ 配置来启用服务。 看一下系统默认的
+ <filename>/etc/defaults/rc.conf</filename> 文件, 这些默认配置可以使用
+ <filename>/etc/rc.conf</filename> 文件来改变。 因此,
+ 当安装附加应用程序时最好回顾下文档来决定到底该如何启用任何相关的服务。</para>
+
+ <para>下面的一小段内容用来在 <filename>/etc/rc.conf</filename>
+ 中启用 &man.sshd.8; 和 <application>Apache 2.2</application>。
+ 还指定了 <application>Apache</application> 应该通过
+ SSL 方式启动。</para>
+
+ <programlisting># enable SSHD
+sshd_enable="YES"
+# enable Apache with SSL
+apache22_enable="YES"
+apache22_flags="-DSSL"</programlisting>
+
+ <para>一旦服务已经在 <filename>/etc/rc.conf</filename>
+ 中启用,服务将能够从命令行启动(不需要重新启动系统):</para>
+
+ <screen>&prompt.root; <userinput>/etc/rc.d/sshd start</userinput></screen>
+
+ <para>如果服务还没有被启用,可以使用
+ <option>forcestart</option> 来从命令行启动:</para>
+
+ <screen>&prompt.root; <userinput>/etc/rc.d/sshd forcestart</userinput></screen>
+ </sect1>
+
+ <sect1 xml:id="network">
+ <title>网络配置</title>
+
+ <sect2 xml:id="interfaces">
+ <title>网络接口</title>
+
+ <para>代替 &linux; 中所使用的标识网络接口所常用的
+ <emphasis>ethX</emphasis> 格式的是,&os;
+ 使用驱动名字后跟一个数字来标识。下面
+ &man.ifconfig.8; 的输出显示了两个 &intel;&nbsp;Pro&nbsp;1000
+ 的网络接口(<filename>em0</filename> 和 <filename>em1</filename>):</para>
+
+ <screen>&prompt.user; <userinput>ifconfig</userinput>
+em0: flags=8843&lt;UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST&gt; mtu 1500
+ options=b&lt;RXCSUM,TXCSUM,VLAN_MTU&gt;
+ inet 10.10.10.100 netmask 0xffffff00 broadcast 10.10.10.255
+ ether 00:50:56:a7:70:b2
+ media: Ethernet autoselect (1000baseTX &lt;full-duplex&gt;)
+ status: active
+em1: flags=8843&lt;UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST&gt; mtu 1500
+ options=b&lt;RXCSUM,TXCSUM,VLAN_MTU&gt;
+ inet 192.168.10.222 netmask 0xffffff00 broadcast 192.168.10.255
+ ether 00:50:56:a7:03:2b
+ media: Ethernet autoselect (1000baseTX &lt;full-duplex&gt;)
+ status: active</screen>
+ </sect2>
+
+ <sect2 xml:id="ipaddress">
+ <title>IP配置</title>
+
+ <para>一个 IP 地址可以使用 &man.ifconfig.8;
+ 来指定到一个网络接口。通常,要保持重启后依然能够使用的
+ IP 配置信息需要包含在 <filename>/etc/rc.conf</filename>
+ 中。下列例子指定了主机名,IP 地址,以及默认网关:</para>
+
+ <programlisting>hostname="server1.example.com"
+ifconfig_em0="inet 10.10.10.100 netmask 255.255.255.0"
+defaultrouter="10.10.10.1"</programlisting>
+
+ <para>使用下面内容来为网络接口配置DHCP:</para>
+
+ <programlisting>hostname="server1.example.com"
+ifconfig_em0="DHCP"</programlisting>
+
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="firewall">
+ <title>防火墙</title>
+
+ <para>像 &linux; 中的 <application>IPTABLES</application>
+ 一样, &os; 也提供了一个内核级的防火墙;
+ 实际上 &os; 提供了三个防火墙:</para>
+
+ <itemizedlist>
+ <listitem><simpara><link xlink:href="&url.base;/doc/en_US.ISO8859-1/books/handbook/firewalls-ipfw.html">IPFIREWALL</link></simpara></listitem>
+ <listitem><simpara><link xlink:href="&url.base;/doc/en_US.ISO8859-1/books/handbook/firewalls-ipf.html">IPFILTER</link></simpara></listitem>
+ <listitem><simpara><link xlink:href="&url.base;/doc/en_US.ISO8859-1/books/handbook/firewalls-pf.html">PF</link></simpara></listitem>
+ </itemizedlist>
+
+ <para><application>IPFIREWALL</application> 或是
+ <application>IPFW</application>(管理
+ <application>IPFW</application> 规则的 &man.ipfw.8; 命令)
+ 是 &os; 开发者开发并维持的。
+ <application>IPFW</application> 能够与 &man.dummynet.4;
+ 配合使用来提供流量图形功能以及模拟不同网络连接类型的功能。</para>
+
+ <para>允许 <application>SSH</application>
+ 进入的 <application>IPFW</application> 规则样例如下:</para>
+
+ <programlisting>ipfw add allow tcp from any to me 22 in via $ext_if</programlisting>
+
+ <para><application>IPFILTER</application> 是
+ Darren&nbsp;Reed 所开发的防火墙程序。不是专门针对
+ &os; 的,它已经被移植到 NetBSD,OpenBSD,SunOS,HP/UX,
+ 还有Solaris等一些操作系统之上。</para>
+
+ <para>允许 <application>SSH</application>
+ 进入的 <application>IPFILTER</application>
+ 命令样例如下:</para>
+
+ <programlisting>pass in on $ext_if proto tcp from any to any port = 22</programlisting>
+
+ <para>最后一种防火墙程序,<application>PF</application>,
+ 是 OpenBSD 项目所开发的。<application>PF</application>
+ 是被作为 <application>IPFILTER</application>
+ 的一个替代品而被创建出的。就这点而言,
+ <application>PF</application> 的语法与
+ <application>IPFILTER</application> 的非常相似。
+ <application>PF</application> 可以与 &man.altq.4;
+ 配合来提供 QoS 的特性。</para>
+
+ <para>允许 <application>SSH</application>
+ 进入的 <application>PF</application>
+ 命令样例如下:</para>
+
+ <programlisting>pass in on $ext_if inet proto tcp from any to ($ext_if) port 22</programlisting>
+ </sect1>
+
+ <sect1 xml:id="updates">
+ <title>升级 &os;</title>
+
+ <para>共有三种方法来升级 &os; 系统:
+ 源码,二进制更新,还有安装光盘。</para>
+
+ <para>从源码升级是最复杂的升级方法,但是提供了最棒的总体灵活性。
+ 这个过程包含了使用 &os; <application>CVS</application>
+ (并行版本系统)来同步一个本地的 &os; 源代码。
+ 一旦本地源码已经更新到当前最新你便可以构建新版本的内核以及应用程序。
+ 关于源码更新的更多信息可见于 &os; 手册
+ <link xlink:href="&url.base;/doc/en_US.ISO8859-1/books/handbook/cutting-edge.html">
+ 关于如何更新操作系统的章节</link>。</para>
+
+ <para>二进制更新类似于使用 <command>yum</command> 或
+ <command>apt-get</command> 更新 &linux; 系统。
+ &man.freebsd-update.8; 命令会获取新的更新并安装它们。
+ 这些更新可以通过 &man.cron.8; 使用程序来调度。</para>
+
+ <note>
+ <para>如果你使用 &man.cron.8; 来预定更新,
+ 请确信在你的 &man.crontab.1; 中使用了
+ <command>freebsd-update cron</command>
+ 来控制大数目的机器同时获取更新。</para>
+
+ <programlisting>0 3 * * * root /usr/sbin/freebsd-update cron</programlisting>
+ </note>
+
+ <para>最后一种更新的方法,从安装光盘来升级,是个直接的过程。
+ 从安装光盘启动并选择该选项来更新。</para>
+ </sect1>
+
+ <sect1 xml:id="procfs">
+ <title>procfs:已是过去式但仍未被遗忘</title>
+
+ <para>&linux; 中,你可能会通过看一看
+ <filename>/proc/sys/net/ipv4/ip_forward</filename>
+ 来确定 IP 转发是否被启用。在 &os; 中你应该使用 &man.sysctl.8;
+ 来查看这和其他方面的系统设置,在当前的 &os; 版本中
+ &man.procfs.5; 已经不赞成使用了。(虽然
+ <command>sysctl</command>在 &os; 也同样可用。)</para>
+
+ <para>在 IP 转发样例中,你应该使用下列内容来确定 &os;
+ 系统中是否已经开启了 IP 转发:</para>
+
+ <screen>&prompt.user; <userinput>sysctl net.inet.ip.forwarding</userinput>
+net.inet.ip.forwarding: 0</screen>
+
+ <para><option>-a</option> 标志用来列出所有的系统设置:</para>
+
+ <screen>&prompt.user; <userinput>sysctl -a</userinput>
+kern.ostype: FreeBSD
+kern.osrelease: 6.2-RELEASE-p9
+kern.osrevision: 199506
+kern.version: FreeBSD 6.2-RELEASE-p9 #0: Thu Nov 29 04:07:33 UTC 2007
+ root@i386-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC
+
+kern.maxvnodes: 17517
+kern.maxproc: 1988
+kern.maxfiles: 3976
+kern.argmax: 262144
+kern.securelevel: -1
+kern.hostname: server1
+kern.hostid: 0
+kern.clockrate: { hz = 1000, tick = 1000, profhz = 666, stathz = 133 }
+kern.posix1version: 200112
+...</screen>
+
+ <note>
+ <para>某些 <command>sysctl</command> 的参数是只读的。</para>
+ </note>
+
+ <para>需要 procfs 的情况是,运行一些较老的软件,使用
+ &man.truss.1; 来跟踪系统信号,以及
+ <link xlink:href="&url.base;/doc/en_US.ISO8859-1/books/handbook/linuxemu.html">&linux; 二进制兼容</link>.
+ (尽管,&linux; 二进制兼容性使用其本身的 procfs,&man.linprocfs.5;。)
+ 如果你需要挂载 procfs 你可以在
+ <filename>/etc/fstab</filename> 中加入如下内容:</para>
+
+ <screen>proc /proc procfs rw,noauto 0 0</screen>
+
+ <note>
+ <para><option>noauto</option> 会防止
+ <filename>/proc</filename> 在启动时被自动挂载。</para>
+ </note>
+
+ <para>然后使用如下命令挂载 procfs:</para>
+
+ <screen>&prompt.root; <userinput>mount /proc</userinput></screen>
+ </sect1>
+
+ <sect1 xml:id="commands">
+ <title>常用命令</title>
+
+ <sect2 xml:id="packageCommands">
+ <title>软件包管理</title>
+
+ <para>
+ <informaltable frame="none" pgwide="1">
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>&linux; 命令 (Red&nbsp;Hat/Debian)</entry>
+ <entry>&os; 等价命令</entry>
+ <entry>目的</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><command>yum install package</command> / <command>apt-get install package</command></entry>
+ <entry><command>pkg_add -r package</command></entry>
+ <entry>从远程仓库安装 <replaceable>package</replaceable></entry>
+ </row>
+
+ <row>
+ <entry><command>rpm -ivh package</command> / <command>dpkg -i package</command></entry>
+ <entry><command>pkg_add -v package</command></entry>
+ <entry>安装 package</entry>
+ </row>
+
+ <row>
+ <entry><command>rpm -qa</command> / <command>dpkg -l</command></entry>
+ <entry><command>pkg_info</command></entry>
+ <entry>列出已安装的软件包</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </sect2>
+
+ <sect2 xml:id="systemCommands">
+ <title>系统管理</title>
+
+ <para>
+ <informaltable frame="none" pgwide="1">
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>&linux; 命令</entry>
+ <entry>&os; 等价命令</entry>
+ <entry>目的</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><command>lspci</command></entry>
+ <entry><command>pciconf</command></entry>
+ <entry>列出 PCI 设备</entry>
+ </row>
+
+ <row>
+ <entry><command>lsmod</command></entry>
+ <entry><command>kldstat</command></entry>
+ <entry>列出已载入的内核模块</entry>
+ </row>
+
+ <row>
+ <entry><command>modprobe</command></entry>
+ <entry><command>kldload</command> / <command>kldunload</command></entry>
+ <entry>载入/卸载内核模块</entry>
+ </row>
+
+ <row>
+ <entry><command>strace</command></entry>
+ <entry><command>truss</command></entry>
+ <entry>跟踪系统调用</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="conclusion">
+ <title>总结</title>
+
+ <para>非常希望这篇文档能够给予你足够的帮助来开始你的
+ &os; 之路。务必要再去看一下 <link xlink:href="&url.base;/doc/en_US.ISO8859-1/books/handbook/index.html">&os;&nbsp;手册</link>
+ 所提到的但并没有被包含在本文档中的那些更深入广泛的主题。</para>
+ </sect1>
+</article>
diff --git a/zh_CN.UTF-8/articles/nanobsd/Makefile b/zh_CN.UTF-8/articles/nanobsd/Makefile
new file mode 100644
index 0000000000..dcb5195f26
--- /dev/null
+++ b/zh_CN.UTF-8/articles/nanobsd/Makefile
@@ -0,0 +1,28 @@
+#
+# The FreeBSD Simplified Chinese Project
+#
+# Original Revision: 1.2
+# $FreeBSD$
+#
+# Article: Introduction to NanoBSD
+
+DOC?= article
+
+FORMATS?= html
+WITH_ARTICLE_TOC?= YES
+
+INSTALL_COMPRESSED?= gz
+INSTALL_ONLY_COMPRESSED?=
+
+# Images from the cross-document image library
+IMAGES_LIB= callouts/1.png
+IMAGES_LIB+= callouts/2.png
+IMAGES_LIB+= callouts/3.png
+IMAGES_LIB+= callouts/4.png
+
+SRCS= article.xml
+
+URL_RELPREFIX?= ../../../..
+DOC_PREFIX?= ${.CURDIR}/../../..
+
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_CN.UTF-8/articles/nanobsd/article.xml b/zh_CN.UTF-8/articles/nanobsd/article.xml
new file mode 100644
index 0000000000..c2f7554c5e
--- /dev/null
+++ b/zh_CN.UTF-8/articles/nanobsd/article.xml
@@ -0,0 +1,468 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
+<!--
+ The FreeBSD Documentation Project
+ The FreeBSD Chinese (Simplified) Documentation Project
+
+ Original Revision: 1.7
+-->
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_cn">
+ <info><title>NanoBSD 简介</title>
+
+
+ <authorgroup>
+ <author><personname><firstname>Daniel</firstname><surname>Gerzo</surname></personname></author>
+ </authorgroup>
+
+ <copyright>
+ <year>2006</year>
+ <holder>The FreeBSD Documentation Project</holder>
+ </copyright>
+
+ <pubdate>$FreeBSD$</pubdate>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+
+ <legalnotice xml:id="trademarks" role="trademarks">
+ &tm-attrib.freebsd;
+ &tm-attrib.general;
+ </legalnotice>
+
+ <abstract>
+ <para>这篇文档提供了关于 <application>NanoBSD</application> 工具的介绍信息,
+ 这一工具可以用来创建用于嵌入式应用的 &os; 系统映像,
+ 以适应存放到袖珍闪存 (Compact Flash) 卡 (或其它大容量存储介质) 上的需要。</para>
+ </abstract>
+ </info>
+
+ <sect1 xml:id="intro">
+ <title>NanoBSD 简介</title>
+
+ <indexterm><primary>NanoBSD</primary></indexterm>
+
+ <para><application>NanoBSD</application> 是 &a.phk; 目前正在开发的一项工具。
+ 它可以用来创建用于嵌入式应用的 &os; 系统映像,
+ 以便配合袖珍闪存 (Compact Flash) 卡 (或其他大容量存储介质) 使用。</para>
+
+ <para>这一工具也可以用来构建定制的安装映像,
+ 以简化通常称为 <quote>计算设备 (computer appliances)</quote>
+ 的系统的安装和维护工作。 计算设备通常在产品中将捆绑硬件和软件,
+ 或者换言之, 所有的应用程序都是预先装好的。
+ 这些设备可以直接插到暨存的网络中,
+ 并 (几乎是) 立即投入使用。</para>
+
+ <para><application>NanoBSD</application> 提供的功能包括:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>可以和 &os; 一样使用 Ports 和预编译包&mdash;
+ 所有的应用程序都可以在 <application>NanoBSD</application> 映像中直接使用,
+ 而方式与 &os; 完全一样。</para>
+ </listitem>
+
+ <listitem>
+ <para>不减少功能 &mdash; 能够使用 &os; 做的任何工作, 都可以在
+ <application>NanoBSD</application> 中使用,
+ 除非您在创建 <application>NanoBSD</application> 映像时,
+ 明确地删去它们。</para>
+ </listitem>
+
+ <listitem>
+ <para>所有对象在运行时均是只读的 &mdash; 可以安全地拔掉电源插销。
+ 在系统非正常关闭之后, 无需运行
+ &man.fsck.8;。</para>
+ </listitem>
+
+ <listitem>
+ <para>便于联编和定制 &mdash; 只需使用一个 shell 脚本和一个配置文件,
+ 您可以很容易地裁减和定制适于任意需求的映像。</para>
+ </listitem>
+ </itemizedlist>
+ </sect1>
+
+ <sect1 xml:id="howto">
+ <title>如何使用 NanoBSD</title>
+
+ <sect2 xml:id="design">
+ <title>NanoBSD 的设计</title>
+
+ <para>一旦将映像存入介质, 就可以用它来引导 <application>NanoBSD</application>
+ 了。 默认情况下, 大容量存储器会划分为三个区:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>两个映像区: <literal>code#1</literal>
+ 和 <literal>code#2</literal>。</para>
+ </listitem>
+
+ <listitem>
+ <para>一个配置文件区, 运行环境中,
+ 可以将其挂接到 <filename>/cfg</filename> 目录下。</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>这些分区默认情况下以只读方式挂接。</para>
+
+ <para><filename>/etc</filename> 和
+ <filename>/var</filename> 目录均为
+ &man.md.4; (malloc) 盘。</para>
+
+ <para>配置文件分区保存在
+ <filename>/cfg</filename> 目录。
+ 它包含了用于 <filename>/etc</filename>
+ 目录的文件, 在启动之后暂时以只读方式挂接。 因此,
+ 在需要从 <filename>/etc</filename> 向
+ <filename>/cfg</filename> 目录复制所进行的、
+ 希望在重启时保持不变的配置时, 需要进行一些额外的操作。</para>
+
+ <example>
+ <title>在 <filename>/etc/resolv.conf</filename> 中进行需要保持的修改</title>
+
+ <screen>&prompt.root; <userinput>vi /etc/resolv.conf</userinput>
+[...]
+&prompt.root; <userinput>mount /cfg</userinput>
+&prompt.root; <userinput>cp /etc/resolv.conf /cfg</userinput>
+&prompt.root; <userinput>umount /cfg</userinput></screen>
+ </example>
+
+ <note>
+ <para>只有在系统启动过程中, 以及需要修改配置文件的场合, 才需要挂接包含
+ <filename>/cfg</filename> 的那个分区。</para>
+
+ <para>在任何时候都保持挂接 <filename>/cfg</filename>
+ 不是一个好主意, 特别是当您把 <application>NanoBSD</application>
+ 放在不适合进行大量写操作的分区时
+ (由于文件系统的同步进程会定期向系统盘写一些数据)。</para>
+ </note>
+ </sect2>
+
+ <sect2>
+ <title>构建 NanoBSD 映像</title>
+
+ <para><application>NanoBSD</application> 映像是通过使用非常简单的
+ <filename>nanobsd.sh</filename> shell 脚本来构建的, 这个脚本可以在
+ <filename>/usr/src/tools/tools/nanobsd</filename>
+ 目录中找到。 这个脚本建立的映像文件, 可以用 &man.dd.1; 工具复制到存储介质上。</para>
+
+ <para>构建
+ <application>NanoBSD</application> 映像所需的命令是:</para>
+
+ <screen>&prompt.root; <userinput>cd /usr/src/tools/tools/nanobsd</userinput> <co xml:id="nbsd-cd"/>
+&prompt.root; <userinput>sh nanobsd.sh</userinput> <co xml:id="nbsd-sh"/>
+&prompt.root; <userinput>cd /usr/obj/nanobsd.full</userinput> <co xml:id="nbsd-cd2"/>
+&prompt.root; <userinput>dd if=_.disk.full of=/dev/da0 bs=64k</userinput> <co xml:id="nbsd-dd"/></screen>
+
+ <calloutlist>
+ <callout arearefs="nbsd-cd">
+ <para>进入 <application>NanoBSD</application> 构建脚本的主目录。</para>
+ </callout>
+
+ <callout arearefs="nbsd-sh">
+ <para>开始构建过程。</para>
+ </callout>
+
+ <callout arearefs="nbsd-cd2">
+ <para>进入构建好的映像文件所在的目录。</para>
+ </callout>
+
+ <callout arearefs="nbsd-dd">
+ <para>在存储介质上安装 <application>NanoBSD</application>。</para>
+ </callout>
+ </calloutlist>
+ </sect2>
+
+ <sect2>
+ <title>定制 NanoBSD 映像</title>
+
+ <para>这可能是 <application>NanoBSD</application> 最为重要,
+ 同时也是您最感兴趣的功能。 同时, 您在开发
+ <application>NanoBSD</application> 应用时,
+ 这也是相当耗时的过程。</para>
+
+ <para>执行下面的命令将使
+ <filename>nanobsd.sh</filename> 从当前目录中的
+ <filename>myconf.nano</filename> 文件读取配置:</para>
+
+ <screen>&prompt.root; <userinput>sh nanobsd.sh -c myconf.nano</userinput></screen>
+
+ <para>定制过程包含两步:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>配置选项</para>
+ </listitem>
+
+ <listitem>
+ <para>定制函数</para>
+ </listitem>
+ </itemizedlist>
+
+ <sect3>
+ <title>配置选项</title>
+
+ <para>通过对配置进行设置, 可以配置用以传递给
+ <application>NanoBSD</application> 构建过程中
+ <buildtarget>buildworld</buildtarget>
+ 和 <buildtarget>installworld</buildtarget> 阶段的联编和安装选项, 以及
+ <application>NanoBSD</application> 的主构建过程中的选项。
+ 通过使用这些选项可以削减系统的尺寸, 使之能够放入
+ 64MB 的存储。 您还可以进一步通过这些选项来削减 &os;,
+ 直到它只包含内核以及两三个用户环境文件为止。</para>
+
+ <para>配置文件中包含用以代替默认值的配置选项。
+ 最重要的语句包括:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>NANO_NAME</literal> &mdash; 本次构建的名称
+ (用于创建工作目录的名字)。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>NANO_SRC</literal> &mdash; 用以联编和构建映像的源码树的位置。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>NANO_KERNEL</literal> &mdash; 用以联编内核的配置文件的名字。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>CONF_BUILD</literal> &mdash; 用于传递给
+ <buildtarget>buildworld</buildtarget> 构建阶段的选项。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>CONF_INSTALL</literal> &mdash; 用于传递给
+ <buildtarget>installworld</buildtarget> 构建阶段的选项。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>CONF_WORLD</literal> &mdash; 用以传递给
+ <buildtarget>buildworld</buildtarget> 和
+ <buildtarget>installworld</buildtarget> 这两个构建阶段的选项。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>FlashDevice</literal> &mdash; 定义所用的介质类型。
+ 要了解进一步的细节, 请参考 <filename>FlashDevice.sub</filename>
+ 文件。</para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+
+ <sect3>
+ <title>定制函数</title>
+
+ <para>通过在配置文件中使用 shell 函数可以进一步微调
+ <application>NanoBSD</application>。 下面的例子展示了定制函数的基本模式:</para>
+
+ <programlisting>cust_foo () (
+ echo "bar=baz" &gt; \
+ &dollar;{NANO_WORLDDIR}/etc/foo
+)
+customize_cmd cust_foo</programlisting>
+
+ <para>下面是一个更贴近实际的例子, 它将默认的
+ <filename>/etc</filename> 目录尺寸,
+ 从 5MB 调整为 30MB:</para>
+
+ <programlisting>cust_etc_size () (
+ cd &dollar;{NANO_WORLDDIR}/conf
+ echo 30000 &gt; default/etc/md_size
+)
+customize_cmd cust_etc_size</programlisting>
+
+ <para>除此之外, 还有几个默认的预定义定制函数:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>cust_comconsole</literal> &mdash; 在 VGA 设备上禁止
+ &man.getty.8;
+ (<filename>/dev/ttyv*</filename> 设备节点) 并启用串口 COM1
+ 作为系统控制台。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>cust_allow_ssh_root</literal> &mdash; 允许
+ <systemitem class="username">root</systemitem> 通过 &man.sshd.8; 登录。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>cust_install_files</literal> &mdash;
+ 从 <filename>nanobsd/Files</filename>
+ 目录中安装文件, 这包含一些实用的系统管理脚本。</para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+
+ <sect3>
+ <title>安装预编译软件包</title>
+
+ <para>通过增加自定义的函数, 可以在 <application>NanoBSD</application>
+ 增加预编译的软件包。 下面的函数会添加位于
+ <filename>/usr/src/tools/tools/nanobsd/packages</filename>
+ 的全部预编译软件包:</para>
+
+ <programlisting>install_packages () (
+mkdir -p ${NANO_WORLDDIR}/packages
+cp /usr/src/tools/tools/nanobsd/packages/* ${NANO_WORLDDIR}/packages
+chroot ${NANO_WORLDDIR} sh -c 'cd packages; pkg_add -v *;cd ..;'
+rm -rf ${NANO_WORLDDIR}/packages
+)
+customize_cmd install_packages</programlisting>
+ </sect3>
+
+ <sect3>
+ <title>配置文件举例</title>
+
+ <para>下面是一个用于构建定制的 <application>NanoBSD</application> 映像的完整例子:</para>
+
+ <programlisting>NANO_NAME=custom
+NANO_SRC=/usr/src
+NANO_KERNEL=MYKERNEL
+NANO_IMAGES=2
+
+CONF_BUILD='
+NO_KLDLOAD=YES
+NO_NETGRAPH=YES
+NO_PAM=YES
+'
+
+CONF_INSTALL='
+NO_ACPI=YES
+NO_BLUETOOTH=YES
+NO_CVS=YES
+NO_FORTRAN=YES
+NO_HTML=YES
+NO_LPR=YES
+NO_MAN=YES
+NO_SENDMAIL=YES
+NO_SHAREDOCS=YES
+NO_EXAMPLES=YES
+NO_INSTALLLIB=YES
+NO_CALENDAR=YES
+NO_MISC=YES
+NO_SHARE=YES
+'
+
+CONF_WORLD='
+NO_BIND=YES
+NO_MODULES=YES
+NO_KERBEROS=YES
+NO_GAMES=YES
+NO_RESCUE=YES
+NO_LOCALES=YES
+NO_SYSCONS=YES
+NO_INFO=YES
+'
+
+FlashDevice SanDisk 1G
+
+cust_nobeastie() (
+ touch &dollar;{NANO_WORLDDIR}/boot/loader.conf
+ echo "beastie_disable=\"YES\"" &gt;&gt; &dollar;{NANO_WORLDDIR}/boot/loader.conf
+)
+
+customize_cmd cust_comconsole
+customize_cmd cust_install_files
+customize_cmd cust_allow_ssh_root
+customize_cmd cust_nobeastie</programlisting>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>更新 NanoBSD</title>
+
+ <para>更新 <application>NanoBSD</application> 相对而言较为简单:</para>
+
+ <procedure>
+ <step>
+ <para>和之前一样构建新的 <application>NanoBSD</application> 映像文件。</para>
+ </step>
+
+ <step>
+ <para>将新的映像放入正运行的
+ <application>NanoBSD</application> 设备中的一个未用的分区。</para>
+
+ <para>与之前最初安装 <application>NanoBSD</application> 的步骤相比,
+ 这一步骤最重要的区别在于这次不应使用 <filename>_.disk.full</filename> 文件
+ (它包含整个盘的映像),
+ 而应安装 <filename>_.disk.image</filename> 映像 (这个文件中,
+ 只包含一个系统分区)。</para>
+ </step>
+
+ <step>
+ <para>重新启动, 并从新安装的分区中启动系统。</para>
+ </step>
+
+ <step>
+ <para>如果一切顺利的话, 升级工作就完成了。</para>
+ </step>
+
+ <step>
+ <para>如果发生了任何问题, 则可以从先前的分区启动
+ (其中包含了旧的、 可用的映像), 来尽可能快地恢复系统功能。
+ 接下来可以修正新联编的版本中存在的问题, 并重复前述步骤。</para>
+ </step>
+ </procedure>
+
+ <para>要在正在运行的
+ <application>NanoBSD</application> 系统中安装新的映像, 可以使用位于
+ <filename>/root</filename> 目录的
+ <filename>updatep1</filename> 或
+ <filename>updatep2</filename> 脚本,
+ 具体使用哪一个脚本, 取决于正在运行的系统位于那个分区。</para>
+
+ <para>随时提供新 <application>NanoBSD</application> 映像所提供的服务,
+ 以及采用的传输方法的不同, 您可以参考并使用下列三种方式之一:</para>
+
+ <sect3>
+ <title>使用 &man.ftp.1;</title>
+
+ <para>如果传输速度是第一要务,
+ 采用下面的例子:</para>
+
+ <screen>&prompt.root; <userinput>ftp myhost
+get _.disk.image "| sh updatep1"</userinput></screen>
+ </sect3>
+
+ <sect3>
+ <title>使用 &man.ssh.1;</title>
+
+ <para>如果更倾向于安全传输, 应参考下面的例子:</para>
+
+ <screen>&prompt.root; <userinput>ssh myhost cat _.disk.image.gz | zcat | sh updatep1</userinput></screen>
+ </sect3>
+
+ <sect3>
+ <title>使用 &man.nc.1;</title>
+
+ <para>如果远程主机既不提供
+ &man.ftp.1; 服务, 也不提供 &man.sshd.8; 服务:</para>
+
+ <procedure>
+ <step>
+ <para>开始时, 在提供映像的主机上开启 TCP 监听,
+ 并令其将映像文件发给客户机:</para>
+
+ <screen>myhost&prompt.root; <userinput>nc -l 2222 &lt; _.disk.image</userinput></screen>
+
+ <note>
+ <para>请确认您所使用的端口没有通过防火墙阻止来自
+ <application>NanoBSD</application> 客户机的联接请求。</para>
+ </note>
+ </step>
+ <step>
+ <para>连接到提供新映像服务的主机, 并执行
+ <filename>updatep1</filename> 脚本:</para>
+
+ <screen>&prompt.root; <userinput>nc myhost 2222 | sh updatep1</userinput></screen>
+ </step>
+ </procedure>
+ </sect3>
+ </sect2>
+ </sect1>
+
+ <index/>
+</article>
diff --git a/zh_CN.UTF-8/articles/rc-scripting/Makefile b/zh_CN.UTF-8/articles/rc-scripting/Makefile
new file mode 100644
index 0000000000..6ac2a1559d
--- /dev/null
+++ b/zh_CN.UTF-8/articles/rc-scripting/Makefile
@@ -0,0 +1,33 @@
+#
+# $FreeBSD$
+# Original Revision: 1.2
+# Article: Practical rc.d scripting in BSD
+
+DOC?= article
+
+FORMATS?= html
+WITH_ARTICLE_TOC?= YES
+
+INSTALL_COMPRESSED?= gz
+INSTALL_ONLY_COMPRESSED?=
+
+SRCS= article.xml
+
+IMAGES_LIB+= callouts/1.png
+IMAGES_LIB+= callouts/2.png
+IMAGES_LIB+= callouts/3.png
+IMAGES_LIB+= callouts/4.png
+IMAGES_LIB+= callouts/5.png
+IMAGES_LIB+= callouts/6.png
+IMAGES_LIB+= callouts/7.png
+IMAGES_LIB+= callouts/8.png
+IMAGES_LIB+= callouts/9.png
+IMAGES_LIB+= callouts/10.png
+IMAGES_LIB+= callouts/11.png
+IMAGES_LIB+= callouts/12.png
+IMAGES_LIB+= callouts/13.png
+IMAGES_LIB+= callouts/14.png
+
+URL_RELPREFIX?= ../../../..
+DOC_PREFIX?= ${.CURDIR}/../../..
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_CN.UTF-8/articles/rc-scripting/article.xml b/zh_CN.UTF-8/articles/rc-scripting/article.xml
new file mode 100644
index 0000000000..8714b75920
--- /dev/null
+++ b/zh_CN.UTF-8/articles/rc-scripting/article.xml
@@ -0,0 +1,1219 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
+<!--
+ The FreeBSD Documentation Project
+ The FreeBSD Chinese (Simplified) Documentation Project
+
+ Original Revision: 1.14
+-->
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_cn">
+ <info><title>BSD rc.d脚本编程实战</title>
+
+
+ <author><personname><firstname>Yar</firstname><surname>Tikhiy</surname></personname><affiliation>
+ <address><email>yar@FreeBSD.org</email></address>
+ </affiliation></author>
+
+ <copyright>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2012</year>
+
+ <holder>The FreeBSD Project</holder>
+ </copyright>
+
+ <pubdate>$FreeBSD$</pubdate>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+
+ <legalnotice xml:id="trademarks" role="trademarks">
+ &tm-attrib.freebsd;
+ &tm-attrib.netbsd;
+ &tm-attrib.general;
+ </legalnotice>
+
+ <abstract>
+ <para>初学者可能会发现,难以通过正式的文档,
+ 基于 BSD 的 <filename>rc.d</filename>
+ 框架,编写一些实际任务的 <filename>rc.d</filename> 脚本。
+ 本文中,我们采用了一些复杂性不断增加的典型案例,
+ 来展示适合每个案例的 <filename>rc.d</filename> 特性,
+ 并探讨其中的工作原理。
+ 这样的实验为大家进一步研究设计有效的
+ <filename>rc.d</filename> 应用程序提供了一些参考点。</para>
+ </abstract>
+ </info>
+
+ <sect1 xml:id="rcng-intro">
+ <title>简介</title>
+
+ <para>历史上 BSD 曾有过一个单一的启动脚本,
+ <filename>/etc/rc</filename>。 该脚本在系统启动的时候被
+ &man.init.8; 程序所引导,并执行所有多用户操作所需求的用户级任务:
+ 检查并挂载文件系统,设置网络,启动守护进程,等等。
+ 在每个系统中实际的任务清单也并不相同;
+ 管理员需要根据需求自定义这样的任务清单。在一些特殊的情况中,
+ 还不得不去修改 <filename>/etc/rc</filename> 文件,
+ 一些真正的黑客乐此不疲。</para>
+
+ <para>单一脚本启动方法的真正问题是它没有提供对从
+ <filename>/etc/rc</filename> 启动的单个组件的控制。
+ 拿一个例子来说吧,<filename>/etc/rc</filename>
+ 不能够重新启动某个单独的守护进程。
+ 系统管理员不得不手动找出守护进程,并杀掉它,
+ 等待它真正退出后,再通过浏览 <filename>/etc/rc</filename>
+ 得到该守护进程的标识,最终输入全部命令来再次启动守护进程。
+ 如果重新启动的服务包括不止一个守护进程或需要更多动作的话,
+ 该任务将变得更加困难以及容易出错。简而言之,
+ 单一脚本在实现我们这样的目的上是不成功的:
+ 让系统管理员的生活更轻松。</para>
+
+ <para>再后来,为了将最重要的一些子系统独立出来,
+ 便尝试将部分的内容从 <filename>/etc/rc</filename> 分离出来了。
+ 最广为人知的例子就是用来启动联网的 <filename>/etc/netstart</filename>
+ 文件。它容许从单用户模式访问网络,
+ 但由于它的部分代码需要和一些与联网完全无关的动作交互,
+ 所以它并没有完美地结合到自启动的进程中。那便是为何
+ <filename>/etc/netstart</filename> 被演变成
+ <filename>/etc/rc.network</filename> 的原因了。
+ 后者不再是一个普通的脚本;它包括了庞大的,由
+ <filename>/etc/rc</filename> 在不同的系统启动级别中调用的凌乱的
+ &man.sh.1; 函数。然而,当启动任务变得多样化以及久经更改,
+ <quote>类模块化</quote> 方法变得比曾经的整体
+ <filename>/etc/rc</filename> 更缓慢费事。</para>
+
+ <para>由于没有一个干净和易于设计的框架,
+ 启动脚本不得不全力更改以满足飞速开发中基于 BSD 的操作系统的需求。
+ 它逐渐变得明朗并经过许多必要的步骤最终变成一个具有细密性和扩展性的
+ <filename>rc</filename> 系统。BSD <filename>rc.d</filename>
+ 就这样诞生了。Luke Mewburn 和 NetBSD 社区是公认的
+ <filename>rc.d</filename> 之父。再之后它被引入到了 &os; 中。
+ 它的名字引用为系统单独的服务脚本的位置,也就是
+ <filename>/etc/rc.d</filename>下面的那些脚本。
+ 之后我们将学习到更多的 <filename>rc.d</filename>
+ 系统的组件并看看单个脚本是如何被调用的。</para>
+
+ <para>BSD <filename>rc.d</filename>
+ 背后的基本理念是 <emphasis>良好</emphasis> 的模块化和代码重用性。
+ <emphasis>良好</emphasis> 的模块化意味着每个基本
+ <quote>服务</quote> 就象系统守护进程或原始启动任务那样,
+ 通过属于它们的可启动该服务的 &man.sh.1; 脚本,来停止服务,
+ 重载服务,检查服务的状态。具体动作由脚本的命令行参数所决定。
+ <filename>/etc/rc</filename> 脚本仍然掌管着系统的启动,
+ 但现在它仅仅是使用 <option>start</option> 参数来一个个调用那些小的脚本。
+ 这便于用 <option>stop</option> 来对运行中的同样的脚本很好地执行停止任务,
+ 这是被 <filename>/etc/rc.shutdown</filename>
+ 脚本所完成的。看,这是多么好地体现了 Unix 的哲学:
+ 拥有一组小的专用的工具,每个工具尽可能好地完成自己的任务。
+ <emphasis>代码重用</emphasis> 意味着所有的通用操作由
+ <filename>/etc/rc.subr</filename> 中的一些 &man.sh.1; 函数所实现。
+ 现在一个典型的脚本只需要寥寥几行的 &man.sh.1; 代码。最终,
+ &man.rcorder.8; 成为了 <filename>rc.d</filename> 框架中重要的一部分,
+ 它用来帮助 <filename>/etc/rc</filename>
+ 处理小脚本之间的依赖关系并有次序地运行它们。它同样帮助
+ <filename>/etc/rc.shutdown</filename> 做类似的事情,
+ 因为正确的关闭次序是相对于启动的次序的。</para>
+
+ <para>BSD <filename>rc.d</filename> 的设计在
+ <link linkend="lukem"> Luke Mewburn 的原文 </link> 中有记录,
+ 以及 <filename>rc.d</filename> 组件也被充分详细地记录在各自的
+ <link linkend="manpages">联机手册</link> 中。然而,
+ 它可能没能清晰展现给一个 <filename>rc.d</filename>
+ 新手,如何将无数的块和片进行关联来为具体的任务创建一个好风格的脚本。
+ 因此本文将试着以不同的方式来讲述 <filename>rc.d</filename>。
+ 它将展示在某些典型情况中应该使用哪些特性,并阐述了为何如此。
+ 注意这并不是一篇 how-to 文档,我们的目的不是给出现成的配方,
+ 而是在展示一些简单的进入 <filename>rc.d</filename> 的范围的门路。
+ 本文也不是相关联机手册的替代品。
+ 阅读本文时记得同时参考联机手册以获取更完整正规的文档。</para>
+
+ <para>理解本文需要一些先决条件。首先,你需要熟悉
+ &man.sh.1; 脚本编程语言以掌握 <filename>rc.d</filename>,
+ 还有,你需要知道系统是如何执行用户级的启动和停止任务,这些在
+ &man.rc.8; 中都有说明。</para>
+
+ <para>本文关注的是 <filename>rc.d</filename> 的 &os; 分支。
+ 不过,它可能对 NetBSD 的开发者也同样有用,因为 BSD
+ <filename>rc.d</filename> 的两个分支不只是共享了同样的设计,
+ 还保留了对脚本编写者都可见的类似观点。</para>
+ </sect1>
+
+ <sect1 xml:id="rcng-task">
+ <title>任务描述</title>
+
+ <para>在开始打开 <envar>$EDITOR</envar>(编辑器)
+ 之前进行小小的思考不是坏事。为了给一个系统服务写一个
+ <quote>听话的</quote> <filename>rc.d</filename> 脚本,
+ 我们首先应该能回答以下问题:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>该服务是必须性的还是可选性的?</para>
+ </listitem>
+
+ <listitem>
+ <para>脚本将为单个程序服务,如一个守护进程,还是执行更复杂的动作?</para>
+ </listitem>
+
+ <listitem>
+ <para>我们的服务依赖哪些服务?反过来哪些服务依赖我们的服务?</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>从下面的例子中我们将看到,为什么说知道这些问题的答案是很重要的。</para>
+ </sect1>
+
+ <sect1 xml:id="rcng-dummy">
+ <title>虚拟的脚本</title>
+
+ <para>下面的脚本是用来在每次系统启动时发出一个信息:</para>
+
+ <informalexample>
+ <programlisting>#!/bin/sh<co xml:id="rcng-dummy-shebang"/>
+
+. /etc/rc.subr<co xml:id="rcng-dummy-include"/>
+
+name="dummy"<co xml:id="rcng-dummy-name"/>
+start_cmd="${name}_start"<co xml:id="rcng-dummy-startcmd"/>
+stop_cmd=":"<co xml:id="rcng-dummy-stopcmd"/>
+
+dummy_start()<co xml:id="rcng-dummy-startfn"/>
+{
+ echo "Nothing started."
+}
+
+load_rc_config $name<co xml:id="rcng-dummy-loadconfig"/>
+run_rc_command "$1"<co xml:id="rcng-dummy-runcommand"/></programlisting>
+ </informalexample>
+
+ <para>需要注意的是:</para>
+
+ <calloutlist>
+ <callout arearefs="rcng-dummy-shebang">
+ <para>一个解释性的脚本应该以一行魔幻的
+ <quote>shebang</quote> 行开头。
+ 该行指定了脚本的解析程序。由于 shebang 行的作用,
+ 假如再有可执行位的设置,
+ 脚本就能象一个二进制程序一样被精确地调用执行。
+ (请参考 &man.chmod.1;。) 例如,
+ 一个系统管理员可以从命令行手动运行我们的脚本:</para>
+
+ <screen>&prompt.root; <userinput>/etc/rc.d/dummy start</userinput></screen>
+
+ <note>
+ <para>为了使 <filename>rc.d</filename> 框架正确地管理脚本,
+ 它的脚本需要用 &man.sh.1; 语言编写。
+ 如果你的某个服务或 port 套件使用了二进制控制程序或是用其它语言编写的例程,
+ 请将其组件安装到 <filename>/usr/sbin</filename>(相对于系统)
+ 或 <filename>/usr/local/sbin</filename>(相对于ports),
+ 然后从合适的 <filename>rc.d</filename> 目录的某个
+ &man.sh.1; 脚本调用它。</para>
+ </note>
+
+ <tip>
+ <para>如果你想知道为什么 <filename>rc.d</filename>
+ 脚本必须用 &man.sh.1; 语言编写的细节,先看下
+ <filename>/etc/rc</filename> 是如何依靠
+ <function>run_rc_script</function> 调用它们,
+ 然后再去学习 <filename>/etc/rc.subr</filename>
+ 下 <function>run_rc_script</function>
+ 的相关实现。</para>
+ </tip>
+ </callout>
+
+ <callout arearefs="rcng-dummy-include">
+ <para>在 <filename>/etc/rc.subr</filename> 下,
+ 有许多定义过的 &man.sh.1; 函数可供每个
+ <filename>rc.d</filename> 脚本使用。这些函数在
+ &man.rc.subr.8; 中都有说明。尽管理论上可以完全不使用
+ &man.rc.subr.8; 来编写一个 <filename>rc.d</filename>
+ 脚本,但它的函数已经证明了它真的很方便,
+ 并且能使任务更加的简单。所以所有人在编写
+ <filename>rc.d</filename> 脚本时都会求助于
+ &man.rc.subr.8; 也不足为奇了。当然我们也不例外。</para>
+
+ <para>一个 <filename>rc.d</filename> 脚本在其调用
+ &man.rc.subr.8; 函数之前必须先 <quote>source</quote>
+ <filename>/etc/rc.subr</filename>(用
+ <quote><command>.</command></quote>将其包含进去),
+ 而使 &man.sh.1; 程序有机会来获悉那些函数。
+ 首选风格是在脚本的最开始 source
+ <filename>/etc/rc.subr</filename> 文件。</para>
+
+ <note>
+ <para>某些有用的与联网有关的函数由另一个被包含进来的文件提供,
+ <filename>/etc/network.subr</filename> 文件。</para>
+ </note>
+ </callout>
+
+ <callout arearefs="rcng-dummy-name">
+ <para><anchor xml:id="name-var"/>强制的变量
+ <envar>name</envar> 指定我们脚本的名字。
+ 这是 &man.rc.subr.8; 所强调的。也就是,
+ 每个 <filename>rc.d</filename> 脚本在调用
+ &man.rc.subr.8; 的函数之前必须设置
+ <envar>name</envar> 变量。</para>
+
+ <para>现在是时候来为我们的脚本一次性选择一个独一无二的名字了。
+ 在编写这个脚本的时我们将在许多地方用到它。在开始之前,
+ 我们来给脚本文件也取个相同的名字。</para>
+
+ <note>
+ <para>当前的 <filename>rc.d</filename>
+ 脚本风格是把值放在双引号中来给变量赋值。
+ 请记住这只是个风格问题,可能并不总是这样。
+ 你可以在只是简单的并不包括 &man.sh.1;
+ 元字符的词句中放心地省略掉引号,
+ 而在某些情况下你将需要使用单引号以防止
+ &man.sh.1; 对任何的变量的解释。
+ 程序员是可以灵巧地由风格惯例获悉其语法以及使用的。
+ </para>
+ </note>
+ </callout>
+
+ <callout arearefs="rcng-dummy-startcmd">
+ <para>&man.rc.subr.8; 背后主要的构思是
+ <filename>rc.d</filename> 脚本提供处理程序,或者方法,来让
+ &man.rc.subr.8; 调用。特别是,<option>start</option>,
+ <option>stop</option>,以及其它的 <filename>rc.d</filename>
+ 脚本参数都是这样被处理的。方法是存储在一个以
+ <envar><replaceable>argument_cmd</replaceable></envar>
+ 形式命名的变量中的 &man.sh.1; 表达式,该
+ <replaceable>argument</replaceable>
+ 对应着脚本命令行中所特别指定的参数。我们稍后将看到
+ &man.rc.subr.8; 是如何为标准参数提供默认方法的。</para>
+
+ <note>
+ <para>为了让 <filename>rc.d</filename> 中的代码更加统一,
+ 常见的是在任何适合的地方都使用 <envar>${name}</envar> 形式。
+ 这样一来,可以轻松地将一些代码从一个脚本拷贝到另一个中使用。</para>
+ </note>
+ </callout>
+
+ <callout arearefs="rcng-dummy-stopcmd">
+ <para>我们应谨记 &man.rc.subr.8; 为标准参数提供了默认的方法。
+ 因此,如果希望它什么都不做的话,我们必须使用无操作的
+ &man.sh.1; 表达式来改写标准的方法。</para>
+ </callout>
+
+ <callout arearefs="rcng-dummy-startfn">
+ <para>比较复杂的方法主体可以用函数来实现。
+ 在能够保证函数名有意义的情况下,这是个很不错的想法。</para>
+
+ <important>
+ <para>强烈推荐给我们脚本中所定义的所有函数名都添加类似
+ <envar>${name}</envar> 这样的前缀,以使它们永远不会和
+ &man.rc.subr.8; 或其它公用包含文件中的函数冲突。</para>
+ </important>
+ </callout>
+
+ <callout arearefs="rcng-dummy-loadconfig">
+ <para>这是在请求 &man.rc.subr.8; 载入 &man.rc.conf.5; 变量。
+ 尽管我们这个脚本中使用的变量并没有被其它地方使用,但由于
+ &man.rc.subr.8; 自身所控制着的 &man.rc.conf.5;
+ 变量存在的原因,仍然推荐脚本去装载 &man.rc.conf.5;。</para>
+ </callout>
+
+ <callout arearefs="rcng-dummy-runcommand">
+ <para>通常这是 <filename>rc.d</filename> 脚本的最后一个命令。
+ 它调用 &man.rc.subr.8;
+ 体系使用我们脚本所提供的变量和方法来执行相应的请求动作。</para>
+ </callout>
+ </calloutlist>
+ </sect1>
+
+ <sect1 xml:id="rcng-confdummy">
+ <title>可配置的虚拟脚本</title>
+
+ <para>现在我们来给我们的虚拟脚本增加一些控制参数吧。正如你所知,
+ <filename>rc.d</filename> 脚本是由 &man.rc.conf.5; 所控制的。
+ 幸运的是,&man.rc.subr.8; 隐藏了所有复杂化的东西。
+ 下面这个脚本使用 &man.rc.conf.5; 通过 &man.rc.subr.8;
+ 来查看它是否在第一个地方被启用,并获取一条信息在启动时显示。
+ 事实上这两个任务是相互独立的。一方面,<filename>rc.d</filename>
+ 脚本要能够支持启动和禁用它的服务。另一方面,
+ <filename>rc.d</filename> 脚本必须能具备配置信息变量。
+ 我们将通过下面同一脚本来演示这两方面的内容:</para>
+
+ <informalexample>
+ <programlisting>#!/bin/sh
+
+. /etc/rc.subr
+
+name=dummy
+rcvar=dummy_enable<co xml:id="rcng-confdummy-rcvar"/>
+
+start_cmd="${name}_start"
+stop_cmd=":"
+
+load_rc_config $name<co xml:id="rcng-confdummy-loadconfig"/>
+eval "${rcvar}=\${${rcvar}:-'NO'}"<co xml:id="rcng-confdummy-enable"/>
+dummy_msg=${dummy_msg:-"Nothing started."}<co xml:id="rcng-confdummy-opt"/>
+
+dummy_start()
+{
+ echo "$dummy_msg"<co xml:id="rcng-confdummy-msg"/>
+}
+
+run_rc_command "$1"</programlisting>
+ </informalexample>
+
+ <para>在这个样例中改变了什么?</para>
+
+ <calloutlist>
+ <callout arearefs="rcng-confdummy-rcvar">
+ <para>变量 <envar>rcvar</envar> 指定了 ON/OFF
+ 开关变量的名字。</para>
+ </callout>
+
+ <callout arearefs="rcng-confdummy-loadconfig">
+ <para>现在 <function>load_rc_config</function> 在任何
+ &man.rc.conf.5; 变量被访问之前就在脚本中被预先调用。</para>
+
+ <note>
+ <para>检查 <filename>rc.d</filename> 脚本时,切记 &man.sh.1;
+ 会把函数延迟到其被调用时才对其中的表达式进行求值运算。
+ 因此尽可能晚地在 <function>run_rc_command</function>
+ 之前调用 <function>load_rc_config</function>,
+ 以及仍然访问从方法函数输出到
+ <function>run_rc_command</function> 的 &man.rc.conf.5;
+ 变量并不是一个错误。这是因为方法函数将在
+ <function>load_rc_config</function> <emphasis>之后</emphasis>,
+ 被调用的 <function>run_rc_command</function> 调用。</para>
+ </note>
+ </callout>
+
+ <callout arearefs="rcng-confdummy-enable">
+ <para>如果自身设置了 <envar>rcvar</envar>,
+ 但指示开关变量却未被设置,那么 <function>run_rc_command</function>
+ 将发出一个警告。如果你的 <filename>rc.d</filename>
+ 脚本是为基本系统所用的,你应当在
+ <filename>/etc/defaults/rc.conf</filename>
+ 中给开关变量添加一个默认的设置并将其标注在 &man.rc.conf.5; 中。
+ 否则的话你的脚本应该给开关变量提供一个默认设置。
+ 范例中演示了一个可移植接近于后者情况的案例。</para>
+
+ <note>
+ <para>你可以通过将开关变量设置为 ON 来使 &man.rc.subr.8; 有效,
+ 使用 <literal>one</literal> 或 <literal>force</literal>
+ 为脚本的参数加前缀,如 <literal>onestart</literal> 或
+ <literal>forcestop</literal> 这样,会忽略其当前的设置。
+ 切记 <literal>force</literal>
+ 在我们下面要提到的情况下有额外的危险后果,那就是当用
+ <literal>one</literal> 改写了 ON/OFF 开关变量。例如,
+ 假定 <envar>dummy_enable</envar> 是 <literal>OFF</literal>
+ 的,而下面的命令将忽略系统设置而强行运行
+ <option>start</option>方法:</para>
+
+ <screen>&prompt.root; <userinput>/etc/rc.d/dummy onestart</userinput></screen>
+ </note>
+ </callout>
+
+ <callout arearefs="rcng-confdummy-opt">
+ <para>现在启动时显示的信息不再是硬编码在脚本中的了。
+ 它是由一个命名为 <envar>dummy_msg</envar> 的
+ &man.rc.conf.5; 变量所指定的。这就是 &man.rc.conf.5;
+ 变量如何来控制 <filename>rc.d</filename>
+ 脚本的一个小例子。</para>
+
+ <important>
+ <para>我们的脚本所独占使用的所有 &man.rc.conf.5; 变量名,
+ 都必须具有同样的前缀:<envar>${name}</envar>。
+ 例如:<envar>dummy_mode</envar>,
+ <envar>dummy_state_file</envar>,等等。</para>
+ </important>
+
+ <note>
+ <para>当可以内部使用一个简短的名字时,如 <envar>msg</envar>
+ 这样,为我们的脚本所引进的全部的共用名添加唯一的前缀
+ <envar>${name}</envar>,能够避免我们与 &man.rc.subr.8;
+ 命名空间冲突的可能。</para>
+
+ <para>只要一个 &man.rc.conf.5; 变量与其内部等同值是相同的,
+ 我们就能够使用一个更加兼容的表达式来设置默认值:</para>
+
+ <programlisting>: ${dummy_msg:="Nothing started."}</programlisting>
+
+ <para>尽管目前的风格是使用了更详细的形式。</para>
+
+ <para>通常,基本系统的 <filename>rc.d</filename>
+ 脚本不需要为它们的 &man.rc.conf.5; 变量提供默认值,
+ 因为默认值应该是在 <filename>/etc/defaults/rc.conf</filename>
+ 设置过了。但另一方面,为 ports 所用的 <filename>rc.d</filename>
+ 脚本应提供如范例所示的默认设置。</para>
+ </note>
+ </callout>
+
+ <callout arearefs="rcng-confdummy-msg">
+ <para>这里我们使用 <envar>dummy_msg</envar>
+ 来实际地控制我们的脚本,即,发一个变量信息。</para>
+ </callout>
+ </calloutlist>
+ </sect1>
+
+ <sect1 xml:id="rcng-daemon">
+ <title>启动并停止简单守护进程</title>
+
+ <para>我们早先说过 &man.rc.subr.8; 是能够提供默认方法的。
+ 显然,这些默认方法并不是太通用的。
+ 它们都是适用于大多数情况下来启动和停止一个简单的守护进程况。
+ 我们来假设现在需要为一个叫做 <command>mumbled</command>
+ 的守护进程编写一个 <filename>rc.d</filename>脚本,
+ 在这里:</para>
+
+ <informalexample>
+ <programlisting>#!/bin/sh
+
+. /etc/rc.subr
+
+name=mumbled
+rcvar=mumbled_enable
+
+command="/usr/sbin/${name}"<co xml:id="rcng-daemon-basic-cmd"/>
+
+load_rc_config $name
+run_rc_command "$1"</programlisting>
+ </informalexample>
+
+ <para>感到很简单吧,不是么?我们来检查下我们这个小脚本。
+ 只需要注意下面的这些新知识点:</para>
+
+ <calloutlist>
+ <callout arearefs="rcng-daemon-basic-cmd">
+ <para>这个 <envar>command</envar> 变量对于
+ &man.rc.subr.8; 来说是有意义的。当它被设置时,
+ &man.rc.subr.8; 将根据提供传统守护进程的情形而生效。
+ 特别是,将为这些参数提供默认的方法:
+ <option>start</option>,<option>stop</option>,
+ <option>restart</option>,<option>poll</option>,
+ 以及 <option>status</option>。</para>
+
+ <para>该守护进程将会由运行中的 <envar>$command</envar>
+ 配合由 <envar>$mumbled_flags</envar> 所指定的命令行标帜来启动。
+ 因此,对默认的 <option>start</option> 方法来说,
+ 所有的输入数据在我们脚本变量集合中都可用。与
+ <option>start</option> 不同的是,
+ 其他方法可能需要与进程启动相关的额外信息。举个例子,
+ <option>stop</option> 必须知道进程的 PID 号来终结进程。
+ 在目前的情况中,&man.rc.subr.8; 将扫描全部进程的清单,
+ 查找一个名字等同于 <envar>$procname</envar> 的进程。
+ 后者是另一个对 &man.rc.subr.8; 有意义的变量,
+ 并且默认它的值跟 <envar>command</envar> 一样。
+ 换而言之,当我们给 <envar>command</envar> 设置值后,
+ <envar>procname</envar> 实际上也设置了同样的值。
+ 这启动我们的脚本来杀死守护进程并检查它是否正在第一个位置运行。</para>
+
+ <note>
+ <para>某些程序实际上是可执行的脚本。
+ 系统启动脚本的解释器以传递脚本名为命令行参数的形式来运行脚本。
+ 然后被映射到进程列表中,这会使 &man.rc.subr.8; 迷惑。因此,当
+ <envar>$command</envar> 是一个脚本的时,你应该额外地设置
+ <envar>command_interpreter</envar> 来让 &man.rc.subr.8;
+ 知晓进程的实际名字。</para>
+
+ <para>对每个 <filename>rc.d</filename> 脚本而言,
+ 有一个可选的 &man.rc.conf.5; 变量给
+ <envar>command</envar> 指示其优先级。
+ 它的名字是下面这样的形式:<envar>${name}_program</envar>,
+ <envar>name</envar> 是我们 <link linkend="name-var">之前</link>
+ 讨论过的必须性变量。如,在这个案例中它应该命名为
+ <envar>emumbled_program</envar>。这其实是 &man.rc.subr.8;
+ 分配 <envar>${name}_program</envar> 来改写
+ <envar>command</envar> 的。</para>
+
+ <para>当然,即使 <envar>command</envar> 未被设置,
+ &man.sh.1; 也将允许你从 &man.rc.conf.5; 或自身来设置
+ <envar>${name}_program</envar>。在那种情况下,
+ <envar>${name}_program</envar> 的特定属性丢失了,
+ 并且它成为了一个能供你的脚本用于其自身目的的普通变量。
+ 然而,单独使用 <envar>${name}_program</envar>
+ 是并不是我们所寄望的,因为同时使用它和 <envar>command</envar>
+ 已成为了 <filename>rc.d</filename> 脚本编程的一个惯用的约定。</para>
+ </note>
+
+ <para>关于默认方法的更详细的信息,请参考
+ &man.rc.subr.8;。</para>
+ </callout>
+ </calloutlist>
+ </sect1>
+
+ <sect1 xml:id="rcng-daemon-adv">
+ <title>启动并停止高级守护进程</title>
+
+ <para>我们来给之前的 <quote>骨架</quote>
+ 脚本加点 <quote>血肉</quote>,并让它更复杂更富有特性吧。
+ 默认的方法已能够为我们做很好的工作了,
+ 但是我们可能会需要它们一些方面的调整。
+ 现在我们将学习如何调整默认方法来符合我们的需要。</para>
+
+ <informalexample>
+ <programlisting>#!/bin/sh
+
+. /etc/rc.subr
+
+name=mumbled
+rcvar=mumbled_enable
+
+command="/usr/sbin/${name}"
+command_args="mock arguments &gt; /dev/null 2&gt;&amp;1"<co xml:id="rcng-daemon-adv-args"/>
+
+pidfile="/var/run/${name}.pid"<co xml:id="rcng-daemon-adv-pid"/>
+
+required_files="/etc/${name}.conf /usr/share/misc/${name}.rules"<co xml:id="rcng-daemon-adv-reqfiles"/>
+
+sig_reload="USR1"<co xml:id="rcng-daemon-adv-sig"/>
+
+start_precmd="${name}_prestart"<co xml:id="rcng-daemon-adv-precmd"/>
+stop_postcmd="echo Bye-bye"<co xml:id="rcng-daemon-adv-postcmd"/>
+
+extra_commands="reload plugh xyzzy"<co xml:id="rcng-daemon-adv-extra"/>
+
+plugh_cmd="mumbled_plugh"<co xml:id="rcng-daemon-adv-methods"/>
+xyzzy_cmd="echo 'Nothing happens.'"
+
+mumbled_prestart()
+{
+ if checkyesno mumbled_smart; then<co xml:id="rcng-daemon-adv-yn"/>
+ rc_flags="-o smart ${rc_flags}"<co xml:id="rcng-daemon-adv-rcflags"/>
+ fi
+ case "$mumbled_mode" in
+ foo)
+ rc_flags="-frotz ${rc_flags}"
+ ;;
+ bar)
+ rc_flags="-baz ${rc_flags}"
+ ;;
+ *)
+ warn "Invalid value for mumbled_mode"<co xml:id="rcng-daemon-adv-warn"/>
+ return 1<co xml:id="rcng-daemon-adv-preret"/>
+ ;;
+ esac
+ run_rc_command xyzzy<co xml:id="rcng-daemon-adv-run"/>
+ return 0
+}
+
+mumbled_plugh()<co xml:id="rcng-daemon-adv-plugh"/>
+{
+ echo 'A hollow voice says "plugh".'
+}
+
+load_rc_config $name
+run_rc_command "$1"</programlisting>
+ </informalexample>
+
+ <calloutlist>
+ <callout arearefs="rcng-daemon-adv-args">
+ <para>附加给 <envar>$command</envar> 的参数在
+ <envar>command_args</envar> 中进行传递。它们在
+ <envar>$mumbled_flags</envar> 之后将被添加到命令行。
+ 其实际的执行便是此后最终的命令行传递给
+ <command>eval</command> 运算,输入和输出以及重定向都可以在
+ <envar>command_args</envar> 中指定。</para>
+
+ <note>
+ <para><emphasis>永远不要</emphasis> 在
+ <envar>command_args</envar> 包含破折号选项,
+ 类似 <option>-X</option> 或 <option>--foo</option>
+ 这样的。<envar>command_args</envar>
+ 的内容将出现在最终命令行的末尾,因此它们可能是紧接在
+ <envar>${name}_flags</envar> 中所列出的参数后面;
+ 但大多的命令将不能识别出普通参数后的破折号选项。
+ 更好的传递附加给 <envar>$command</envar>
+ 的选项的方式是添加它们到 <envar>${name}_flags</envar>
+ 的起始处。另一种方法是像后文所示的那样来修改
+ <envar>rc_flags</envar>。</para>
+ </note>
+ </callout>
+
+ <callout arearefs="rcng-daemon-adv-pid">
+ <para>一个得体的守护进程会创建一个
+ <emphasis>pidfile</emphasis> 进程文件,
+ 以使其进程能够更容易更可靠地被找到。如果设置了
+ <envar>pidfile</envar> 变量,告诉 &man.rc.subr.8;
+ 哪里能找到供其默认方法所使用的
+ <envar>pidfile</envar> 进程文件。</para>
+
+ <note>
+ <para>事实上,&man.rc.subr.8;
+ 在启动一个守护进程前还会使用 pidfile
+ 进程文件来查看它是否已经在运行。使用了
+ <option>faststart</option> 参数可以跳过这个检查步骤。</para>
+ </note>
+ </callout>
+
+ <callout arearefs="rcng-daemon-adv-reqfiles">
+ <para>如果守护进程只有在确定的文件存在的情况下才可以运行,
+ 那就将它们列到 <envar>required_files</envar> 中,而
+ &man.rc.subr.8; 将在启动守护进程之前检查那些文件是否存在。
+ 还有相关的分别用来检查目录和环境变量的
+ <envar>required_dirs</envar> 和 <envar>required_vars</envar>
+ 可供使用。它们都在 &man.rc.subr.8; 中有详细的说明。</para>
+
+ <note>
+ <para>来自 &man.rc.subr.8; 的默认方法,通过使用
+ <option>forcestart</option> 作为脚本的参数,
+ 可以强制性地跳过预先需要的检查。</para>
+ </note>
+ </callout>
+
+ <callout arearefs="rcng-daemon-adv-sig">
+ <para>我们可以在守护进程有异常的时候,自定义发送给守护进程的信号。
+ 特别是,<envar>sig_reload</envar>
+ 指定了使守护进程重新装载其配置的信号;默认情况也就是
+ <symbol>SIGHUP</symbol> 信号。
+ 另一个信号是发送给守护进程以停止该进程;默认情况下是
+ <symbol>SIGTERM</symbol> 信号,但这是可以通过设置
+ <envar>sig_stop</envar> 来进行适当更改的。</para>
+
+ <note>
+ <para>信号名称应当以不包含 <literal>SIG</literal>
+ 前缀的形式指定给 &man.rc.subr.8;,就如范例中所示的那样。
+ &os; 版本的 &man.kill.1; 程序能够识别出
+ <literal>SIG</literal> 前缀,不过其它系统版本的就不一定了。</para>
+ </note>
+ </callout>
+
+ <callout arearefs="rcng-daemon-adv-precmd rcng-daemon-adv-postcmd">
+ <para>在默认的方法前面或后面执行附加任务是很容易的。
+ 对于我们脚本所支持的每条命令参数而言,我们可以定义
+ <envar><replaceable>argument</replaceable>_precmd</envar> 和
+ <envar><replaceable>argument</replaceable>_postcmd</envar>
+ 来完成。这些 &man.sh.1; 命令分别在它们各自的方法前后被调用,
+ 显然,从它们各自的名字就能看出来。</para>
+
+ <note>
+ <para>如果我们需要的话,用自定义的
+ <envar><replaceable>argument</replaceable>_cmd</envar>
+ 改写默认的方法,并不妨碍我们仍然使用
+ <envar><replaceable>argument</replaceable>_precmd</envar> 和
+ <envar><replaceable>argument</replaceable>_postcmd</envar>。
+ 特别是,前者便于检查自定义的方法,
+ 以及执行自身命令之前所遇到更严密的条件。于是,将
+ <envar><replaceable>argument</replaceable>_precmd</envar> 和
+ <envar><replaceable>argument</replaceable>_cmd</envar>
+ 一起使用,使我们合理地将检查从动作中独立了出来。</para>
+
+ <para>别忘了你可以将任意的有效的 &man.sh.1;
+ 表达式插入到方法和你定义的 pre- 与 post-commands 命令中。
+ 在大部分情况下,调用函数使实际任务有好的风格,
+ 但千万不要让风格限制了你对其幕后到底是怎么回事的思考。</para>
+ </note>
+ </callout>
+
+ <callout arearefs="rcng-daemon-adv-extra">
+ <para>如果我们愿意实现一些自定义参数,
+ 这些参数也可被认作为我们脚本的 <emphasis>命令</emphasis>,我们需要在
+ <envar>extra_commands</envar> 中将它们列出并提供方法以处理它们。</para>
+
+ <note>
+ <para><option>reload</option> 是个特别的命令。一方面,
+ 它有一个在 &man.rc.subr.8; 中预置的方法。另一方面,
+ <option>reload</option> 命令默认是不被提供的。
+ 理由是并非所有的守护进程都使用同样的重载方法,
+ 并且有些守护进程根本没有任何东西可重载的。所以显而易见,
+ 我们需要去询问都提供了哪些的内建功能。我们可以通过
+ <envar>extra_commands</envar> 来这样做。</para>
+
+ <para>我们从 <option>reload</option> 的默认方法得到了什么呢?
+ 守护进程常常在收到一个信号后重新载入它们的配置 &mdash;
+ 一般来说,也就是 <symbol>SIGHUP</symbol> 信号。因此
+ &man.rc.subr.8; 尝试发送一个信号给守护进程来重载它。
+ 该信号一般预设为 <symbol>SIGHUP</symbol>,
+ 但是如果必要的话可以通过 <envar>sig_reload</envar>
+ 变量来自定义它。</para>
+ </note>
+ </callout>
+
+ <callout arearefs="rcng-daemon-adv-methods rcng-daemon-adv-plugh">
+ <para>我们的脚本提供了两个非标准的命令,
+ <option>plugh</option> 和 <option>xyzzy</option>。
+ 我们看到它们在 <envar>extra_commands</envar> 中被列出来了,
+ 并且现在是时候给它们提供方法了。<option>xyzzy</option>
+ 的方法是内联的而 <option>plugh</option> 的是以
+ <function>mumbled_plugh</function> 形式完成的函数。</para>
+
+ <para>非标准命令在启动或停止的时候不被调用。
+ 通常它们是为了系统管理员的方便。它们还能被其它的子系统所使用,
+ 例如,&man.devd.8;,前提是 &man.devd.conf.5; 中已经指定了。</para>
+
+ <para>全部可用命令的列表,当脚本不加参数地调用时,在
+ &man.rc.subr.8; 打印出的使用方法中能够找到。例如,
+ 这就是供学习的脚本用法的内容:</para>
+
+ <screen>&prompt.root; <userinput>/etc/rc.d/mumbled</userinput>
+Usage: /etc/rc.d/mumbled [fast|force|one](start|stop|restart|rcvar|reload|plugh|xyzzy|status|poll)</screen>
+ </callout>
+
+ <callout arearefs="rcng-daemon-adv-run">
+ <para>如果脚本需要的话,它可以调用自己的标准或非标准的命令。
+ 这可能看起来有点像函数的调用,但我们知道,命令和 shell
+ 函数并非一直都是同样的东西。举个例子,<command>xyzzy</command>
+ 在这里不是以函数来实现的。另外,还有应该被有序调用的
+ pre-command 预置命令和 post-command 后置命令。
+ 所以脚本运行自己命令的合适方式就是利用 &man.rc.subr.8;,
+ 就像范例中展示的那样。</para>
+ </callout>
+
+ <callout arearefs="rcng-daemon-adv-yn">
+ <para>&man.rc.subr.8; 提供了一个方便的函数叫做
+ <function>checkyesno</function>。
+ 它以一个变量名作为参数并返回一个为零的退出值,
+ 当且仅当该变量设置为 <literal>YES</literal>,或
+ <literal>TRUE</literal>,或 <literal>ON</literal>,或
+ <literal>1</literal>,区分大小写;否则返回一个非零的退出值。
+ 在第二种情况中,函数测试变量的设置为 <literal>NO</literal>,
+ <literal>FALSE</literal>,<literal>OFF</literal>,或
+ <literal>0</literal>,区分大小写;
+ 如果变量包含别的内容的话它打印一条警告信息,例如,垃圾。</para>
+
+ <para>切记对 &man.sh.1; 而言零值意味着真而非零值意味着假。</para>
+
+ <important>
+ <para><function>checkyesno</function> 函数使用一个
+ <emphasis>变量名</emphasis>。不要扩大含义将变量的
+ <emphasis>值</emphasis> 传递给它;
+ 否则它不会如你预期那样的工作。</para>
+
+ <para>下面是 <function>checkyesno</function>
+ 的合理使用范围:</para>
+
+ <programlisting>if checkyesno mumbled_enable; then
+ foo
+fi</programlisting>
+
+ <para>相反地,以下面的方式调用 <function>checkyesno</function>
+ 是不会工作的 -- 至少是不会如你预期的那样:</para>
+
+ <programlisting>if checkyesno "${mumbled_enable}"; then
+ foo
+fi</programlisting>
+ </important>
+ </callout>
+
+ <callout arearefs="rcng-daemon-adv-rcflags">
+ <para>我们可以通过修改 <envar>$start_precmd</envar> 中的
+ <envar>rc_flags</envar> 来影响传递到
+ <envar>$command</envar> 的标帜。</para>
+ </callout>
+
+ <callout arearefs="rcng-daemon-adv-warn">
+ <para>某种情况下我们可能需要发出一条重要的信息,那样的话
+ <application>syslog</application> 可以很好地记录日志。
+ 这可以使用下列 &man.rc.subr.8; 函数来轻松完成:
+ <function>debug</function>,<function>info</function>,
+ <function>warn</function>,以及 <function>err</function>。
+ 后者以指定的代码值退出脚本。</para>
+ </callout>
+
+ <callout arearefs="rcng-daemon-adv-preret">
+ <para>方法的退出值和它们的 pre-commands 预命令不只是默认被忽略掉。如果
+ <envar><replaceable>argument</replaceable>_precmd</envar>
+ 返回了一个非零退出值,主方法将不会被执行。依次地是,
+ <envar><replaceable>argument</replaceable>_postcmd</envar>
+ 将不会被调用,除非主方法返回的是一个为零的退出值。</para>
+
+ <note>
+ <para>然而,当给一个参数使用 <literal>force</literal>
+ 前缀的时候,如 <option>forcestart</option>,&man.rc.subr.8;
+ 会听从命令行指示而忽略那些退出值最后仍然调用所有的命令。</para>
+ </note>
+ </callout>
+ </calloutlist>
+ </sect1>
+
+ <sect1 xml:id="rcng-hookup">
+ <title>链接脚本到 rc.d 框架</title>
+
+ <para>当编写好了一个脚本,它需要被整合到 <filename>rc.d</filename> 中去。
+ 一个重要的步骤就是安装脚本到 <filename>/etc/rc.d</filename>
+ (对基本系统而言)或 <filename>/usr/local/etc/rc.d</filename>
+ (对ports而言)中去。在 &lt;<filename>bsd.prog.mk</filename>&gt; 和
+ &lt;<filename>bsd.port.mk</filename>&gt; 中都为此提供了方便的接口,
+ 通常你不必担心适当的所有权限和模式。系统脚本应当是通过可以在
+ <filename>src/etc/rc.d</filename> 找到的 <filename>Makefile</filename>
+ 安装的。Port 脚本可以像
+ <link xlink:href="&url.books.porters-handbook;/rc-scripts.html">Porter's Handbook</link>
+ 中描述那样通过使用 <varname>USE_RC_SUBR</varname> 来被安装。</para>
+
+ <para>不过,我们应该预先考虑到我们脚本在系统启动顺序中的位置。
+ 我们的脚本所处理的服务可能依赖于其它的服务。举个例子,
+ 没有网络接口和路由选择的启用运行的话,一个网络守护进程是不起作用的。
+ 即使一个服务看似什么都不需要,在基本文件系统检查挂载完毕之前也很难启动。</para>
+
+ <para>之前我们曾提到过 &man.rcorder.8;。现在是时候来密切地关注下它了。
+ 笼统地说,&man.rcorder.8; 处理一组文件,检验它们的内容,
+ 并从文件集合打印一个文件列表的依赖顺序到 <varname>stdout</varname>
+ 标准输出。这点是用于保持文件内部的依赖信息,
+ 而每个文件只能说明自己的依赖。一个文件可以指定如下信息:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>它 <emphasis>提供</emphasis> 的 <quote>条件</quote>
+ 的名字(意味着我们服务的名字);</para>
+ </listitem>
+
+ <listitem>
+ <para>它 <emphasis>需求</emphasis> 的
+ <quote>条件</quote> 的名字;</para>
+ </listitem>
+
+ <listitem>
+ <para>应该 <emphasis>先</emphasis> 运行的文件的
+ <quote>条件</quote>的名字;</para>
+ </listitem>
+
+ <listitem>
+ <para>能用于从全部文件集合中选择一个子集的额外
+ <emphasis>关键字</emphasis>( &man.rcorder.8;
+ 可通过选项而被指定来包括或省去由特殊关键字所列出的文件。)</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>并不奇怪的是,&man.rcorder.8; 只能处理接近 &man.sh.1;
+ 语法的文本文件。&man.rcorder.8; 所解读的特殊行看起来类似
+ &man.sh.1; 的注释。这种特殊文本行的语法相当严格地简化了其处理。
+ 请查阅 &man.rcorder.8; 以获取更详细的信息。</para>
+
+ <para>除使用 &man.rcorder.8; 的特殊行以外,
+ 脚本可以坚持将其依赖的其它服务强制性启动。当其它服务是可选的,
+ 并因系统管理员错误地在 &man.rc.conf.5;
+ 中禁用掉该服务而使其不能自行启动时,会需要这一点。</para>
+
+ <para>将这些谨记在心,我们来考虑下简单结合了依赖信息增强的守护进程脚本:</para>
+
+ <informalexample>
+ <programlisting>#!/bin/sh
+
+# PROVIDE: mumbled oldmumble <co xml:id="rcng-hookup-provide"/>
+# REQUIRE: DAEMON cleanvar frotz<co xml:id="rcng-hookup-require"/>
+# BEFORE: LOGIN<co xml:id="rcng-hookup-before"/>
+# KEYWORD: nojail shutdown<co xml:id="rcng-hookup-keyword"/>
+
+. /etc/rc.subr
+
+name=mumbled
+rcvar=mumbled_enable
+
+command="/usr/sbin/${name}"
+start_precmd="${name}_prestart"
+
+mumbled_prestart()
+{
+ if ! checkyesno frotz_enable &amp;&amp; \
+ ! /etc/rc.d/frotz forcestatus 1&gt;/dev/null 2&gt;&amp;1; then
+ force_depend frotz || return 1<co xml:id="rcng-hookup-force"/>
+ fi
+ return 0
+}
+
+load_rc_config $name
+run_rc_command "$1"</programlisting>
+ </informalexample>
+
+ <para>跟前面一样,做如下详细分析:</para>
+
+ <calloutlist>
+ <callout arearefs="rcng-hookup-provide">
+ <para>该行声明了我们脚本所提供的 <quote>条件</quote> 的名字。
+ 现在其它脚本可以用那些名字来标明我们脚本的依赖。</para>
+
+ <note>
+ <para>通常脚本指定一个单独的已提供的条件。然而,
+ 并没有什么妨碍我们从列出的那些条件中指定,例如,
+ 为了兼容性的目的。</para>
+
+ <para>在其它情况,主要的名称,或者说唯一的,
+ <literal>PROVIDE:</literal> 条件应该与
+ <envar>${name}</envar> 相同。</para>
+ </note>
+ </callout>
+
+ <callout arearefs="rcng-hookup-require rcng-hookup-before">
+ <para>因此我们的脚本指示了其依赖于别的脚本所提供的
+ <quote>条件</quote>。根据这些行的信息,脚本请示
+ &man.rcorder.8; 以将其放在一个或多个提供
+ <filename>DAEMON</filename> 和 <filename>cleanvar</filename>
+ 的脚本后面,但在提供 <filename>LOGIN</filename> 的脚本前面。</para>
+
+ <note>
+ <para><literal>BEFORE:</literal>
+ 这一行不可以在其它脚本不完整的依赖关系列表中滥用。
+ 适合使用 <literal>BEFORE:</literal>
+ 的情况是当其它脚本不关心我们的脚本,
+ 但是我们的脚本如果在另一个之前运行的话能够更好地执行任务。
+ 一个典型的实例是网络接口和防火墙:
+ 虽然接口不依赖防火墙来完成自己的工作,
+ 但是系统安全将因一切网络流量之前启动的防火墙而受益。</para>
+
+ <para>除了条件相对应的每个单独服务,脚本使用元条件和它们的
+ <quote>占位符</quote> 来保证某个操作组在其它之前被执行。
+ 这些是由 <filename>UPPERCASE</filename>
+ 大写名字所表示的。它们的列表和用法可以在 &man.rc.8; 中找到。</para>
+
+ <para>切记将一个服务名称放进 <literal>REQUIRE:</literal>
+ 行不能保证实际的服务会在我们的脚本启动的时候运行。
+ 所需求的服务可能会启动失败或在 &man.rc.conf.5; 中被禁掉了。
+ 显然,&man.rcorder.8; 是无法追踪这些细节的,并且
+ &man.rc.8; 也不会去追踪。所以,
+ 脚本启动的应用程序应当能够应付任何所需求的服务的不可用情况。
+ 某些情况下,我们可以用 <link linkend="forcedep">下面</link>
+ 所讨论的方式来协助脚本。</para>
+ </note>
+ </callout>
+
+ <callout arearefs="rcng-hookup-keyword">
+ <para><anchor xml:id="keywords"/>如我们从上述文字所记起的,&man.rcorder.8;
+ 关键字可以用来选择或省略某些脚本。即任何 &man.rcorder.8;
+ 用户可以通过指定 <option>-k</option> 和 <option>-s</option>
+ 选项来分别指定 <quote>保留清单(keep list)</quote> 和
+ <quote>跳过清单(skip list)</quote>。
+ 从全部文件到按依赖关系排列的清单,&man.rcorder.8;
+ 将只是挑出保留清单(除非是空的)
+ 中那些带关键字的以及从跳过清单中挑出不带关键字的文件。</para>
+
+ <para>在 &os; 中,&man.rcorder.8; 被
+ <filename>/etc/rc</filename> 和
+ <filename>/etc/rc.shutdown</filename> 所使用。
+ 这两个脚本定义了 &os; 中 <filename>rc.d</filename>
+ 关键字以及它们的意义的标准列表如下:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>nojail</literal></term>
+
+ <listitem>
+ <para>该服务不适用于 &man.jail.8; 环境。
+ 如果是在 jail 的内部的话,自动启动和关闭程序将忽略该脚本。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>nostart</literal></term>
+
+ <listitem>
+ <para>该服务只能手动启动否则将不会启动。
+ 自动启动程序将忽略此脚本。结合 <literal>shutdown</literal>
+ 关键字的话,这可以用来编写只在系统关闭时执行一些任务的脚本。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>shutdown</literal></term>
+
+ <listitem>
+ <para>这个关键字 <emphasis>明确</emphasis>
+ 地列出了需要在系统关闭前停止的服务。</para>
+
+ <note>
+ <para>当系统即将关闭的时候,
+ <filename>/etc/rc.shutdown</filename> 在运行。
+ 它假定认为大部分的 <filename>rc.d</filename>
+ 脚本在那刻什么都不做。因此,
+ <filename>/etc/rc.shutdown</filename>
+ 选择性地调用带有 <literal>shutdown</literal>
+ 关键字的 <filename>rc.d</filename> 脚本,
+ 有效地忽略其余的脚本。为了更快的关闭,
+ <filename>/etc/rc.shutdown</filename> 传递
+ <option>faststop</option> 命令给其运行的脚本,
+ 以跳过预置的检查,例如,进程文件 pidfile 的检查。
+ 正如依赖性服务应该在其所依赖的服务之前停止,
+ <filename>/etc/rc.shutdown</filename>
+ 以相反的依赖次序来运行这些脚本。</para>
+
+ <para>如果写一个真正的 <filename>rc.d</filename> 脚本的话,
+ 你应当考虑到其是否与系统关闭时有关系。例如,
+ 如果你的脚本只通过响应 <option>start</option>
+ 命令来运行任务,那么你不需要包含这个关键字。然而,
+ 如果你的脚本管理着一个服务,那么,在系统进入 &man.halt.8;
+ 中所描述的其本身关闭顺序的最终阶段之前停止该脚本,
+ 可能是个不错的主意。特别是,
+ 你显然是应该关闭一个需要相当长时间,
+ 或需要特定的动作才能干净地关闭的服务。
+ 数据库引擎就是这样一个典型的例子。</para>
+ </note>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </callout>
+
+ <callout arearefs="rcng-hookup-force">
+ <para><anchor xml:id="forcedep"/>以
+ <function>force_depend</function>
+ 起始的行应被用于更谨慎的情况。通常,用于修正相互关联的
+ <filename>rc.d</filename>
+ 脚本分层结构的配置文件时会更加稳妥。</para>
+
+ <para>如果你仍不能完成不含 <function>force_depend</function> 的脚本,
+ 范例提供了一个如何有条件地调用它的习惯用法。在范例中,我们的
+ <command>mumbled</command> 守护进程需求另一个以高级方式启动的进程,
+ <command>frotz</command>。但 <command>frotz</command> 也是可选的;
+ 而且 &man.rcorder.8; 对这些信息是一无所知的。幸运的是,
+ 我们的脚本已访问到全部的 &man.rc.conf.5; 变量。如果
+ <envar>frotz_enable</envar> 为真,我们希望的最好结果是依靠
+ <filename>rc.d</filename> 已经启动了 <command>frotz</command>。
+ 否则我们强制检查 <command>frotz</command> 的状态。最终,
+ 如果 <command>frotz</command> 依赖的服务没有找到或运行的话,
+ 我们将强制其运行。这时 <function>force_depend</function>
+ 将发出一条警告信息,因为它只应该在检查到配置信息丢失的情况下被调用。</para>
+ </callout>
+ </calloutlist>
+ </sect1>
+
+ <sect1 xml:id="rcng-args">
+ <title>给予 rc.d 脚本更多的灵活性</title>
+
+ <para>当进行启动或停止的调用时,<filename>rc.d</filename>
+ 脚本应该作用于其所负责的整个子系统。例如,
+ <filename>/etc/rc.d/netif</filename> 应该启动或停止
+ &man.rc.conf.5; 中所描述的全部网络接口。每个任务都唯一地听从一个如
+ <option>start</option> 或 <option>stop</option>
+ 这样的单独命令参数的指示。在启动和停止之间的时间,
+ <filename>rc.d</filename> 脚本帮助管理员控制运行中的系统,
+ 并其在需要的时候它将产生更多的灵活性和精确性。举个例子,
+ 管理员可能想在 &man.rc.conf.5; 中添加一个新网络接口的配置信息,
+ 然后在不妨碍其它已存在接口的情况下将其启动。
+ 在下次管理员可能需要关闭一个单独的网络接口。在魔幻的命令行中,
+ 对应的 <filename>rc.d</filename> 脚本调用一个额外的参数,
+ 网络接口名即可。</para>
+
+ <para>幸运的是,&man.rc.subr.8; 允许传递任意多(取决于系统限制)的参数给脚本的方法。
+ 由于这个原因,脚本自身的改变可以说是微乎其微。</para>
+
+ <para>&man.rc.subr.8; 如何访问到附加的命令行参数呢?直接获取么?
+ 并非是无所不用其极的。首先,&man.sh.1;
+ 函数没有访问到调用者的定位参数,而 &man.rc.subr.8;
+ 只是这些函数的容器。其次,<filename>rc.d</filename>
+ 指令的一个好的风格是由主函数来决定将哪些参数传递给它的方法。</para>
+
+ <para>所以 &man.rc.subr.8; 提供了如下的方法:
+ <function>run_rc_command</function>
+ 传递其所有参数但将第一个参数逐字传递到各自的方法。首先,
+ 发出以方法自身为名字的参数:<option>start</option>,
+ <option>stop</option>,等等。这会被
+ <function>run_rc_command</function> 移出,
+ 这样命令行中原本 <envar>$2</envar> 的内容将作为
+ <envar>$1</envar> 来提供给方法,等等。</para>
+
+ <para>为了说明这点,我们来修改原来的虚拟脚本,
+ 这样它的信息将取决于所提供的附加参数。从这里出发:</para>
+
+ <informalexample>
+ <programlisting>#!/bin/sh
+
+. /etc/rc.subr
+
+name="dummy"
+start_cmd="${name}_start"
+stop_cmd=":"
+kiss_cmd="${name}_kiss"
+extra_commands="kiss"
+
+dummy_start()
+{
+ if [ $# -gt 0 ]; then<co xml:id="rcng-args-start"/>
+ echo "Greeting message: $*"
+ else
+ echo "Nothing started."
+ fi
+}
+
+dummy_kiss()
+{
+ echo -n "A ghost gives you a kiss"
+ if [ $# -gt 0 ]; then<co xml:id="rcng-args-kiss"/>
+ echo -n " and whispers: $*"
+ fi
+ case "$*" in
+ *[.!?])
+ echo
+ ;;
+ *)
+ echo .
+ ;;
+ esac
+}
+
+load_rc_config $name
+run_rc_command "$@"<co xml:id="rcng-args-all"/></programlisting>
+ </informalexample>
+
+ <para>能注意到脚本里发生了那些实质性改变么?</para>
+
+ <calloutlist>
+ <callout arearefs="rcng-args-start">
+ <para>你输入的所有在 <option>start</option>
+ 之后的参数可以被当作各自方法的定位参数一样被终结。
+ 我们可以根据我们的任务、技巧和想法来以任何方式使用他们。
+ 在当前的例子中,我们只是以下行中字符串的形式传递参数给
+ &man.echo.1; 程序 &mdash; 注意 <envar>$*</envar>
+ 是有双引号的。这里是脚本如何被调用的:</para>
+
+ <screen>&prompt.root; <userinput>/etc/rc.d/dummy start</userinput>
+Nothing started.
+&prompt.root; <userinput>/etc/rc.d/dummy start Hello world!</userinput>
+Greeting message: Hello world!</screen>
+ </callout>
+
+ <callout arearefs="rcng-args-kiss">
+ <para>同样用于我们脚本提供的任何方法,并不仅限于标准的方法。
+ 我们已经添加了一个自定义的叫做 <option>kiss</option> 的方法,
+ 并且它给附加参数带来的戏耍决不亚于 <option>start</option>。
+ 例如:</para>
+
+ <screen>&prompt.root; <userinput>/etc/rc.d/dummy kiss</userinput>
+A ghost gives you a kiss.
+&prompt.root; <userinput>/etc/rc.d/dummy kiss Once I was Etaoin Shrdlu...</userinput>
+A ghost gives you a kiss and whispers: Once I was Etaoin Shrdlu...</screen>
+ </callout>
+
+ <callout arearefs="rcng-args-all">
+ <para>如果我们只是传递所有附加参数给任意的方法,
+ 我们只需要在脚本的最后一行我们调用
+ <function>run_rc_command</function> 的地方,
+ 用 <literal>"$@</literal> 代替 <literal>"$1"</literal> 即可。</para>
+
+ <important>
+ <para>一个 &man.sh.1; 程序员应该是可以理解
+ <envar>$*</envar> 和 <envar>$@</envar>
+ 的微妙区别只是指定全部定位参数的不同方法。
+ 关于此更深入的探讨,可以参考这个很好的 &man.sh.1;
+ 脚本编程手册。在你完全理解这些表达式的意义之前请不要使用它们,
+ 因为误用它们将给脚本引入缺陷和不安全的弊端。</para>
+ </important>
+
+ <note>
+ <para>现在 <function>run_rc_command</function> 可能有个缺陷,
+ 它将影响保持参数之间的原本边界。也就是,
+ 带有嵌入空白的参数可能不会被正确处理。该缺陷是由于对
+ <envar>$*</envar> 的误用。</para>
+ </note>
+ </callout>
+ </calloutlist>
+ </sect1>
+
+ <sect1 xml:id="rcng-furthur">
+ <title>进一步阅读</title>
+
+ <para><anchor xml:id="lukem"/><link xlink:href="http://www.mewburn.net/luke/papers/rc.d.pdf">
+ Luke Mewburn 的原始文章</link> 中讲述了
+ <filename>rc.d</filename> 的基本概要,
+ 并详细阐述了其设计方案的原理。该文章提供了深入了解整个
+ <filename>rc.d</filename> 框架以及其所在的现代 BSD
+ 操作系统的内容。</para>
+
+ <para><anchor xml:id="manpages"/>在 &man.rc.8;,&man.rc.subr.8;,
+ 还有 &man.rcorder.8; 的联机手册中,对
+ <filename>rc.d</filename> 组件做了非常详细的记载。
+ 在你写脚本时,如果不去学习和参考这些联机手册的话,
+ 你是无法完全发挥出 <filename>rc.d</filename> 的能量的。</para>
+
+ <para>工作中实际范例的主要来源就是运行的系统中的
+ <filename>/etc/rc.d</filename> 目录。
+ 它的内容可读性非常好,因为大部分的枯燥的内容都深藏在
+ &man.rc.subr.8; 中了。切记 <filename>/etc/rc.d</filename>
+ 的脚本也不是神仙写出来的,
+ 所以它们可能也存在着代码缺陷以及低级的设计方案。
+ 但现在你可以来改进它们了!</para>
+ </sect1>
+</article>
diff --git a/zh_CN.UTF-8/articles/remote-install/Makefile b/zh_CN.UTF-8/articles/remote-install/Makefile
new file mode 100644
index 0000000000..5fc385e414
--- /dev/null
+++ b/zh_CN.UTF-8/articles/remote-install/Makefile
@@ -0,0 +1,28 @@
+#
+# $FreeBSD$
+# Original Revision: 1.1
+#
+
+DOC?= article
+
+FORMATS?= html
+WITH_ARTICLE_TOC?= YES
+
+INSTALL_COMPRESSED?= gz
+INSTALL_ONLY_COMPRESSED?=
+
+SRCS= article.xml
+
+# Images from the cross-document image library
+IMAGES_LIB= callouts/1.png
+IMAGES_LIB+= callouts/2.png
+IMAGES_LIB+= callouts/3.png
+IMAGES_LIB+= callouts/4.png
+IMAGES_LIB+= callouts/5.png
+IMAGES_LIB+= callouts/6.png
+IMAGES_LIB+= callouts/7.png
+
+URL_RELPREFIX?= ../../../..
+DOC_PREFIX?= ${.CURDIR}/../../..
+
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_CN.UTF-8/articles/remote-install/article.xml b/zh_CN.UTF-8/articles/remote-install/article.xml
new file mode 100644
index 0000000000..fa95df333a
--- /dev/null
+++ b/zh_CN.UTF-8/articles/remote-install/article.xml
@@ -0,0 +1,512 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
+<!--
+ The FreeBSD Documentation Project
+ The FreeBSD Chinese (Simplified) Documentation Project
+
+ Original Revision: 1.6
+-->
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_cn">
+ <info><title>&os; 操作系统在无远程控制台下的远程安装</title>
+
+
+ <author><personname><firstname>Daniel</firstname><surname>Gerzo</surname></personname><affiliation>
+ <address><email>danger@FreeBSD.org</email></address>
+ </affiliation></author>
+
+ <legalnotice xml:id="trademarks" role="trademarks">
+ &tm-attrib.freebsd;
+ &tm-attrib.general;
+ </legalnotice>
+
+ <copyright>
+ <year>2008</year>
+ <holder>The &os; Documentation Project</holder>
+ </copyright>
+
+ <pubdate>$FreeBSD$</pubdate>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+
+ <abstract>
+ <para>本文归档了当远程控制台不可用的情况下 &os; 操作系统的远程安装。
+ 文章背后的主要灵感归功于和 &a.mm; 还有由 &a.pjd;
+ 提供的宝贵输入合作的结果。</para>
+ </abstract>
+ </info>
+
+ <sect1 xml:id="background">
+ <title>背景</title>
+
+ <para>世界上有很多的服务器主机供应商,
+ 但是他们中只有很少的一部分正式支持 &os;,
+ 他们通常为他们提供的服务器上安装 &linux;
+ 发行版提供支持。</para>
+
+ <para>在某些情况下,如果你请求这些公司他们会安装一个你首选的 &linux;
+ 发行版。有了这个选择,我们将试图安装 &os;。
+ 在其他情况下,他们可能提供一个急救系统用于紧急情况。
+ 使用这个可能将有利于我们的目的更好的实现。</para>
+
+ <para>本文涵盖了引导一个包含 RAID-1 及 <application>ZFS</application>
+ 性能的 &os; 系统的远程安装的基本安装配置所必须的步骤。</para>
+ </sect1>
+
+ <sect1 xml:id="intro">
+ <title>简介</title>
+
+ <para>这一节会摘要本文的目的以及更好阐述这里所概括的东西。
+ 本文中的这些指令将有益于那些使用不支持 &os;
+ 的托管设施提供的服务的人。</para>
+
+ <procedure>
+ <step>
+ <para>如我们提到过的 <link linkend="background">背景</link>
+ 的那一节,许多的有声望的服务器主机托管公司提供了各种的急救系统。
+ 可以从他们自己的 <acronym>局域网</acronym> 启动并可以通过
+ <application>SSH</application> 访问。
+ 他们通常提供这种支持目的用于帮助他们的顾客修正损坏的操作系统。
+ 如文章将说明的,我们将能够通过这些急救系统的帮助来安装 &os;。</para>
+ <!-- XXXTR: Solaris has a restore command, something like
+ sysrestore, FreeBSD Should have one too. -->
+ </step>
+
+ <step>
+ <para>文章的下一小节会描述如何配置,并在本地机器上构建最小限度的
+ &os;。该版本最终会从随机存储盘运行到远程机器上面去。
+ 这将允许我们使用 <application>sysinstall</application>
+ 实用程序从一个 <acronym>FTP</acronym>
+ 镜像安装一套完整的 &os; 操作系统。</para>
+ </step>
+
+ <step>
+ <para>文章的剩余内容除了描述 <application>ZFS</application>
+ 文件系统的配置还将描述系统本身的安装步骤。</para>
+ </step>
+ </procedure>
+
+ <sect2 xml:id="requirements">
+ <title>需求</title>
+
+ <para>想要成功地做下去,你必须:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>拥有一个可通过 <application>SSH</application>
+ 网络访问的操作系统。</para>
+ </listitem>
+
+ <listitem>
+ <para>理解 &os; 的安装过程</para>
+ </listitem>
+
+ <listitem>
+ <para>熟悉 &man.sysinstall.8; 实用程序</para>
+ </listitem>
+
+ <listitem>
+ <para>拥有 &os; 安张的 <acronym>ISO</acronym>
+ 镜像文件或者易于使用的 <acronym>CD</acronym></para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="preparation">
+ <title>准备工作 - <application>mfsBSD</application></title>
+
+ <para>在 &os; 可能安装到目标系统上之前,
+ 需要先构建一个最小化的从磁盘启动的 &os; 操作系统映像文件。
+ 此方法中新系统必须能够从网络访问,
+ 并且安装的其他过程能够在没有远程访问到系统控制台的情况下完成。</para>
+
+ <para><application>mfsBSD</application> 设置工具能够被用来构建一个微小的
+ &os; 映像。如 <application>mfsBSD</application> 名字的含义
+ (<quote>mfs</quote> 的意思是 <quote>memory file system</quote> 内存文件系统),
+ 最后的映像全部从随机存储器运行。多亏了这个特性,
+ 磁盘的操作将不会有任何限制,因此它能够被用来安装一个完整的 &os; 操作系统。
+ <application>mfsBSD</application> 的主页在
+ <uri xlink:href="http://people.freebsd.org/~mm/mfsbsd/">http://people.freebsd.org/~mm/mfsbsd/</uri>,
+ 包含了指向最新释出的设置工具。</para>
+
+ <para>请注意关于 <application>mfsBSD</application>
+ 内幕以及它所有的适用都超出了本文的内容,
+ 感兴趣的读者应该去查阅 <application>mfs</application>
+ 的原始文档得到更多详细内容。</para>
+
+ <para>下载并解压出最新的 <application>mfsBSD</application>
+ 版本,并改变自己的当前工作目录到存在 <application>mfsBSD</application>
+ 脚本文件的目录:</para>
+
+ <screen>&prompt.root; <userinput>fetch http://people.freebsd.org/~mm/mfsbsd/mfsbsd-latest.tar.gz</userinput>
+&prompt.root; <userinput>tar xvzf mfsbsd-1.0-beta1.tar.gz</userinput>
+&prompt.root; <userinput>cd mfsbsd-1.0-beta1/</userinput></screen>
+
+ <sect2 xml:id="mfsbsd-config">
+ <title><application>mfsBSD</application> 的配置</title>
+
+ <para>引导 <application>mfsBSD</application> 之前,
+ 必须设置一些重要的配置选项。
+ 最重要的是我们必须有正确地,自然地,网络配置。
+ 最适合的方法配置网络选项取决于我们是否事先知道我们会用到的网络接口,
+ 而且网络接口驱动程序应被系统为我们的硬件载入。
+ 我们将看到 <application>mfsBSD</application>
+ 如何能够在任一种情况下被配置。</para>
+
+ <para>另外一件重要的事情是设置 <systemitem class="username">root</systemitem> 的密码。
+ 这将通过编辑 <filename>conf/rootpw.conf</filename> 文件来完成。
+ 请记住该文件将把你的密码保存在简单的文本中,
+ 所以在此我们不推荐你使用真实的密码。然而,
+ 这只是一个临时使用一次的密码,你可以在随后安装好的系统中更改它。</para>
+
+ <sect3>
+ <title>编辑 <filename>conf/interfaces.conf</filename> 的方法</title>
+
+ <para>如果我们安装好的网卡是未知类型的,
+ 我们可以使用 <application>mfsBSD</application> 的自动探测功能。
+ <application>mfsBSD</application> 启动脚本能够探测到正确的驱动来使用,
+ 基于网络接口的 MAC 地址,我们假设在
+ <filename>conf/interfaces.conf</filename> 文件中设置如下选项:</para>
+
+ <programlisting>initconf_interfaces="ext1"
+initconf_mac_ext1="00:00:00:00:00:00"
+initconf_ip_ext1="192.168.0.2"
+initconf_netmask_ext1="255.255.255.0"</programlisting>
+
+ <para>别忘了添加 <literal>defaultrouter</literal>
+ 信息到 <filename>conf/rc.conf</filename> 文件中:</para>
+
+ <programlisting>defaultrouter="192.168.0.1"</programlisting>
+ </sect3>
+
+ <sect3>
+ <title>编辑 <filename>conf/rc.conf</filename> 的方法</title>
+
+ <para>当网络接口的驱动是已知类型的,使用
+ <filename>conf/rc.conf</filename> 文件添加联网选项会更加方便。
+ 该文件的语法跟 &os; 中标准的 &man.rc.conf.5; 文件的语法相同。</para>
+
+ <para>例如,当你知道被使用的将是一个 &man.re.4; 网络接口设备,
+ 你可以在 <filename>conf/rc.conf</filename> 文件中设置如下选项:</para>
+
+ <programlisting>defaultrouter="192.168.0.1"
+ifconfig_re0="inet 192.168.0.2 netmask 255.255.255.0"</programlisting>
+ </sect3>
+ </sect2>
+
+ <sect2 xml:id="mfsbsd-build">
+ <title>构建一个 <application>mfsBSD</application> 映像</title>
+
+ <para>构建一个 <application>mfsBSD</application>
+ 映像文件的过程是非常简单明了的。</para>
+
+ <para>第一步是挂载 &os; 的安装 <acronym>CD</acronym>,
+ 或者挂载安装 <acronym>ISO</acronym> 文件到
+ <filename>/cdrom</filename>。
+ 因为例子的缘故,在文章中我们将假定你下载的是 &os; 7.0-RELEASE
+ <acronym>ISO</acronym> 文件。使用 &man.mdconfig.8;
+ 实用程序挂载 <acronym>ISO</acronym> 映像文件到
+ <filename>/cdrom</filename> 目录非常简单:</para>
+
+ <screen>&prompt.root; <userinput>mdconfig -a -t vnode -u 10 -f 7.0-RELEASE-amd64-disc1.iso</userinput>
+&prompt.root; <userinput>mount_cd9660 /dev/md10 /cdrom</userinput></screen>
+
+ <para>紧接着,构建可启动的 <application>mfsBSD</application>
+ 映像:</para>
+
+ <screen>&prompt.root; <userinput>make BASE=/cdrom/7.0-RELEASE</userinput></screen>
+
+ <note>
+ <para>上面的 <command>make</command> 命令必须在
+ <application>mfsBSD</application> 目录树的最高一层运行,也就是:
+ <filename>~/mfsbsd-1.0-beta1/</filename>。</para>
+ </note>
+ </sect2>
+
+ <sect2>
+ <title>启动 <application>mfsBSD </application></title>
+
+ <para>现在 <application>mfsBSD</application> 映像已经准备好了,
+ 必须把它上传到远程的一个正在运行的急救系统上或者一个预安装了
+ &linux; 发行版的系统上。最适合做这个工作的工具是
+ <application>scp</application>:</para>
+
+ <screen>&prompt.root; <userinput>scp disk.img root@192.168.0.2:.</userinput></screen>
+
+ <para>想要正确的引导 <application>mfsBSD</application> 映像,
+ 必须把它安放在机器的第一块(可启动)设备上。
+ 这可能会和使用的例子我们假定的一样,第一块可启动磁盘设备是
+ <filename>sda</filename>:</para>
+
+ <screen>&prompt.root; <userinput>dd if=/root/disk.img of=/dev/sda bs=1m</userinput></screen>
+
+ <para>如果一切正常,该映像现在应该存在于第一块设备的
+ <acronym>MBR</acronym>(主引导区)而机器也应该能够被启动了。
+ 使用工具 &man.ping.8; 来查看机器是否被正确启动。
+ 一旦它回复在线状态,就应该能够使用 <systemitem class="username">root</systemitem>
+ 用户和配置好的密码通过 &man.ssh.1; 来访问它了。</para>
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="installation">
+ <title>&os; 操作系统的安装</title>
+
+ <para><application>mfsBSD</application> 成功被引导后它就应该能够通过
+ &man.ssh.1; 登入了。这一节会描述如何创建 slices 并标记 slices 的 label,
+ 为 RAID-1 配置 <application>gmirror</application>,
+ 还有如何使用 <application>sysinstall</application>
+ 来安装一个最小的FreeBSD操作系统版本。</para>
+
+ <sect2>
+ <title>准备磁盘</title>
+
+ <para>首要的任务是为 &os; 分配磁盘空间,也就是,
+ 创建 slices 和 partitions。很显然,
+ 当前运行的系统是全部被载入到系统内存中的因此操作磁盘将没有任何问题。
+ 要完成这个任务,可以是使用 <application>sysinstall</application>
+ 或者 &man.fdisk.8; 中的二者任一并结合工具 &man.bsdlabel.8;。</para>
+
+ <para>在开始时,将所有磁盘都标记成空的,
+ 在每个磁盘上重复如下命令:</para>
+
+ <screen>&prompt.root; <userinput>dd if=/dev/zero of=/dev/ad0 count=2</userinput></screen>
+
+ <para>下面,使用你喜欢的工具创建 slices 并标记磁盘 label。
+ 比较简单的方法是使用 <application>sysinstall</application>,
+ 强大也可能几乎没有漏洞方法是使用标准的基于文本的 &unix; 工具,
+ 类似于 &man.fdisk.8; 和 &man.bsdlabel.8;
+ 这些工具的使用也会在这一节中包括。前者已经被包括在 &os; 手册的
+ <link xlink:href="&url.books.handbook;/install-steps.html">安装FreeBSD</link>
+ 一章中了。如本节中刚提到的,这篇文章会展示如何设置一个带有 RAID-1
+ 和 <application>ZFS</application> 性能的系统。我们的设置由一个小工具
+ &man.gmirror.8; 镜像为 <filename>/</filename> (root),
+ <filename>/usr</filename> 和
+ <filename>/var</filename> 文件系统,
+ 并把剩余的磁盘空间被分配为 &man.zpool.8; 镜像出的
+ <application>ZFS</application> 文件系统。请注意,
+ <application>ZFS</application> 文件系统将在 &os;
+ 操作系统成功安装并启动后才会被配置。</para>
+
+ <para>下面的例子会描述如何去创建 slices 和 labels,
+ 在每个 partition 上初始化 &man.gmirror.8;
+ 并如何在每个被镜像过的 partition 上创建
+ <application>UFS2</application> 文件系统:</para>
+
+ <screen>&prompt.root; <userinput>fdisk -BI /dev/ad0</userinput> <co xml:id="fdisk"/>
+&prompt.root; <userinput>fdisk -BI /dev/ad1</userinput>
+&prompt.root; <userinput>bsdlabel -wB /dev/ad0s1</userinput> <co xml:id="bsdlabel-writing"/>
+&prompt.root; <userinput>bsdlabel -wB /dev/ad1s1</userinput>
+&prompt.root; <userinput>bsdlabel -e /dev/ad0s1</userinput> <co xml:id="bsdlabel-editing"/>
+&prompt.root; <userinput>bsdlabel /dev/ad0s1 &gt; /tmp/bsdlabel.txt &amp;&amp; bsdlabel -R /dev/ad1s1 /tmp/bsdlabel.txt</userinput> <co xml:id="bsdlabel-restore"/>
+&prompt.root; <userinput>gmirror label root /dev/ad[01]s1a</userinput> <co xml:id="gmirror1"/>
+&prompt.root; <userinput>gmirror label var /dev/ad[01]s1d</userinput>
+&prompt.root; <userinput>gmirror label usr /dev/ad[01]s1e</userinput>
+&prompt.root; <userinput>gmirror label -F swap /dev/ad[01]s1b</userinput> <co xml:id="gmirror2"/>
+&prompt.root; <userinput>newfs /dev/mirror/root</userinput> <co xml:id="newfs"/>
+&prompt.root; <userinput>newfs /dev/mirror/var</userinput>
+&prompt.root; <userinput>newfs /dev/mirror/usr</userinput></screen>
+
+ <calloutlist>
+ <callout arearefs="fdisk">
+ <para>在整个磁盘上创建一个 slice
+ 并初始化包含在磁盘第一个扇区启动代码。
+ 重复在系统上全部的磁盘上执行此命令。</para>
+ </callout>
+
+ <callout arearefs="bsdlabel-writing">
+ <para>为每块磁盘写入一个包括启动代码的内容的标准
+ label。</para>
+ </callout>
+
+ <callout arearefs="bsdlabel-editing">
+ <para>现在,手动去编辑磁盘的 label。可以查阅 &man.bsdlabel.8;
+ 的联机手册来找到如何建立 partitions 的方法。创建如下
+ partions,<literal>a</literal> 为
+ <filename>/</filename> (root) 文件系统,
+ <literal>b</literal> 为 swap 交换空间,
+ <literal>d</literal> 为
+ <filename>/usr</filename>
+ 还有最后 <literal>f</literal> 被用于
+ <application>ZFS</application>。</para>
+ </callout>
+
+ <callout arearefs="bsdlabel-restore">
+ <para>引入你刚才创建的 label 到第二块磁盘,
+ 所以两块磁盘会使用同样的 label。</para>
+ </callout>
+
+ <callout arearefs="gmirror1">
+ <para>在每个 partition 上初始化 &man.gmirror.8;。</para>
+ </callout>
+
+ <callout arearefs="gmirror2">
+ <para>注意 <option>-F</option> 选项被用在 swap
+ 交换分区的 partition。 &man.gmirror.8;
+ 这个指令认为设备处于可靠的状态除非电源系统故障。</para>
+ </callout>
+
+ <callout arearefs="newfs">
+ <para>在每个被镜像的分区上创建一个
+ <application>UFS2</application> 的文件系统。</para>
+ </callout>
+ </calloutlist>
+ </sect2>
+
+ <sect2>
+ <title>系统安装</title>
+
+ <para>这是最重要的一部分。
+ 此节将描述如何在我们上一小节已经准备好的磁盘上安装一个最小的
+ &os; 版本。要达成这个目的,所有的文件安系统需要被挂载乃至于
+ <application>sysinstall</application> 可以把 &os;
+ 系统的内容写到磁盘上:</para>
+
+ <screen>&prompt.root; <userinput>mount /dev/mirror/root /mnt</userinput>
+&prompt.root; <userinput>mkdir /mnt/var /mnt/usr</userinput>
+&prompt.root; <userinput>mount /dev/mirror/var /mnt/var</userinput>
+&prompt.root; <userinput>mount /dev/mirror/usr /mnt/usr</userinput></screen>
+
+ <para>当你做完这些时,打开 &man.sysinstall.8;。
+ 从主菜单选择自定义 <guimenuitem>Custom</guimenuitem> 安装。
+ 选中 <guimenuitem>Options</guimenuitem> 选项然后按回车确认。
+ 使用方向键获取帮助,移动鼠标指针到 <literal>Install Root</literal>
+ 选项,按 <keycap>空格</keycap> 更改为
+ <filename>/mnt</filename>。
+ 按 <keycap>回车</keycap> 提交你的更改并使用
+ <keycap>q</keycap> 退出 <guimenuitem>Options</guimenuitem>
+ (选项)菜单。</para>
+
+ <warning>
+ <para>注意这一步骤非常重要,如果被跳过了,
+ <application>sysinstall</application>
+ 将不能安装 &os;。</para>
+ </warning>
+
+ <para>到 <guimenuitem>Distributions</guimenuitem>(发行版)菜单选项,
+ 使用方向键移动鼠标指针到 <option>Minimal</option>(最小化)选项,
+ 并使用 <keycap>空格键</keycap> 选中该选项。
+ 本文使用了最小版本来保存网络联通信息,因为系统本身会通过
+ <application>ftp</application> 来安装。使用
+ <option>Exit</option>(退出)选项退出这个菜单。</para>
+
+ <note>
+ <para><guimenuitem>Partition</guimenuitem> 和
+ <guimenuitem>Label</guimenuitem> 菜单将被跳过,
+ 这些没有多少价值了。</para>
+ </note>
+
+ <para><guimenuitem>Media</guimenuitem>(媒介)菜单,
+ 选择 <option>FTP</option> 选项。
+ 选择一个距离你最近的镜像站点并交给
+ <application>sysinstall</application>
+ 假定网络已经配置完好。你将再回到
+ <guimenuitem>Custom</guimenuitem>
+ (自定义)菜单。</para>
+
+ <para>最后,选择最后的选项来执行系统的安装过程,
+ <guimenuitem>Commit</guimenuitem>,
+ 当安装完成后退出 <application>sysinstall</application>
+ 即可。</para>
+ </sect2>
+
+ <sect2>
+ <title>后期安装步骤</title>
+
+ <para>&os; 操作系统现在应该安装完毕了;通常情况下,
+ 安装过程还没有结束。还需要进行一些安装后期的步骤使得容许
+ &os; 在将来启动并能够登入系统。</para>
+
+ <para>你现在必须 &man.chroot.8;
+ 到刚安装的全新的系统中来完成安装。
+ 使用如下命令: </para>
+
+ <screen>&prompt.root; <userinput>chroot /mnt</userinput></screen>
+
+ <para>要达到我们的目的,进行如下步骤:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>拷贝 <literal>GENERIC</literal>(通用)内核到
+ <filename>/boot/kernel</filename>
+ 目录:</para>
+
+ <screen>&prompt.root; <userinput>cp -Rp /boot/GENERIC/* /boot/kernel</userinput></screen>
+ </listitem>
+
+ <listitem>
+ <para>创建 <filename>/etc/rc.conf</filename>,
+ <filename>/etc/resolv.conf</filename> 还有
+ <filename>/etc/fstab</filename> 文件。
+ 不要忘记正确地设置网络信息并在
+ <filename>/etc/rc.conf</filename>
+ 文件中启用 <application>sshd</application>。
+ <filename>/etc/fstab</filename>
+ 文件内容类似于下面的内容:</para>
+
+ <programlisting># Device Mountpoint FStype Options Dump Pass#
+/dev/mirror/swap none swap sw 0 0
+/dev/mirror/root / ufs rw 1 1
+/dev/mirror/usr /usr ufs rw 2 2
+/dev/mirror/var /var ufs rw 2 2
+/dev/cd0 /cdrom cd9660 ro,noauto 0 0</programlisting>
+ </listitem>
+
+ <listitem>
+ <para>创建 <filename>/boot/loader.conf</filename>
+ 文件,并写入如下内容:</para>
+
+ <programlisting>geom_mirror_load="YES"
+zfs_load="YES"</programlisting>
+ </listitem>
+
+ <listitem>
+ <para>执行下面的命令,使得
+ <application>ZFS</application> 在下次启动后可用:</para>
+
+ <screen>&prompt.root; <userinput>echo 'zfs_enable="YES"' &gt;&gt; /etc/rc.conf </userinput></screen>
+ </listitem>
+
+ <listitem>
+ <para>可以用 &man.adduser.8; 工具来添加额外的用户。
+ 不要忘记添加一个用户到 <systemitem class="groupname">wheel</systemitem>
+ 组,这样你可以在重新启动后获得 root 权限。</para>
+ </listitem>
+
+ <listitem>
+ <para>反复检验你的设置是否正确。</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>现在你的系统在下次启动后应该可用了。使用
+ &man.reboot.8; 命令重新启动你的系统。</para>
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="zfs">
+ <title>ZFS</title>
+
+ <para>如果你的系统重新启动后还完好,现在应该能够登入了。
+ 欢迎来到崭新的 &os; 安装,进行远程的不使用远程控制台的安装。</para>
+
+ <para>最后还剩下的步骤是配置 &man.zpool.8; 并创建一些
+ &man.zfs.8; 文件系统。建立并管理
+ <application>ZFS</application> 非常简单。
+ 首先,创建一个镜像的pool:</para>
+
+ <screen>&prompt.root; <userinput>zpool create tank mirror /dev/ad[01]s1f</userinput></screen>
+
+ <para>再接着,创建一些文件系统:</para>
+
+ <screen>&prompt.root; <userinput>zfs create tank/ports</userinput>
+&prompt.root; <userinput>zfs create tank/src</userinput>
+&prompt.root; <userinput>zfs set compression=gzip tank/ports</userinput>
+&prompt.root; <userinput>zfs set compression=on tank/src</userinput>
+&prompt.root; <userinput>zfs set mountpoint=/usr/ports tank/ports</userinput>
+&prompt.root; <userinput>zfs set mountpoint=/usr/src tank/src</userinput></screen>
+
+ <para>这就是全部步骤了。如果你对 &os; 上的
+ <application>ZFS</application> 感兴趣,请查阅 &os; WIKI 中的
+ <link xlink:href="http://wiki.freebsd.org/ZFS">ZFS</link> 一节。</para>
+ </sect1>
+</article>