Performing additional tasks before or after the default methods is easy. For each command-argument supported by our script, we can define argument_precmd and argument_postcmd. These sh(1) commands are invoked before and after the respective method, as it is evident from their names.

Note: Overriding a default method with a custom argument_cmd still does not prevent us from making use of argument_precmd or argument_postcmd if we need to. In particular, the former is good for checking custom, sophisticated conditions that should be met before performing the command itself. Using argument_precmd along with argument_cmd lets us logically separate the checks from the action.

Do not forget that you can cram any valid sh(1) expressions into the methods, pre-, and post-commands you define. Just invoking a function that makes the real job is a good style in most cases, but never let style limit your understanding of what is going on behind the curtain.

If we would like to implement custom arguments, which can also be thought of as commands to our script, we need to list them in extra_commands and provide methods to handle them.

Note: The reload command is special. On the one hand, it has a preset method in rc.subr(8). On the other hand, reload is not offered by default. The reason is that not all daemons use the same reload mechanism and some have nothing to reload at all. So we need to ask explicitly that the builtin functionality be provided. We can do so via extra_commands.

What do we get from the default method for reload? Quite often daemons reload their configuration upon reception of a signal — typically, SIGHUP. Therefore rc.subr(8) attempts to reload the daemon by sending a signal to it. The signal is preset to SIGHUP but can be customized via sig_reload if necessary.

(8) (14)
Our script supports two non-standard commands, plugh and xyzzy. We saw them listed in extra_commands, and now it is time to provide methods for them. The method for xyzzy is just inlined while that for plugh is implemented as the mumbled_plugh function.

Non-standard commands are not invoked during startup or shutdown. Usually they are for the system admin’s convenience. They can also be used from other subsystems, e.g., devd(8) if specified in devd.conf(5).

The full list of available commands can be found in the usage line printed by rc.subr(8) when the script is invoked without arguments. For example, here is the usage line from the script under study:

# /etc/rc.d/mumbledUsage: /etc/rc.d/mumbled [fast|force|one](start|stop|restart|rcvar|reload|plugh|xyzzy|status|poll) 
A script can invoke its own standard or non-standard commands if needed. This may look similar to calling functions, but we know that commands and shell functions are not always the same thing. For instance, xyzzy is not implemented as a function here. In addition, there can be a pre-command and post-command, which should be invoked orderly. So the proper way for a script to run its own command is by means of rc.subr(8), as shown in the example.
A handy function named checkyesno is provided by rc.subr(8). It takes a variable name as its argument and returns a zero exit code if and only if the variable is set to YES, or TRUE, or ON, or 1, case insensitive; a non-zero exit code is returned otherwise. In the latter case, the function tests the variable for being set to NO, FALSE, OFF, or 0, case insensitive; it prints a warning message if the variable contains anything else, i.e., junk.
Keep in mind that for sh(1) a zero exit code means true and a non-zero exit code means false.

Important: The checkyesno function takes a variable name. Do not pass the expanded value of a variable to it; it will not work as expected.

The following is the correct usage of checkyesno:

			if checkyesno mumbled_enable; then        foofi 		

On the contrary, calling checkyesno as shown below will not work — at least not as expected:

			if checkyesno "${mumbled_enable}"; then        foofi 		
We can affect the flags to be passed to $command by modifying rc_flags in $start_precmd.
In certain cases we may need to emit an important message that should go to syslog as well. This can be done easily with the following rc.subr(8) functions: debug, info, warn, and err. The latter function then exits the script with the code specified.

The exit codes from methods and their pre-commands are not just ignored by default. If argument_precmd returns a non-zero exit code, the main method will not be performed. In turn, argument_postcmd will not be invoked unless the main method returns a zero exit code.

Note: However, rc.subr(8) can be instructed from the command line to ignore those exit codes and invoke all commands anyway by prefixing an argument with force, as in forcestart.

Leave a Comment

Your email address will not be published. Required fields are marked *