How To Create RPMs and Init Scripts That Are Compatible On Both SUSE Linux and Red Hat Linux

SUSE by default is LSB compliant. Red Hat is LSB compliant if the lsb.rpm is installed (which is not by default). The best solution is to create LSB compliant rpms and init scripts and require lsb.rpm to be pre-installed on Red Hat systems. However, for various reasons sometimes this requirement cannot be enforced. To create rpms and init scripts that can be installed on default Red Hat and SUSE (LSB) systems requires knowing how to support both environments. This document outlines how to create such init scripts and rpms.

If you follow the LSB specification while developing your rpms and init scripts, your work to support SUSE(LSB) and LSB compliant systems is simplified and you only need to worry about whether or not you want to support SUSE specific features (e.g. YaST etc.). IBM and others have created an excellent
guide that outlines the steps necessary for developing LSB compliant applications.

SUSE by default is LSB compliant. Red Hat is also LSB compliant if lsb.rpm is installed. However, by default Red Hat does not install lsb.rpm. Sometimes the requirement to have lsb.rpm installed on Red Hat systems cannot be enforced.

To create rpms and init scripts that can be used on default Red Hat (without lsb.rpm being installed) and SUSE (LSB) requires knowing how to support both environments. This document outlines how to create such init scripts and rpms.

Init Scripts

Red Hat's specific handling of init scripts is different than how SUSE (LSB) handles them. It is possible to code for both the Red Hat's (using chkconfig) way of doing things as well as to follow the LSB specification.

First: The Comment Block

Near the top of the init script, you need to include comment blocks such as the following:

For LSB 1.3 compliant systems you should use the X-UnitedLinux-Should-Start tag instead of the new LSB 2.0 Should-Start. Basically both keywords mean that nthd should start before novell-thingy if nthd is present on the system. If nthd is not on the system, the init script will still continue.

The item(s) that are provided via the Provides directive must be unique.
It is wise to prefix them with a LANANA approved name (i.e. "novell-") to ensure uniqueness.

The 'K' means that the script is executed with a "stop" argument when leaving the runlevel. A 'S' means the script is executed with a "start" argument when entering the runlevel. The numbers determine the order in which the scripts are executed. The number field (e.g the 17 in S17novell-thingy) doesn't mean that the init script is the nth script invoked, it just means that the init script starts after any lower number specified init script and before any higher numbered init script.

On Red Hat systems using chkconfig you have explicit control over these numbers. You are responsible to make sure that you use a higher start number than the services you require started before yours (and vice-a-versa for stopping services).

With SUSE (LSB) you do not have explicit control. Instead you must list your dependencies using the Required-Start and Required-Stop keywords (Should-Start and Should-Stop can also be used in LSB 2.0 systems). When SUSE init script tools (insserv, etc.) are run they handle the numerical ordering of the symbolic links for you based on the dependency information you provide in the init script.

In the previous comment block example, the line:

Required-Start: $local_fs $network $syslog

indicates, by start order, that local_fs, network and syslog services must be running before the current service is started. The Required-Stop keyword indicates what services must still be running during the shutdown of the service (however, this is currently ignored in SUSE; the reverse order of the Required-Start is used instead).

RPM Issues

To ensure that an rpm behaves the same in Red Hat and SUSE (LSB) there are a couple of changes that need to be made.

First: RPM %post scripts

In the rpm %post script you can enable services to be started automatically when the OS boots.

Point 1:

On SUSE you must use their utilities to install and remove the init scripts. If you don't use them, the system won't know that the service is enabled. For instance,
if nthd is installed but the symlinks are created through means other than install_initd, SUSE won't know that nthd is enabled at boot-time. When an application is installed that has a service listed in Required-Start, install_initd will fail to enable the service at boot-time because it thinks that service isn't enabled yet.

Also note that you must include INIT INFO comments in your init script on SUSE. If you don't, the next time insserv (install_initd) is executed your symlinks will be re-numbered to S01.

Point 2:

Avoid the following in your init scripts:

Don't include the symlinks in /etc/rc.d/rc?.d in the %files section of the spec file.

Don't install an init script on SUSE that doesn't have INIT INFO comments.

Don't create symlinks in /etc/rc.d/rc?.d on SUSE by any means other then /usr/lib/lsb/install_initd.

Point 3:

Naming conventions and return codes for init scripts:

There are certain actions that should be supported by init scripts (see the LSB specification).

The return codes for those actions are also specified in the LSB specification.

Use LSB/LANANA naming for init scripts to avoid collisions.

Point 4:

There are also bash functions specified in the LSB specification that are available to be used in init scripts. It is also useful to have a common set of function names that can be used in init scripts that can be used on either platform.

Adhering to the LSB specifications is the best way to create init scripts and rpms. However, when LSB system compliance cannot be assured, the information contained in this document can be used to mitigate the differences between Red Hat specific conventions and SUSE (LSB) when creating init scripts and rpms.