Linux.com

Feature

Managing Linux daemons with init scripts

By Brian K. Jones on August 10, 2005 (8:00:00 AM)

Share    Print    Comments   

When you install a new Linux server distribution, you can often install all of the daemons you'll need to run on that machine at install time. Distribution vendors present a "ready to go" distribution by supplying initialization scripts for all of the services you might run. But what happens if you're building from source, and no init script is supplied? What if you're writing the source and haven't ever built an init script? Here are a few ways to cope when you're faced with this challenge.

You can handle initialization in several different ways. One option is to place the commands used to start up a daemon into /etc/rc.d/rc.local file. This method is very simple: Cut and paste the instructions the README gives to start the daemon, and that's your initialization. Unfortunately, this method goes against what most systems are set up to do by default, which is to use init scripts.

Using the rc.local method also forces you to forgo some flexibility afforded by init scripts, or to hack your own functionality into a wrapper startup script that is called in rc.local. I've seen this done, but it's largely a duplication of effort.

Another method is to start your daemon directly from the /etc/inittab file. More than a few administrators use this technique, but I don't recommend it for an environment of several servers (or more) maintained by several administrators, for a couple of reasons.

Reason one is consistency. If possible, you should manage every daemon on every server using the same procedure. The only thing that should change in the commands run is the name of the daemon.

The second reason, which relates to consistency, is manageability in the event of your demise. If you're the only administrator, then this is a moot point. However, unless you require every administrator to know the intricacies of every daemon running in the environment, running things out of inittab is not a great idea. Manageability, as a goal of a systems management group, is not something that a single admin can handle. Manageability spans the entire group responsible for the welfare of the systems and services they maintain. Of course, good admins also document procedures.

Init scripts are your friend because they represent an efficient use of the resources given to an administrator with which to manage the startup and shutdown of daemons. Distribution vendors have largely standardized on initialization scripts around which to build their daemon management tools, and they've put a great deal of work into make managing daemons as simple as possible. Even if you have an init-scriptless daemon, putting together an init script to be managed by the normal system tools and procedures is easy.

Let's go over the process of creating an init script. You'll see how easy this procedure is, and discover functionality that makes you rethink how you manage daemons.

Creating your own init script

I'm going to review this process based on a real-life experience. I'm using the newly released Fedora Directory Server on production Red Hat Advanced Server machines. I've downloaded and installed the binary RPM packages and tested that it works. The next step is to make sure it's manageable in a way that is consistent with everything else on the system. What to do?

I created my own init script. The first thing I did was look for something I could use as a template. If you know that your daemon has similar demands to another daemon, you can use the init script from that daemon as a template. In this case, I simply copied the init script template that comes with my Linux distribution, which is in /usr/share/doc/initscript package/sysvinitfiles. Here's what I took from that file:

#!/bin/bash
#
#       /etc/rc.d/init.d/
#
#
#
#
#

# Source function library.
. /etc/init.d/functions



start() {
        echo -n "Starting : "

        touch /var/lock/subsys/
        return
}

stop() {
        echo -n "Shutting down : "

        rm -f /var/lock/subsys/
        return
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    status)

        ;;
    restart)
        stop
        start
        ;;
    reload)

tart)

        [ -f /var/lock/subsys/ ] && restart || :
    probe)

        ;;
    *)
        echo "Usage:  {start|stop|status|reload|restart[|probe]"
        exit 1
        ;;
esac
exit $?

As you can see, all of the structure for an init script is already in place, and the functions and other bits of code you'll need are stubbed out, just waiting for you to fill in the blanks.

The most important line sits at the top of the file, as unassuming as can be. It's the one that sources the file /etc/init.d/functions. This file is filled with simple but useful bash shell functions that are ready for use in your init script. If you've never noticed this file, read it! Even if you don't use the stuff, it will give you insight into how your system does things, and it can explain why some boot time or shutdown time errors occur.

Here's my finished init script, which is currently in use on my almost-production servers:


#!/bin/bash
#
#       /etc/rc.d/init.d/ns-slapd
# ns-slapd      This shell script takes care of starting and stopping
#               ns-slapd (the Fedora Directory Server)
#
# Author: Brian Jones jonesy@cs.princeton.edu
#
# chkconfig: 2345 13 87
# description: ns-slapd is the Fedora Directory Service daemon. \
# FDS can serve as a repository for (and, subsequently, a source of) \
# data for most of the resources listed in /etc/nsswitch.conf, such as \
# passwd or group entries.

# Source function library.
. /etc/init.d/functions

SLAPD_HOST=`hostname -a`
SLAPD_DIR=/opt/fedora-ds/bin/slapd/server
PIDFILE=$SLAPD_DIR/logs/pid
STARTPIDFILE=$SLAPD_DIR/logs/startpid

if [ -f /etc/sysconfig/ns-slapd ]; then
        . /etc/sysconfig/ns-slapd
fi


start() {
        echo -n "Starting Fedora Directory Server: "
        if [ -f $STARTPIDFILE ]; then
                PID=`cat $STARTPIDFILE`
                echo ns-slapd already running: $PID
                exit 2;
        elif [ -f $PIDFILE ]; then
                PID=`cat $PIDFILE`
                echo ns-slapd already running: $PID
                exit 2;
        else
                cd $SLAPD_DIR
                daemon  ./ns-slapd $OPTIONS
                RETVAL=$?
                echo
                [ $RETVAL -eq 0 ] && touch /var/lock/subsys/ns-slapd
                return $RETVAL
        fi

}

stop() {
        echo -n "Shutting down Fedora Directory Server: "
        echo
        killproc ns-slapd
        echo
        rm -f /var/lock/subsys/ns-slapd
        return 0
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    status)
        status ns-slapd
        ;;
    restart)
        stop
        start
        ;;
    *)
        echo "Usage:  {start|stop|status|restart}"
        exit 1
        ;;
esac
exit $?

The three functions I use in my script are killproc, status, and daemon. You have to be careful that you know both what the functions do, and what your application's default behavior is. For example, the function that attempts to grab the PID of the running process, pidofproc, assumes that the process writes a pid file somewhere under /var/run. For all other daemons on my system, this works, and I've requested that the Directory Server folks do this as well. (Right now there are pid files, but they're managed within the directory hierarchy where the daemon lives, under /opt/fedora-ds.)

Also, notice that this script will work with the chkconfig command, as denoted by the line reading chkconfig: 2345 13 87. After that, just run chkconfig add scriptname . This script also works with the service command on systems that have it (including Fedora and, I think, SUSE), which is a useful tool in the sysadmin's arsenal. It serves as a shortcut -- instead of typing cd /etc/init.d; ./mydaemon status, or /etc/init.d/mydaemon status, you can type service mydaemon status from whatever your working directory happens to be.

One last note about this simple example concerns the line that reads . /etc/sysconfig/ns-slapd. If the file exists, it will be used to pass arguments to the daemon when I start it. I've used this file to take the default arguments the server normally starts with and put them in their own file; this keep admins from having to edit init scripts, and lets them easily add items to the file later, just as we add options to other daemons on the system. My file contains a single line, which reads OPTIONS="-D /opt/fedora-ds/slapd-ldap -i /opt/fedora-ds/slapd-ldap/logs/pid -w /opt/fedora-ds/slapd-ldap/logs/startpid". This option line gets tagged right onto the end of the command that starts the daemon.

This whole process seems like it should have been lengthy, but it took only about 30 minutes, and that includes some troubleshooting related to Fedora Directory Server's unusually self-contained install structure. With a simple daemon that more or less follows the rules, it shouldn't take you more than 10 minutes to integrate it into the mechanisms used to manage services on your Linux server.

Share    Print    Comments   

Comments

on Managing Linux daemons with init scripts

Note: Comments are owned by the poster. We are not responsible for their content.

Consider using start-stop-daemon

Posted by: Anonymous Coward on August 11, 2005 03:33 PM
Rather than killing off all processes using killproc (which for example doesn't happen to be available on my Gentoo system), you could use the much more powerful start-stop-daemon coming from the Debian distribution.

The recent versions are able to (among other things) - create the PID file
- stop the daemon based on the PID found inside that file
- do chuid and chgid calls
- either chroot or working directory
- seng signals to reload the config rather than restart

By doing slight changes to the source code, it rungs fine on Solaris based servers too.

The article might be a good starting point, but especially the "rm -rf" approach doesn't make me feel very relieved.

#

What are trying to tell us ?

Posted by: Anonymous Coward on August 11, 2005 04:17 PM
Another article by someone who thinks RH is Linux.
Nope, RH isn't Linux, RH is just one of the many distributions.

If you want to write about startup scripts and the like, please so a better job and write about the mechanisms that are involved here. We're able to do a little bit more than copy paste, you know ?

#

Re:What are trying to tell us ?

Posted by: Anonymous Coward on August 13, 2005 12:57 AM
I totally agree.

Not only is it a cut and paste job but the article also makes the assumption that every distribution uses the same init script system. Which anyone who knows anything about Linux knows is not true.

An entirely useless article. imho.

#

Potential hazard in Redhat init-scripts

Posted by: Anonymous Coward on August 11, 2005 05:20 PM
If you look carefully at the example init-script, you'll see these lines:

touch<nobr> <wbr></nobr>/var/lock/subsys/ns-ldap
rm -f<nobr> <wbr></nobr>/var/lock/subsys/ns-ldap

(The file, in this example ns-ldap, must have the same name as your init-script in<nobr> <wbr></nobr>/etc/init.d)

Be aware that if this file doesn't exist, the daemon WILL NOT be stopped at shutdown/reboot. This can be potentially hazardous, if your application does essential cleanup at shutdown.

Likewise, if this file exists at boot, many daemons WILL NOT start.

#

On the service command

Posted by: Administrator on August 17, 2005 01:44 PM
Besides Fedora and SuSE, it's also found in any Linux distribution I know of that is RPM based. Meaning Mandriva, PCLinuxOS and others. In all of those it is supplied by initscripts in all of them AFAIK.

#

This story has been archived. Comments can no longer be posted.



 
Tableless layout Validate XHTML 1.0 Strict Validate CSS Powered by Xaraya