Packaging/SUSE Package Conventions/Init Scripts

From openSUSE

7.Init Scripts

Prev

Next



Contents

7. Init Scripts


This section describes how to name, create, and install init scripts on SUSE Linux. They are LSB compilant, as explained at http://refspecs.freestandards.org/LSB_2.0.1/LSB-generic/LSB-generic/sysinit.html.


7.1. Name


The name of init scripts must be LSB compliant, so it must be listed at http://www.lanana.org/lsbreg/init/init.txt. A new name can be registered as described at http://www.lanana.org/lsbreg/instructions.html.


7.2. Structure


The structure of init scripts is well described in /etc/init.d/skeleton. This file can also be used as an efficient template for new init scripts.

Init scripts are shell scripts, so the file begins with the usual header:

#!/bin/sh

or

#!/bin/bash

Then there are usually comments. These should mention the information about author, copyright, or license. The file must include a special comment header providing some meta information about the init script. See [[SUSE_Package_Conventions/Init_Scripts#spc_is_comment_conventions Section�7.3, “Comment Conventions”] for more details. See also the [spc_init_scripts.html#spc_is_default_facilities list of default facilities] that are available on SUSE.

This example is taken from /etc/init.d/esound:

# Copyright (c) 1995-2002 SUSE Linux AG, Nuernberg, Germany.
 # All rights reserved.
 #
 # Author: Stanislav Brabec, feedback to http://www.suse.de/feedback
 #
 ### BEGIN INIT INFO
 # Provides:          esound
 # Required-Start:    alsasound
 # Should-Start:      $network portmap
 # Required-Stop:     alsasound
 # Should-Stop:      $network portmap
 # Default-Start:     5
 # Default-Stop:
 # Short-Description: Sound daemon with network support
 # Description:       Starts esound server to allow remote access to sound
 #       card. To use esound locally, you do not need to start this
 #       server on boot. You should edit server settings before
 #       starting it via sysconfig editor: Network/Sound/Esound
 ### END INIT INFO

Then there are usually checks of whether the service is correctly installed and the related sysconfig files are read. The LSB compliant error values must be returned in case of problems. See [[SUSE_Package_Conventions/Init_Scripts#spc_is_exit_status_codes Section�7.6, “Exit Status Codes”] for more details.

This example is taken from /etc/init.d/ypbind:

YPBIND_BIN=/usr/sbin/ypbind
 test -x $YPBIND_BIN || { echo "$YPBIND_BIN not installed";
         if [ "$1" = "stop" ]; then exit 0; else exit 5; fi; }
 
 YPBIND_CONFIG=/etc/sysconfig/ypbind
 test -r $YPBIND_CONFIG || { echo "$YPBIND_CONFIG not existing";
         if [ "$1" = "stop" ]; then exit 0; else exit 6; fi; }
 
 # Read config
 . $YPBIND_CONFIG

Then the rc status functions are usually sourced and the rc status is reset. This example is taken from /etc/init.d/network:

. /etc/rc.status
rc_reset

Then the required actions are implemented. See /etc/init/d/skeleton, which contains a sample code and includes some valuable comments. The following example is taken from /etc/init.d/cron:

case "$1" in
    start)
        echo -n "Starting CRON daemon"
        startproc $CRON_BIN
        rc_status -v
        ;;
    stop)
        echo -n "Shutting down CRON daemon"
        killproc -TERM $CRON_BIN
        rc_status -v
        ;;
    try-restart)
        $0 status >/dev/null &&  $0 restart
        rc_status
        ;;
    restart)
        $0 stop
        $0 start
        rc_status
        ;;
    force-reload)
        echo -n "Reload service Cron"
        checkproc $CRON_BIN
        rc_status -v
        ;;
    reload)
        rc_status -v
        ;;
    status)
        echo -n "Checking for Cron: "
        checkproc $CRON_BIN
        rc_status -v
        ;;
    probe)
        ;;
    *)
        echo "Usage: $0 {start|stop|status|try-restart|\
restart|force-reload|reload|probe}"
        exit 1
        ;;
esac

Finally, the init scripts must end with the correct exit status. Therefore, the function rc_exit is usually the last command.


7.3. Comment Conventions


Init scripts are shell scripts, so the comments are delimited by a '#' and can be used without any limitation. There is only one exception; LSB defines a special comment header to provide some meta information about the init script. This header must be included in all init scripts and has the following structure:

### BEGIN INIT INFO
 # Provides:                   boot_facility_1 [ boot_facility_2 ...]
 # Required-Start:             boot_facility_1 [ boot_facility_2 ...]
 # Should-Start:               boot_facility_1 [ boot_facility_2 ...]
 # Required-Stop:              boot_facility_1 [ boot_facility_2 ...]
 # Should-Stop:                boot_facility_1 [ boot_facility_2 ...]
 # Default-Start:              run_level_1 [ run_level_2 ...]
 # Default-Stop:               run_level_1 [ run_level_2 ...]
 # Short-Description:          single_line_description
 # Description:                multiline_description
 ### END INIT INFO

These keywords have the following meaning:


  • Provides defines names of facilities started by this script. It is usually the name of the daemon. If more than one package can provide the same facility (e.g., sendmail vs. postfix, dhcpcd vs. dhclient), the init scripts of both should provide the same facility name.
  • Required-Start defines which facilities must be available to start and run this service. The init script system should make sure that the required facilities are started before this one.
  • Should-Start is an optional field. The function is similar to Required-Start, but it does not define a hard dependency. If a service in Should-Start is not installed or enabled to start, it is silently ignored.
  • Required-Stop defines which facilities must still be available during the shutdown of that service. The init script system should avoid stopping scripts that provide those facilities until this init script is stopped.

This header is currently ignored on SUSE Linux, because the SUSE boot script concept uses a different link scheme (see the init.d(7) man page).

  • Should-Stop is an optional field. The function is similar to Required-Stop, but it does not define a hard dependency. If a service in Should-Stop is not installed or enabled to start, it is silently ignored.
  • Default-Start defines in which runlevels the script should start by default. The runlevels have changed from SUSE Linux 7.1.
  • Default-Stop defines in which runlevels the script should stop by default.

This header is currently ignored on SUSE Linux, because the SUSE boot script concept uses a different link scheme (see the init.d(7) man page).

  • Short-Description defines a single-line description of the function of this facility. It is displayed, for example, in the YaST Runlevel Editor.
  • Description is a multiline description of the function of this facility. Each continuation line must begin with a '#' followed by a tab character or at least two space characters. The multiline description is terminated by the first line that does not match this criteria. This information is also displayed in the YaST runlevel editor.


LSB allows defining distribution-specific extensions to this header. Such keywords are prefixed by X-VendorTag-. The following keywords are available on SUSE Linux:


  • X-SuSE-Should-Start has the same meaning as Should-Start. It has been obsolete since LSB 2.0 included Should-Start.
  • X-SuSE-Should-Stop has the same meaning as Should-Stop. It has been obsolete since Should-Stop became part of LSB 2.0.
  • X-UnitedLinux-Default-Enabled defines if the service should be enabled by default. The possible values are yes or no. Primarily, it was made for United Linux but it is usable also on SUSE Linux products.
  • X-UnitedLinux-Should-Start is the same as X-SuSE-Should-Start but used on United Linux.
  • X-UnitedLinux-Should-Stop is the same as X-SuSE-Should-Stop but used on United Linux.


7.4. Default Facilities


As required by LSB, SUSE Linux init scripts already provide some default facility names. These are defined in /etc/insserv.conf. At the moment, the following system facility names are provided:


  • $local_fs — All local file systems are mounted. Most services should need this.
  • $remote_fs — All remote file systems are mounted. Because /usr may be remote, many services should need this as well.
  • $syslog — The system logging facility is up.
  • $network — Low level networking (eth card, etc.) is up.
  • $named — Hostname resolution is available.
  • $netdaemons — All network daemons are running. This was removed in LSB 1.2. For now, it still available for backward compatibility.
  • $time — The system time has been set correctly.
  • $portmap — SunRPC portmapping service is available.


7.5. Actions


As defined by the LSB, all init scripts should know how to handle the following arguments:


  • start — Starts the service.
  • stop — Stops the service.
  • restart — Stops and restarts the service if it is already running. Otherwise, starts the service.
  • reload — Causes the configuration of the service to be reloaded without actually stopping and restarting the service.
  • force-reload — Causes the configuration to be reloaded if the service supports this. Otherwise, the service is restarted.
  • status — Prints the current status of the service.


The start, stop, restart, force-reload, and status actions must be supported by all init scripts. The reload action is optional.

SUSE defines the following additional actions:


  • try-restart — Restarts the service only if it was active before. This action is now part of LSB (as of 1.9). Red Hat has a similar action named condrestart.
  • probe — Probes for the necessity of a reload. Depending on the service, prints "reload" or "restart" if a reload is required. Nothing is printed if a reload is not required. This action is optional and is not part of LSB (as of 1.9).


7.6. Exit Status Codes


LSB defines the following exit status codes for init scripts:


Exist Status Code

Description

0

success

1

generic or unspecified error

2

invalid or excess arguments

3

unimplemented feature (e.g., "reload")

4

user had insufficient privileges

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


Starting an already running service, stopping or restarting a not-running service, and restart with force-reload (in case signaling is not supported) are considered a success.

7.7. Status Functions


The functions defined in /etc/rc.status help record, display, and return the actual rc status information in init scripts. They can be sourced into the init scripts this way:

. /etc/rc.status

The following functions are available:

rc_active

This function checks whether a service is enabled (by symlinks). It returns “0” if the service is enabled in a runlevel and returns “1” otherwise.

rc_exit

This function terminates an init script with the exit status appropriate to the overall rc status.

rc_failed [num]

This function sets the local and the overall rc status to a selected value defined by the parameter num. The value “1” is used by default.

rc_check

This function checks the exit status of the last command ($?) and sets the local rc status to this value if the value is different from “0”. Then it sets the overall rc status to the value of the local rc status if it differs from “0”. This function is used internally by other rc status functions.

rc_reset

This function sets both the local and the overall rc status to “0”.

rc_status [-r] [-s] [-u] [-v[num]]

This function checks, sets, and displays the rc status. By default, it is quiet: it only calls rc_check. So, it must be called with an option to display the status. The options have the following meaning:


  • -r calls rc_reset. This option is usable together with -v. The command rc_status -v -r checks, sets, and displays the current rc status. Then rc_reset is called.
  • -s displays “skipped” and sets the status to “3”. It means an unimplemented feature.
  • -u displays “unused” and sets the status to “3”. It means an unimplemented feature.
  • -v[num] displays the actual status and resets local status to “0”. By default, the status is displayed on the actual line. The parameter num defines that it should display num lines above the actual cursor position.

7.8. Installation


The init script is usually included in the package sources and an extra source file. It is installed in the %install section and marked as %config in the %files section.

There could also be a symlink named rcname pointing to /etc/init.d/name. The symlink is located either in /sbin or in /usr/sbin depending on the prefix where the service is installed. It is useful for init scripts that can be started, stopped, restarted by hand.

Finally, the init script can be enabled after the package is installed and must be disabled after the package is removed. The service should be restarted after an update and should be stopped before the package is removed. The macros [[SUSE_Package_Conventions/RPM_Macros#spc_rm_fillup_and_insserv %fillup_and_insserv], [spc_rpm_macros.html#spc_rm_insserv_force_if_yast %insserv_force_if_yast], [spc_rpm_macros.html#spc_rm_restart_on_update %restart_on_update], [spc_rpm_macros.html#spc_rm_insserv_cleanup %insserv_cleanup], and [spc_rpm_macros.html#spc_rm_stop_on_removal %stop_on_removal] are intended for this purpose.

Note that SUSE Linux provides the utility insserv to enable or disable init scripts. Refer to the manual page of insserv(8) for more detailed information. This utility is also used by the macros %fillup_and_insserv, %insserv_force_if_yast, and %insserv_cleanup.

The init scripts are disabled by default on SUSE Linux, except those that are necessary for minimal system functionality. Therefore the %fillup_and_insserv and %insserv_force_if_yast macros are used only in packages providing such base services. However, they are also used by packages that added an init script before SUSE Linux 8.0. Another approach was used then to enable services and insserv must be run to update the setting. See the notes at the end of this section for more details.

This example is taken from the package ypserv:

Source1:      ypserv.init
Source2:      yppasswdd.init
Source3:      ypxfrd.init
[...]
%install
[...]
mkdir -p $RPM_BUILD_ROOT/etc/init.d
install -m 755 %SOURCE1 $RPM_BUILD_ROOT/etc/init.d/ypserv
install -m 755 %SOURCE2 $RPM_BUILD_ROOT/etc/init.d/yppasswdd
install -m 755 %SOURCE3 $RPM_BUILD_ROOT/etc/init.d/ypxfrd
[...]
ln -sf ../../etc/init.d/yppasswdd       $RPM_BUILD_ROOT/usr/sbin/rcyppasswdd
ln -sf ../../etc/init.d/ypxfrd          $RPM_BUILD_ROOT/usr/sbin/rcypxfrd
ln -sf ../../etc/init.d/ypserv          $RPM_BUILD_ROOT/usr/sbin/rcypserv
[...]
%post
%{fillup_and_insserv ypserv ypxfrd yppasswdd}

%preun
%stop_on_removal ypserv ypxfrd yppasswdd

%postun
%restart_on_update ypserv ypxfrd yppasswdd
%insserv_cleanup

%files
%defattr(-,root,root)
[...]
%config /etc/init.d/yppasswdd
%config /etc/init.d/ypserv
%config /etc/init.d/ypxfrd
[...]
/usr/sbin/rcyppasswdd
/usr/sbin/rcypserv
/usr/sbin/rcypxfrd

The names of init scripts must be listed as parameters of the related macros if they must be enabled, restarted, or stopped. The only difference is the macro %insserv_cleanup. It does not need any parameters because it removes all dangling symlinks anyway.


Note

Prior to SUSE Linux 8.0, another concept was used to enable services in runlevels. They were not enabled by insserv but by START variables located in /src/rc_config (/etc/rc_config was a predecessor of [[SUSE_Package_Conventions/Sysconfig /etc/sysconfig]). The variables were named START_XXX, where XXX was typically the uppercase name of the init script. They were set to “yes” or “no”, where “yes” meant that the service was enabled.

Technically, each package providing an init script called insserv in its %post script. So, all services were “enabled” and the init scripts were always launched in the defined runlevels. Then the init scripts sourced /etc/rc_config at the beginning and stopped processing if the related START variable was set to “no”.

Prior to SUSE Linux 8.0, the command sbin/insserv etc/init.d was called in the %preun section. This does not make any sense, because insserv does nothing because all files of the package are still present at that time. %insserv_cleanup must be called in %postun.




Prev

Next

6. SuSEconfig (deprecated)

Home

8. Cron Jobs