9.3.2. Writing the scripts
Init scripts are placed in /etc/init.d
. In the common case that a package starts a single service, they should be named /etc/init.d/package
. They should accept one argument, saying what to do:
start
start the service,
stop
stop the service,
restart
stop and restart the service if it’s already running, otherwise start the service
try-restart
restart the service if it’s already running, otherwise just report success.
reload
cause the configuration of the service to be reloaded without actually stopping and restarting the service,
force-reload
cause the configuration to be reloaded if the service supports this, otherwise restart the service.
status
report the current status of the service
The start
, stop
, restart
, and force-reload
options should be supported by all init scripts. Supporting status
is encouraged. The reload
and try-restart
options are optional.
The init.d
scripts must ensure that they will behave sensibly (i.e., returning success and not starting multiple copies of a service) if invoked with start
when the service is already running, or with stop
when it isn’t, and that they don’t kill unfortunately-named user processes. The best way to achieve this is usually to use start-stop-daemon
with the --oknodo
option.
Be careful of using set -e
in init.d
scripts. Writing correct init.d
scripts requires accepting various error exit statuses when daemons are already running or already stopped without aborting the init.d
script, and common init.d
function libraries are not safe to call with set -e
in effect. 4 For init.d
scripts, it’s often easier to not use set -e
and instead check the result of each command separately.
If a service reloads its configuration automatically (as in the case of cron
, for example), the reload
option of the init.d
script should behave as if the configuration has been reloaded successfully.
The /etc/init.d
scripts must be treated as configuration files, either (if they are present in the package, that is, in the .deb file) by marking them as conffile
s, or, (if they do not exist in the .deb) by managing them correctly in the maintainer scripts (see Configuration files). This is important since we want to give the local system administrator the chance to adapt the scripts to the local system, e.g., to disable a service without de-installing the package, or to specify some special command line options when starting a service, while making sure their changes aren’t lost during the next package upgrade.
These scripts should not fail obscurely when the configuration files remain but the package has been removed, as configuration files remain on the system after the package has been removed. Only when dpkg
is executed with the --purge
option will configuration files be removed. In particular, as the /etc/init.d/package
script itself is usually a conffile
, it will remain on the system if the package is removed but not purged. Therefore, you should include a test
statement at the top of the script, like this:
test -f program-executed-later-in-script || exit 0
Often there are some variables in the init.d
scripts whose values control the behavior of the scripts, and which a system administrator is likely to want to change. As the scripts themselves are frequently conffile
s, modifying them requires that the administrator merge in their changes each time the package is upgraded and the conffile
changes. To ease the burden on the system administrator, such configurable values should not be placed directly in the script. Instead, they should be placed in a file in /etc/default
, which typically will have the same base name as the init.d
script. This extra file should be sourced by the script when the script runs. It must contain only variable settings and comments in POSIX.1-2017 sh
format. It may either be a conffile
or a configuration file maintained by the package maintainer scripts. See Configuration files for more details.
To ensure that vital configurable values are always available, the init.d
script should set default values for each of the shell variables it uses, either before sourcing the /etc/default/
file or afterwards using something like the : ${VAR:=default}
syntax. Also, the init.d
script must behave sensibly and not fail if the /etc/default
file is deleted.
Files and directories under /run
, including ones referred to via the compatibility paths /var/run
and /var/lock
, are normally stored on a temporary filesystem and are normally not persistent across a reboot. The init.d
scripts must handle this correctly. This will typically mean creating any required subdirectories dynamically when the init.d
script is run. See /run and /run/lock for more information.