当编写好了一个脚本,它需要被整合到 rc.d 中去。 一个重要的步骤就是安装脚本到 /etc/rc.d (对基本系统而言)或 /usr/local/etc/rc.d (对ports而言)中去。在 <bsd.prog.mk> 和 <bsd.port.mk> 中都为此提供了方便的接口, 通常你不必担心适当的所有权限和模式。系统脚本应当是通过可以在 src/etc/rc.d 找到的 Makefile 安装的。Port 脚本可以像 Porter's Handbook 中描述那样通过使用 USE_RC_SUBR 来被安装。
不过,我们应该预先考虑到我们脚本在系统启动顺序中的位置。 我们的脚本所处理的服务可能依赖于其它的服务。举个例子, 没有网络接口和路由选择的启用运行的话,一个网络守护进程是不起作用的。 即使一个服务看似什么都不需要,在基本文件系统检查挂载完毕之前也很难启动。
之前我们曾提到过 rcorder(8)。现在是时候来密切地关注下它了。
笼统地说,rcorder(8)
处理一组文件,检验它们的内容, 并从文件集合打印一个文件列表的依赖顺序到 stdout
标准输出。这点是用于保持文件内部的依赖信息,
而每个文件只能说明自己的依赖。一个文件可以指定如下信息:
它 提供 的 “条件” 的名字(意味着我们服务的名字);
它 需求 的 “条件” 的名字;
应该 先 运行的文件的 “条件”的名字;
能用于从全部文件集合中选择一个子集的额外 关键字( rcorder(8) 可通过选项而被指定来包括或省去由特殊关键字所列出的文件。)
并不奇怪的是,rcorder(8) 只能处理接近 sh(1) 语法的文本文件。rcorder(8) 所解读的特殊行看起来类似 sh(1) 的注释。这种特殊文本行的语法相当严格地简化了其处理。 请查阅 rcorder(8) 以获取更详细的信息。
除使用 rcorder(8) 的特殊行以外, 脚本可以坚持将其依赖的其它服务强制性启动。当其它服务是可选的, 并因系统管理员错误地在 rc.conf(5) 中禁用掉该服务而使其不能自行启动时,会需要这一点。
将这些谨记在心,我们来考虑下简单结合了依赖信息增强的守护进程脚本:
#!/bin/sh # PROVIDE: mumbled oldmumble # REQUIRE: DAEMON cleanvar frotz # BEFORE: LOGIN # KEYWORD: nojail shutdown . /etc/rc.subr name=mumbled rcvar=mumbled_enable command="/usr/sbin/${name}" start_precmd="${name}_prestart" mumbled_prestart() { if ! checkyesno frotz_enable && \ ! /etc/rc.d/frotz forcestatus 1>/dev/null 2>&1; then force_depend frotz || return 1 fi return 0 } load_rc_config $name run_rc_command "$1"
跟前面一样,做如下详细分析:
注意: 通常脚本指定一个单独的已提供的条件。然而, 并没有什么妨碍我们从列出的那些条件中指定,例如, 为了兼容性的目的。
在其它情况,主要的名称,或者说唯一的, PROVIDE: 条件应该与 ${name} 相同。
注意: BEFORE: 这一行不可以在其它脚本不完整的依赖关系列表中滥用。 适合使用 BEFORE: 的情况是当其它脚本不关心我们的脚本, 但是我们的脚本如果在另一个之前运行的话能够更好地执行任务。 一个典型的实例是网络接口和防火墙: 虽然接口不依赖防火墙来完成自己的工作, 但是系统安全将因一切网络流量之前启动的防火墙而受益。
除了条件相对应的每个单独服务,脚本使用元条件和它们的 “占位符” 来保证某个操作组在其它之前被执行。 这些是由 UPPERCASE 大写名字所表示的。它们的列表和用法可以在 rc(8) 中找到。
切记将一个服务名称放进 REQUIRE: 行不能保证实际的服务会在我们的脚本启动的时候运行。 所需求的服务可能会启动失败或在 rc.conf(5) 中被禁掉了。 显然,rcorder(8) 是无法追踪这些细节的,并且 rc(8) 也不会去追踪。所以, 脚本启动的应用程序应当能够应付任何所需求的服务的不可用情况。 某些情况下,我们可以用 下面 所讨论的方式来协助脚本。
-k
和 -s
选项来分别指定 “保留清单(keep list)” 和 “跳过清单(skip list)”。
从全部文件到按依赖关系排列的清单,rcorder(8)
将只是挑出保留清单(除非是空的)
中那些带关键字的以及从跳过清单中挑出不带关键字的文件。在 FreeBSD 中,rcorder(8) 被 /etc/rc 和 /etc/rc.shutdown 所使用。 这两个脚本定义了 FreeBSD 中 rc.d 关键字以及它们的意义的标准列表如下:
该服务不适用于 jail(8) 环境。 如果是在 jail 的内部的话,自动启动和关闭程序将忽略该脚本。
该服务只能手动启动否则将不会启动。 自动启动程序将忽略此脚本。结合 shutdown 关键字的话,这可以用来编写只在系统关闭时执行一些任务的脚本。
这个关键字 明确 地列出了需要在系统关闭前停止的服务。
注意: 当系统即将关闭的时候, /etc/rc.shutdown 在运行。 它假定认为大部分的 rc.d 脚本在那刻什么都不做。因此, /etc/rc.shutdown 选择性地调用带有 shutdown 关键字的 rc.d 脚本, 有效地忽略其余的脚本。为了更快的关闭, /etc/rc.shutdown 传递
faststop
命令给其运行的脚本, 以跳过预置的检查,例如,进程文件 pidfile 的检查。 正如依赖性服务应该在其所依赖的服务之前停止, /etc/rc.shutdown 以相反的依赖次序来运行这些脚本。如果写一个真正的 rc.d 脚本的话, 你应当考虑到其是否与系统关闭时有关系。例如, 如果你的脚本只通过响应
start
命令来运行任务,那么你不需要包含这个关键字。然而, 如果你的脚本管理着一个服务,那么,在系统进入 halt(8) 中所描述的其本身关闭顺序的最终阶段之前停止该脚本, 可能是个不错的主意。特别是, 你显然是应该关闭一个需要相当长时间, 或需要特定的动作才能干净地关闭的服务。 数据库引擎就是这样一个典型的例子。
force_depend
起始的行应被用于更谨慎的情况。通常,用于修正相互关联的 rc.d
脚本分层结构的配置文件时会更加稳妥。如果你仍不能完成不含 force_depend
的脚本,
范例提供了一个如何有条件地调用它的习惯用法。在范例中,我们的 mumbled 守护进程需求另一个以高级方式启动的进程, frotz。但 frotz 也是可选的; 而且 rcorder(8)
对这些信息是一无所知的。幸运的是, 我们的脚本已访问到全部的 rc.conf(5) 变量。如果
frotz_enable 为真,我们希望的最好结果是依靠 rc.d 已经启动了 frotz。 否则我们强制检查
frotz 的状态。最终, 如果 frotz
依赖的服务没有找到或运行的话, 我们将强制其运行。这时 force_depend
将发出一条警告信息,因为它只应该在检查到配置信息丢失的情况下被调用。
本文档和其它文档可从这里下载:ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.
如果对于FreeBSD有问题,请先阅读文档,如不能解决再联系<questions@FreeBSD.org>.
关于本文档的问题请发信联系 <doc@FreeBSD.org>.