Skip to content

Debian's Policy-rc.d infrastructure explained

When one discusses advantages and disadvantages of some distributions over the other, it is a frequent beef against Debian that on Debian, network services get started immediately after the package was installed. On a package not driven by debconf, this includes the service getting started with some default configuration. On upgrades, services get stopped before the update and started automatically after the update was done. This might be useful with services that run with the default configuration, and is important with services that fork and re-read the configuration in the forked-off process. However, in some circumstances, it might be desireable to keep the old version of the service running until the new version is ready to start. I have always thought that this was written down in Debian policy, but I didn't find the place in the document, and asking on various IRC channels also resulted in no pointer. For now, I have to assume that this is "only" best practice in Deban and not mandatory in any case.

Debian is frequently bashed for this default, and the canonical answer is to use the policy framework delivered with sysv-rc to avoid services from being started. Since this mechanism is frequently misunderstood, I am writing this article to bring some more additional confusion to this matter.

Updated 2013-09-01: Default behavior controllable by init script headers.

When a daemon package uses the common tools like debhelper for its build, maintainer script code is automatically generated that starts the daemon and configures the system to automatically start the daemon on system boot. This is an intrinsic part of our build toolchain. Some packages take precautions not to start the daemon after installation, most commonly by setting a RUN, START or similiar variable in its /etc/default file, requiring the local admin to edit that file before the service can even be manually started by invoking the init script.

A package maintainer can decide whether the daemon should be started automatically or not by configuring the LSB init script headers, giving appropriate parameters to dh_installinit or by writing her own maintainer script code. Judging by the number of packages that still come with an /etc/default file with the default set to "NO", this is quite seldomly used.

A local administrator can influence the behavior of sysv-rc and the init scripts by means of the policy-rc.d layer (see the invoke-rc.d's manpage and /usr/share/doc/sysv-rc/README.policy-rc.d.gz on a Debian system with sysv-rc installed) and the update-rc.d disable and enable calls.

A package's maintainer scripts are supposed to only interface with the init system by means of invoke-rc.d, update-rc.d and the LSB init script headers. Never are they supposed to call the init script directly or via the service script (policy 9.3.3, 9.3.3.2), nor are they supposed to configure their own runlevel configuration themselves (polilcy 9.3.1, 9.3.3). The local admin is allowed to either directly modify the init system configuration (for sysv-rc, the start and stop links) or to use update-rc.d disable or enable. update-rc.d makes sure that the manually set policy is kept during package upgrades - this especially means that a service that was disabled by calling update-rc.d service disable will not be enabled during a package upgrade.

invoke-rc.d, on the other hand, is only meant to be called from maintainer scripts. It honors both the restrictions of the currently selected runlevel, and the local policy set by the local administrator. That means, for example, that a service that is configured to be started in runlevel 3 only does not get started when one invokes invoke-rc.d $SERVICE start while the system is in runlevel 2. This might not be what the local admin expects when she types a command on the command line, so she might be better off by running service $SERVICE start which will start the service regardless of which runlevel the system is in.

invoke-rc.d will, before taking its action, check whether /usr/sbin/policy-rc.d is executable, will call it with the respective service name and the current runlevel number on its command line and act according to its exit code. For example, a return value of 101 will prevent the planned action from being taken. This includes the automated start of the service upon package installation as well as the stop of the service on package removal and reduces the stop-upgrade-restart ritual during package upgrades to just performing the upgrade which might leave the old version of the service running. Unfortunately, policy-rc.d is not told whether its called was caused by a package installation, deinstallation or upgrade.

A local admin who does not want any services to be touched during package operations can just dump an "exit 101" to /usr/sbin/policy-rc.d and is done. This is used, for example, by container and chroot setups to prevent services from being started when the container/chroot is installed. If you feel uncomfortable with dumping a file that is essentially local configuration to /usr/sbin, you might want to look at the policyrcd-script-zg2 package which makes it possible to put your script in /etc.

While policy-rc.d only influences the behavior of maintainer scripts, this does not influence the behavior of a service when the system is rebooted. The "exit 101" policy-rc.d file will not prevent a newly installed service from being started when the system boots or changes runlevel. To make this decision, the local admin needs to manually call update-rc.d service disable after the service got installed. A package maintainer can decide in which runlevel the service should start by default by configuring the Default-Start and Default-Stop stanzas in the init script LSB headers. Giving explicit run level numbers to update-rc.d is deprecated and not any more documented.

To pack things up: The package maintainer already has full control about whether a service gets started after package installation. The local admin has a bit work to do if he wants to prevent service starts for packages whose maintainers have decided to automatically start the server: She needs to dump an appropriate policy-rc.d into the file system and issue update-rc.d service disable after package installation (or to change the init script's LSB headers).

Trackbacks

No Trackbacks

Comments

Display comments as Linear | Threaded

No comments

Add Comment

Markdown format allowed
Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Standard emoticons like :-) and ;-) are converted to images.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.
Form options