当进行启动或停止的调用时,rc.d
脚本应该作用于其所负责的整个子系统。例如, /etc/rc.d/netif
应该启动或停止 rc.conf(5)
中所描述的全部网络接口。每个任务都唯一地听从一个如 start 或
stop 这样的单独命令参数的指示。在启动和停止之间的时间, rc.d 脚本帮助管理员控制运行中的系统,
并其在需要的时候它将产生更多的灵活性和精确性。举个例子, 管理员可能想在 rc.conf(5)
中添加一个新网络接口的配置信息, 然后在不妨碍其它已存在接口的情况下将其启动。
在下次管理员可能需要关闭一个单独的网络接口。在魔幻的命令行中, 对应的 rc.d 脚本调用一个额外的参数, 网络接口名即可。
幸运的是,rc.subr(8) 允许传递任意多(取决于系统限制)的参数给脚本的方法。 由于这个原因,脚本自身的改变可以说是微乎其微。
rc.subr(8) 如何访问到附加的命令行参数呢?直接获取么? 并非是无所不用其极的。首先,sh(1) 函数没有访问到调用者的定位参数,而 rc.subr(8) 只是这些函数的容器。其次,rc.d 指令的一个好的风格是由主函数来决定将哪些参数传递给它的方法。
所以 rc.subr(8)
提供了如下的方法: run_rc_command
传递其所有参数但将第一个参数逐字传递到各自的方法。首先,
发出以方法自身为名字的参数:start, stop,等等。这会被 run_rc_command
移出, 这样命令行中原本 $2 的内容将作为 $1
来提供给方法,等等。
为了说明这点,我们来修改原来的虚拟脚本, 这样它的信息将取决于所提供的附加参数。从这里出发:
#!/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
echo "Greeting message: $*"
else
echo "Nothing started."
fi
}
dummy_kiss()
{
echo -n "A ghost gives you a kiss"
if [ $# -gt 0 ]; then
echo -n " and whispers: $*"
fi
case "$*" in
*[.!?])
echo
;;
*)
echo .
;;
esac
}
load_rc_config $name
run_rc_command "$@"
能注意到脚本里发生了那些实质性改变么?

start
之后的参数可以被当作各自方法的定位参数一样被终结。
我们可以根据我们的任务、技巧和想法来以任何方式使用他们。
在当前的例子中,我们只是以下行中字符串的形式传递参数给 echo(1) 程序 ── 注意
$* 是有双引号的。这里是脚本如何被调用的:# /etc/rc.d/dummy start Nothing started. # /etc/rc.d/dummy start Hello world! Greeting message: Hello world!

kiss 的方法, 并且它给附加参数带来的戏耍决不亚于 start。 例如:# /etc/rc.d/dummy kiss A ghost gives you a kiss. # /etc/rc.d/dummy kiss Once I was Etaoin Shrdlu... A ghost gives you a kiss and whispers: Once I was Etaoin Shrdlu...

run_rc_command 的地方, 用 "$@ 代替 "$1" 即可。重要: 一个 sh(1) 程序员应该是可以理解 $* 和 $@ 的微妙区别只是指定全部定位参数的不同方法。 关于此更深入的探讨,可以参考这个很好的 sh(1) 脚本编程手册。在你完全理解这些表达式的意义之前请不要使用它们, 因为误用它们将给脚本引入缺陷和不安全的弊端。
注意: 现在
run_rc_command可能有个缺陷, 它将影响保持参数之间的原本边界。也就是, 带有嵌入空白的参数可能不会被正确处理。该缺陷是由于对 $* 的误用。
本文档和其它文档可从这里下载:ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.
如果对于FreeBSD有问题,请先阅读文档,如不能解决再联系<questions@FreeBSD.org>.
关于本文档的问题请发信联系 <doc@FreeBSD.org>.