rc.d
scripts are used to start
services on system startup, and to give administrators a
standard way of stopping, starting and restarting the service.
Ports integrate into the system rc.d
framework. Details on its usage can be found in the rc.d
Handbook chapter. Detailed explanation of available
commands is provided in rc(8) and rc.subr(8).
Finally, there is an
article on practical aspects of
rc.d
scripting.
One or more rc.d
scripts can be
installed:
Scripts must be placed in the files
subdirectory and a .in
suffix must be added
to their filename. Standard SUB_LIST
expansions will be used for this file. Use of the
%%PREFIX%%
and
%%LOCALBASE%%
expansions is strongly
encouraged as well. More on SUB_LIST
in
the relevant
section.
Prior to FreeBSD 6.1-RELEASE, integration with
rcorder(8) is available by using
USE_RCORDER
instead of
USE_RC_SUBR
. However, use of this method
is not necessary unless the port has an option to install
itself in the base, or the service needs to run prior to the
FILESYSTEMS
rc.d
script in the base.
As of FreeBSD 6.1-RELEASE, local
rc.d
scripts (including those installed
by ports) are included in the overall rcorder(8) of the
base system.
Example simple rc.d
script:
Unless there is a good reason to start the service earlier all ports scripts should use
If the service runs as a particular user (other than root) this is mandatory.
is included in the script above because the mythical port we are using as an example starts a service, and should be shut down cleanly when the system shuts down. If the script is not starting a persistent service this is not necessary.
For optional configuration elements the "=" style of default variable assignment is preferable to the ":=" style here, since the former sets a default value only if the variable is unset, and the latter sets one if the variable is unset or null. A user might very well include something like
in their rc.conf.local
file, and a
variable substitution using ":=" would
inappropriately override the user's intention. The
_enable
variable is not optional,
and should use the ":" for the default.
No new scripts should be added with the
.sh
suffix.
Before contributing a port with an
rc.d
script, and more importantly,
before committing one, please consult the following
checklist to be sure that it is ready.
If this is a new file, does it have
.sh
in the file name? If so that
should be changed to just file.in
since new rc.d
files may not end
with that extension.
Does the file have a
$FreeBSD$
tag?
Do the name of the file (minus
.in
), the
PROVIDE
line, and
$
name
all match? The file name matching
PROVIDE
makes debugging easier,
especially for rcorder(8) issues. Matching the
file name and
$
name
makes it easier to figure out which variables are
relevant in rc.conf[.local]
. The
latter is also what you might call “policy”
for all new scripts, including those in the base
system.
Is the REQUIRE
line set to
LOGIN
? This is mandatory for scripts
that run as a non-root user. If it runs as root, is
there a good reason for it to run prior to
LOGIN
? If not, it should run there
so that we can loosely group local scripts to a point in
rcorder(8) after most everything in the base is
already running.
Does the script start a persistent service? If so,
it should have KEYWORD:
shutdown
.
Make sure there is no
KEYWORD: FreeBSD
present. This has
not been necessary or desirable for years. It is also
an indication that the new script was copy/pasted from
an old script, so extra caution should be given to the
review.
If the script uses an interpreted language like
perl
, python
, or
ruby
, make certain that
command_interpreter
is set
appropriately. Otherwise,
#
service name
stop
will probably not work properly. See service(8) for more information.
Have all occurrences of
/usr/local
been replaced with
%%PREFIX%%
?
Do the default variable assignments come after
load_rc_config
?
Are there default assignments to empty strings? They should be removed, but double-check that the option is documented in the comments at the top of the file.
Are things that are set in variables actually used in the script?
Are options listed in the default
name
_flags
things that are actually mandatory? If so, they should
be in command_args
. The
-d
option is a red flag (pardon the
pun) here, since it is usually the option to
“daemonize” the process, and therefore is
actually mandatory.
The
name
_flags
variable should never be included in
command_args
(and vice versa,
although that error is less common).
Does the script execute any code unconditionally?
This is frowned on. Usually these things can/should be
dealt with through a
start_precmd
.
All boolean tests should utilize the
checkyesno
function. No
hand-rolled tests for [Yy][Ee][Ss]
,
etc.
If there is a loop (for example, waiting for something to start) does it have a counter to terminate the loop? We do not want the boot to be stuck forever if there is an error.
Does the script create files or directories that
need specific permissions, for example, a
pid
file that needs to be owned by
the user that runs the process? Rather than the
traditional touch(1)/chown(8)/chmod(1)
routine, consider using install(1) with the proper
command line arguments to do the whole procedure with
one step.
All FreeBSD documents are available for download at http://ftp.FreeBSD.org/pub/FreeBSD/doc/
Questions that are not answered by the
documentation may be
sent to <freebsd-questions@FreeBSD.org>.
Send questions about this document to <freebsd-doc@FreeBSD.org>.