[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#208010: [PROPOSAL] init script LSB 1.3 compliance



Package: debian-policy
Version: 3.6.1.0
Severity: wishlist
Tags: patch

This proposal aims to synchronize the Debian Policy, section 9.3, with
the LSB 1.3.0, chapter 24 [1]. Attached is a patch and the resulting
plain text for better reading.

Notes:

* I suggest merging the "reserved for..." items, but left them
  separated for the moment.
* What is log_failure_msg? Does this make sense on a Debian system?
  Replace it or skip it?

Kind regards,

Martin

[1] http://www.linuxbase.org/spec/refspecs/LSB_1.3.0/gLSB/gLSB/iniscrptact.html
--- debian-policy-3.6.1.0.orig/policy.sgml	Tue Aug 19 14:32:23 2003
+++ debian-policy-3.6.1.0/policy.sgml	Sun Aug 31 13:04:48 2003
@@ -5362,13 +5362,16 @@
 	      <tag><tt>force-reload</tt></tag>
 	      <item>cause the configuration to be reloaded if the
 		  service supports this, otherwise restart the
-		  service.</item>
+		  service,</item>
+
+	      <tag><tt>status</tt></tag>
+	      <item>print the current status of the service.</item>
 	    </taglist>
 
-	    The <tt>start</tt>, <tt>stop</tt>, <tt>restart</tt>, and
-	    <tt>force-reload</tt> options should be supported by all
-	    scripts in <file>/etc/init.d</file>, the <tt>reload</tt>
-	    option is optional.
+	    The <tt>start</tt>, <tt>stop</tt>, <tt>restart</tt>,
+	    <tt>force-reload</tt>, and <tt>status</tt> options should
+	    be supported by all scripts in <file>/etc/init.d</file>,
+	    the <tt>reload</tt> option is optional.
 	  </p>
 
 	  <p>
@@ -5416,10 +5419,72 @@
 	    should include a <tt>test</tt> statement at the top of the
 	    script, like this:
 	    <example compact="compact">
-test -f <var>program-executed-later-in-script</var> || exit 0
+test -f <var>program-executed-later-in-script</var> || exit 5
 	    </example>
 	  </p>
 
+      <p>
+        In the case of init script commands other than <tt>status</tt> (i.e.,
+        <tt>start</tt>, <tt>stop</tt>, <tt>restart</tt>, <tt>reload</tt>, and
+        <tt>force-reload</tt>), the init script should return an exit status
+        of zero if the action described by the argument has been successful.
+        Otherwise, the init script should print an error message and return
+        one of the following non-zero exit status codes.
+        <taglist>
+          <tag>1</tag>
+          <item>generic or unspecified error,</item>
+          <tag>2</tag>
+          <item>invalid or excess argument(s),</item>
+          <tag>3</tag>
+          <item>unimplemented feature (for example, <tt>reload</tt>),</item>
+          <tag>4</tag>
+          <item>user had insufficient privilege,</item>
+          <tag>5</tag>
+          <item>program is not installed,</item>
+          <tag>6</tag>
+          <item>program is not configured,</item>
+          <tag>7</tag>
+          <item>program is not running,</item>
+          <tag>8-99</tag>
+          <item>reserved for future LSB use,</item>
+          <tag>100-149</tag>
+          <item>reserved for distribution use,</item>
+          <tag>150-199</tag>
+          <item>reserved for application use,</item>
+          <tag>200-254</tag>
+          <item>reserved.</item>
+        </taglist>
+        All error messages should be printed on standard error. All status
+        messages should be printed on standard output. (This does not prevent
+        scripts from calling the logging functions such as
+        <tt>log_failure_msg</tt>).
+      </p>
+
+	  <p>
+        If the status command is given, the init script should return the
+        following exit status codes.
+	    <taglist>
+	      <tag>0</tag>
+	      <item>program is running or service is OK,</item>
+	      <tag>1</tag>
+	      <item>program is dead and /var/run pid file exists,</item>
+	      <tag>2</tag>
+	      <item>program is dead and /var/lock lock file exists,</item>
+	      <tag>3</tag>
+	      <item>program is stopped,</item>
+	      <tag>4</tag>
+	      <item>program or service status is unknown,</item>
+	      <tag>5-99</tag>
+	      <item>reserved for future LSB use,</item>
+	      <tag>100-149</tag>
+	      <item>reserved for distribution use,</item>
+	      <tag>150-199</tag>
+	      <item>reserved for application use,</item>
+	      <tag>200-254</tag>
+	      <item>reserved.</item>
+	    </taglist>
+	  </p>
+
 	  <p>
 	    Often there are some variables in the <file>init.d</file>
 	    scripts whose values control the behaviour of the scripts,
@@ -5640,7 +5705,7 @@
 # Original version by Robert Leslie
 # &lt;rob@mars.org&gt;, edited by iwj and cs
 
-test -x /usr/sbin/named || exit 0
+test -x /usr/sbin/named || exit 5
 
 # Source defaults file.
 PARAMS=''
@@ -5648,6 +5713,14 @@
   . /etc/default/bind
 fi
 
+help () {
+  echo "Usage: /etc/init.d/bind {start|stop|restart|reload|force-reload}" >&2
+}
+
+if [ "$2" ]; then
+  help
+  exit 2
+fi
 
 case "$1" in
 start)
@@ -5676,10 +5749,13 @@
     --pidfile /var/run/named.pid --exec /usr/sbin/named
   echo "."
   ;;
+status)
+  help
+  exit 4
+  ;;
 *)
-  echo "Usage: /etc/init.d/bind " \
-         " {start|stop|restart|reload|force-reload}" >&2
-  exit 1
+  help
+  exit 2
   ;;
 esac
 
9.3. System run levels and `init.d' scripts
-------------------------------------------

9.3.1. Introduction
-------------------

     The `/etc/init.d' directory contains the scripts executed by `init' at
     boot time and when the init state (or "runlevel") is changed (see
     init(8)).

     There are at least two different, yet functionally equivalent, ways of
     handling these scripts.  For the sake of simplicity, this document
     describes only the symbolic link method.  However, it must not be
     assumed by maintainer scripts that this method is being used, and any
     automated manipulation of the various runlevel behaviours by
     maintainer scripts must be performed using `update-rc.d' as described
     below and not by manually installing or removing symlinks.  For
     information on the implementation details of the other method,
     implemented in the `file-rc' package, please refer to the
     documentation of that package.

     These scripts are referenced by symbolic links in the `/etc/rc<n>.d'
     directories.  When changing runlevels, `init' looks in the directory
     `/etc/rc<n>.d' for the scripts it should execute, where `<n>' is the
     runlevel that is being changed to, or `S' for the boot-up scripts.

     The names of the links all have the form `S<mm><script>' or
     `K<mm><script>' where <mm> is a two-digit number and <script> is the
     name of the script (this should be the same as the name of the actual
     script in `/etc/init.d').

     When `init' changes runlevel first the targets of the links whose
     names start with a `K' are executed, each with the single argument
     `stop', followed by the scripts prefixed with an `S', each with the
     single argument `start'.  (The links are those in the `/etc/rc<n>.d'
     directory corresponding to the new runlevel.) The `K' links are
     responsible for killing services and the `S' link for starting
     services upon entering the runlevel.

     For example, if we are changing from runlevel 2 to runlevel 3, init
     will first execute all of the `K' prefixed scripts it finds in
     `/etc/rc3.d', and then all of the `S' prefixed scripts in that
     directory.  The links starting with `K' will cause the referred-to
     file to be executed with an argument of `stop', and the `S' links with
     an argument of `start'.

     The two-digit number <mm> is used to determine the order in which to
     run the scripts: low-numbered links have their scripts run first.  For
     example, the `K20' scripts will be executed before the `K30' scripts.
     This is used when a certain service must be started before another.
     For example, the name server `bind' might need to be started before
     the news server `inn' so that `inn' can set up its access lists.  In
     this case, the script that starts `bind' would have a lower number
     than the script that starts `inn' so that it runs first:
          /etc/rc2.d/S17bind
          /etc/rc2.d/S70inn

     The two runlevels 0 (halt) and 6 (reboot) are slightly different.  In
     these runlevels, the links with an `S' prefix are still called after
     those with a `K' prefix, but they too are called with the single
     argument `stop'.

     Also, if the script name ends `.sh', the script will be sourced in
     runlevel `S' rather that being run in a forked subprocess, but will be
     explicitly run by `sh' in all other runlevels.

9.3.2. Writing the scripts
--------------------------

     Packages that include daemons for system services should place scripts
     in `/etc/init.d' to start or stop services at boot time or during a
     change of runlevel.  These scripts should be named
     `/etc/init.d/<package>', and 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

     `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'
          print the current status of the service.

     The `start', `stop', `restart', `force-reload', and `status' options
     should be supported by all scripts in `/etc/init.d', the `reload'
     option is optional.

     The `init.d' scripts should ensure that they will behave sensibly 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'.

     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 Section
     10.7, `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 her 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 5

     In the case of init script commands other than `status' (i.e.,
     `start', `stop', `restart', `reload', and `force-reload'), the init
     script should return an exit status of zero if the action described by
     the argument has been successful.  Otherwise, the init script should
     print an error message and return one of the following non-zero exit
     status codes.

     1
          generic or unspecified error,

     2
          invalid or excess argument(s),

     3
          unimplemented feature (for example, `reload'),

     4
          user had insufficient privilege,

     5
          program is not installed,

     6
          program is not configured,

     7
          program is not running,

     8-99
          reserved for future LSB use,

     100-149
          reserved for distribution use,

     150-199
          reserved for application use,

     200-254
          reserved.

     All error messages should be printed on standard error.  All status
     messages should be printed on standard output.  (This does not prevent
     scripts from calling the logging functions such as `log_failure_msg').

     If the status command is given, the init script should return the
     following exit status codes.

     0
          program is running or service is OK,

     1
          program is dead and /var/run pid file exists,

     2
          program is dead and /var/lock lock file exists,

     3
          program is stopped,

     4
          program or service status is unknown,

     5-99
          reserved for future LSB use,

     100-149
          reserved for distribution use,

     150-199
          reserved for application use,

     200-254
          reserved.

     Often there are some variables in the `init.d' scripts whose values
     control the behaviour 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 `sh' format.
     It may either be a `conffile' or a configuration file maintained by
     the package maintainer scripts.  See Section 10.7, `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.

9.3.3. Interfacing with the initscript system
---------------------------------------------

     Maintainers should use the abstraction layer provided by the
     `update-rc.d' and `invoke-rc.d' programs to deal with initscripts in
     their packages' scripts such as `postinst', `prerm' and `postrm'.

     Directly managing the /etc/rc?.d links and directly invoking the
     `/etc/init.d/' initscripts should be done only by packages providing
     the initscript subsystem (such as `sysv-rct' and `file-rc').

9.3.3.1. Managing the links
---------------------------

     The program `update-rc.d' is provided for package maintainers to
     arrange for the proper creation and removal of `/etc/rc<n>.d' symbolic
     links, or their functional equivalent if another method is being used.
     This may be used by maintainers in their packages' `postinst' and
     `postrm' scripts.

     You must not include any `/etc/rc<n>.d' symbolic links in the actual
     archive or manually create or remove the symbolic links in maintainer
     scripts; you must use the `update-rc.d' program instead.  (The former
     will fail if an alternative method of maintaining runlevel information
     is being used.) You must not include the `/etc/rc<n>.d' directories
     themselves in the archive either.  (Only the `sysvinit' package may do
     so.)

     By default `update-rc.d' will start services in each of the multi-user
     state runlevels (2, 3, 4, and 5) and stop them in the halt runlevel
     (0), the single-user runlevel (1) and the reboot runlevel (6).  The
     system administrator will have the opportunity to customize runlevels
     by simply adding, moving, or removing the symbolic links in
     `/etc/rc<n>.d' if symbolic links are being used, or by modifying
     `/etc/runlevel.conf' if the `file-rc' method is being used.

     To get the default behavior for your package, put in your `postinst'
     script
          		update-rc.d <package> defaults
     and in your `postrm'
          		if [ "$1" = purge ]; then
          		update-rc.d <package> remove
          		fi
     .  Note that if your package changes runlevels or priority, you may
     have to remove and recreate the links, since otherwise the old links
     may persist.  Refer to the documentation of `update-rc.d'.

     This will use a default sequence number of 20.  If it does not matter
     when or in which order the `init.d' script is run, use this default.
     If it does, then you should talk to the maintainer of the `sysvinit'
     package or post to `debian-devel', and they will help you choose a
     number.

     For more information about using `update-rc.d', please consult its
     manpage update-rc.d(8).

9.3.3.2. Running initscripts
----------------------------

     The program `invoke-rc.d' is provided to make it easier for package
     maintainers to properly invoke an initscript, obeying runlevel and
     other locally-defined constraints that might limit a package's right
     to start, stop and otherwise manage services.  This program may be
     used by maintainers in their packages' scripts.

     The use of `invoke-rc.d' to invoke the `/etc/init.d/*' initscripts is
     strongly recommended[1], instead of calling them directly.

     By default, `invoke-rc.d' will pass any action requests (start, stop,
     reload, restart...) to the `/etc/init.d' script, filtering out
     requests to start or restart a service out of its intended runlevels.

     Most packages will simply need to change:
          /etc/init.d/<package>
          	      <action>
     in their `postinst' and `prerm' scripts to:
                    if [ -x /usr/sbin/invoke-rc.d ] ; then
          		invoke-rc.d <package> <action>
                    else
                       /etc/init.d/<package> <action>
                    fi

     A package should register its initscript services using `update-rc.d'
     before it tries to invoke them using `invoke-rc.d'.  Invocation of
     unregistered services may fail.

     For more information about using `invoke-rc.d', please consult its
     manpage invoke-rc.d(8).

[1]  In the future, the use of invoke-rc.d to invoke initscripts shall be
     made mandatory.  Maintainers are advised to switch to invoke-rc.d as
     soon as possible.

9.3.4. Boot-time initialization
-------------------------------

     There used to be another directory, `/etc/rc.boot', which contained
     scripts which were run once per machine boot.  This has been
     deprecated in favour of links from `/etc/rcS.d' to files in
     `/etc/init.d' as described in Section 9.3.1, `Introduction'.  Packages
     must not place files in `/etc/rc.boot'.

9.3.5. Example
--------------

     The `bind' DNS (nameserver) package wants to make sure that the
     nameserver is running in multiuser runlevels, and is properly shut
     down with the system.  It puts a script in `/etc/init.d', naming the
     script appropriately `bind'.  As you can see, the script interprets
     the argument `reload' to send the nameserver a `HUP' signal (causing
     it to reload its configuration); this way the system administrator can
     say `/etc/init.d/bind reload' to reload the name server.  The script
     has one configurable value, which can be used to pass parameters to
     the named program at startup; this value is read from
     `/etc/default/bind' (see below).

#!/bin/sh
#
# Original version by Robert Leslie
# <rob@mars.org>, edited by iwj and cs

test -x /usr/sbin/named || exit 5

# Source defaults file.
PARAMS=''
if [ -f /etc/default/bind ]; then
  . /etc/default/bind
fi

help () {
  echo "Usage: /etc/init.d/bind {start|stop|restart|reload|force-reload}" >&2
}

if [ "$2" ]; then
  help
  exit 2
fi

case "$1" in
start)
  echo -n "Starting domain name service: named"
  start-stop-daemon --start --quiet --exec /usr/sbin/named \
                    -- $PARAMS
  echo "."
  ;;
stop)
  echo -n "Stopping domain name service: named"
  start-stop-daemon --stop --quiet  \
    --pidfile /var/run/named.pid --exec /usr/sbin/named
  echo "."
  ;;
restart)
  echo -n "Restarting domain name service: named"
  start-stop-daemon --stop --quiet --oknodo \
    --pidfile /var/run/named.pid --exec /usr/sbin/named
  start-stop-daemon --start --verbose --exec /usr/sbin/named \
                    -- $PARAMS
  echo "."
  ;;
force-reload|reload)
  echo -n "Reloading configuration of domain name service: named"
  start-stop-daemon --stop --signal 1 --quiet  \
    --pidfile /var/run/named.pid --exec /usr/sbin/named
  echo "."
  ;;
status)
  help
  exit 4
  ;;
*)
  help
  exit 2
  ;;
esac

exit 0

     Complementing the above init script is a configuration file
     `/etc/default/bind', which contains configurable parameters used by
     the script.  This would be created by the `postinst' script if it was
     not already present, and removed on purge by the `postrm' script.
          # Specified parameters to pass to named. See named(8).
          # You may uncomment the following line, and edit to taste.
          #PARAMS="-u nobody"

     Another example on which you can base your `/etc/init.d' scripts is
     found in `/etc/init.d/skeleton'.

     If this package is happy with the default setup from `update-rc.d',
     namely an ordering number of 20 and having named running in all
     runlevels, it can say in its `postinst':
          update-rc.d bind defaults >/dev/null
     And in its `postrm', to remove the links when the package is purged:
          if [ "$1" = purge ]; then
            update-rc.d bind remove >/dev/null
          fi

Attachment: pgphDcpCxH9qo.pgp
Description: PGP signature


Reply to: