< Zurück | Inhalt | Weiter >

20.5.1 System V Init System

Virtually all Linux distributions use some variant of the System V init system to create and customize programs and services that run at the startup of the box. Now, we don’t want to write a Linux system administration manual, but we do need to tell you enough to decide how to make JBoss available when needed on your server.

The core of the System V init system is the /etc/inittab file. Everything else devolves from this configuration file. In the days before network services, the primary startup tasks were to get getty programs running and then run a single startup shell script. The /etc/inittab file handles these tasks beautiful- ly. Since then, the world of UNIX and Linux has become a complex mixture of client-server programs and protocols, so a complex set of conventions has been developed to turn the primitive /etc/inittab into a much richer set of


controls. Let’s take a very brief look at /etc/inittab and how it works; then we’ll move on to the extended scripts that manage server processes. That is where we will integrate JBoss.

A key concept in the System V init system is the runlevel. The idea is that a system can have a number of “standard” configurations, numbered from 0 to 6, where 0 is shutdown, 1 is single-user, 2 to 5 are up to the system administra- tor, and 6 is reboot. The init9 command can be used (by the root user) to change the system from its current runlevel to another:


# init 1


What happens when you issue such a command is determined by the

/etc/inittab file. Let’s take a look at the out-of-the-box /etc/inittab file from a Fedora Core 110 system (Example 20.1).

This is a pretty complex file, and we don’t want to bog down in it too much, since most of what interests us occurs outside this file.

The basic format of a line in /etc/inittab is:


id:runlevels:action:process


The id is a unique 1–4 character identifier. The runlevels is a list of the runlevel numbers to which the record applies. The action specifies what action is to be taken. The process is the program to run. The respawn action, for example, tells init that when the process exits, it should be run again. The once action says it should be run once on transition to the runlevel. We won’t go into too much more here. See the man inittab page for details.

The part that concerns us are the l0 through l6 entries. Note that these cause the /etc/rc.d/rc script to be run once, with the runlevel passed as an argument. This is the key to System V init system.


image

9. telinit is a common alias from other UNIX implementations. Linux symlinks this to init.

10. During the writing of this book, RedHat decided to put their completely Free Software OS out to a public-controlled project and to stop calling it “RedHat.” The name RedHat is reserved for Fedora-based Linux systems that must be purchased with support contracts. It is still the same system with a different name maintained by basically the same people. The key difference is that you cannot purchase support for Fedora (at least from RedHat, we expect some enterprising folks to offer Fedora support for a fee at some point).


image

Example 20.1 Fedora Core 1 default /etc/inittab file

#

# inittab This file describes how the INIT process should set up

# the system in a certain runlevel.

#

# Author: Miquel van Smoorenburg, miquels@drinkel.nl.mugnet.org>

# Modified for RHS Linux by Marc Ewing and Donnie Barnes

#


# Default runlevel. The runlevels used by RHS are:

# 0 - halt (Do NOT set initdefault to this)

# 1 - Single user mode

# 2 - Multiuser, without NFS

# (The same as 3, if you do not have networking)

# 3 - Full multiuser mode

# 4 - unused

# 5 - X11

# 6 - reboot (Do NOT set initdefault to this)

#

id:5:initdefault:


# System initialization. si::sysinit:/etc/rc.d/rc.sysinit


l0:0:wait:/etc/rc.d/rc 0

l1:1:wait:/etc/rc.d/rc 1

l2:2:wait:/etc/rc.d/rc 2

l3:3:wait:/etc/rc.d/rc 3

l4:4:wait:/etc/rc.d/rc 4

l5:5:wait:/etc/rc.d/rc 5

l6:6:wait:/etc/rc.d/rc 6


# Trap CTRL-ALT-DELETE

ca::ctrlaltdel:/sbin/shutdown -t3 -r now


# When our UPS tells us power has failed, assume we have a few minutes

# of power left. Schedule a shutdown for 2 minutes from now.

# This does, of course, assume you have powered installed and your

# UPS connected and working correctly.

pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"


# If power was restored before the shutdown kicked in, cancel it. pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"


# Run gettys in standard runlevels 1:2345:respawn:/sbin/mingetty tty1 2:2345:respawn:/sbin/mingetty tty2 3:2345:respawn:/sbin/mingetty tty3 4:2345:respawn:/sbin/mingetty tty4 5:2345:respawn:/sbin/mingetty tty5 6:2345:respawn:/sbin/mingetty tty6


# Run xdm in runlevel 5 x:5:respawn:/etc/X11/prefdm -nodaemon


image




NOTE

Some Linux distributions run different scripts for each runlevel instead of passing the runlevel as an argument to a single script. The details are not important. The net effect is that a script is run for each runlevel.

image


Sure, you could put the code to run JBoss directly in that script if you want. But these scripts have been designed to handle arbitrary sets of services without you having to modify those scripts directly. How? By doing what Linux (and its UNIX antecedents) does so well: making complex systems out of simple parts.

Each service you might wish to start and stop gets a shell script that con- trols it. This shell script must take a command argument. The minimum set of commands that must be supported are start and stop. Other options such as restart and status are often supported, but start and stop are the important ones.

The script for atd, the one-shot job scheduler, is a fine example. Let’s take a look at it (Example 20.2).



image

Example 20.2 The atd init shell script

#!/bin/bash

#

# /etc/rc.d/init.d/atd

#

# Starts the at daemon

#

# chkconfig: 345 95 5


# description: Runs commands scheduled by the at command at the \

# time specified when at was run, and runs batch commands when \

# the load average is low enough.

# processname: atd


# Source function library.

. /etc/init.d/functions


test -x /usr/sbin/atd || exit 0 RETVAL=0

#

# See how we were called.

#

prog="atd" start() {

# Check if atd is already running

if [ ! -f /var/lock/subsys/atd ]; then echo -n $"Starting $prog: "

daemon /usr/sbin/atd RETVAL=$?

[ $RETVAL -eq 0 ] touch /var/lock/subsys/atd echo

fi

return $RETVAL

}


stop() {

echo -n $"Stopping $prog: " killproc /usr/sbin/atd RETVAL=$?

[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/atd echo

return $RETVAL

}


restart() { stop start

}


reload() { restart

}


status_at() {

status /usr/sbin/atd

}


case "$1" in start)

start

;;

stop)

stop

;;

reload|restart) restart

;;

condrestart)

if [ -f /var/lock/subsys/atd ]; then restart

fi

;;

status) status_at

;;

*)

echo $"Usage: $0 {start|stop|restart|condrestart|status}" exit 1

esac


exit $?

exit $RETVAL


image


This script is from a RedHat Linux system. Those comments at the top are a magic incantation for the chkconfig program that ships with that distri- bution11 (and with Fedora Core). We’ll talk more about chkconfig in the next section.

As you can see, the basic premise is that when a daemon is started, the process ID is saved into a file. If the “stop” option is passed, the PID is looked up and the process is killed. That’s the basic idea. But wait! There’s more!

Each runlevel has a directory of scripts. Let’s look at the contents of such a directory (Example 20.3).



image

11. The RedHat chkconfig program is conceptually similar to the one in the IRIX operating system.


image

Example 20.3 A directory of scripts

[mschwarz@host238 mschwarz]$ cd /etc/rc5.d [mschwarz@host238 rc5.d]$ ls

K01yum

K73ypbind

S18rpcgssd

S58ntpd

K05saslauthd

K74nscd

S19rpcidmapd

S80sendmail

K11jboss

K89netplugd

S19rpcsvcgssd

S80spamassassin

K12mysqld

S00microcode_ctl

S20random

S85gpm

K15httpd

S04readahead_early

S24pcmcia

S90crond

K15postgresql

S05kudzu

S25netfs

S90vmware

K20nfs

S06cpuspeed

S26apmd

S90xfs

K24irda

S08iptables

S28autofs

S95anacron

K35smb

S09isdn

S40smartd

S95atd

K35vncserver

S10network

S44acpid

S96readahead

K35winbind

S12syslog

S55cups

S97messagebus

K36lisa

S13irqbalance

S55sshd

S97rhnsd

K50snmpd

S13portmap

S56rawdevices

S99local

K50snmptrapd

S14nfslock

S56xinetd



Notice the file S95atd? Let’s look at the long form ls output for that file:


[mschwarz@host238 rc5.d]$ ls -la S95atd

lrwxrwxrwx 1 root root 13 Feb 2 02:08 S95atd -> ../init.d/atd


The file is a symbolic link to the file in the init.d directory! If you take a look at the actual script run by the /etc/inittab file on a runlevel change, you will notice that what it does is to pick up all the files in the rcX.d directory (where X is the runlevel being changed to12) that begin with the letter K, run through them in numerical order, and execute the linked scripts with stop as the argument. It then picks up all the files that begin with S, runs through them in numerical order, and executes the linked scripts with start as the argument. This sounds like a mess, but it is actually a very nice way to automate the starting and stopping of services by runlevel. Adding or removing a new service is simply a matter of creating the /etc/init.d script, and then adding the


image

12. That phrase actually caused my high school grammar teacher to materialize in my office and scold me. I invite anyone who can come up with an elegant and grammatical way to phrase that to contact me at mschwarz@multitool.net. I’m perfectly serious.


appropriate symlinks to the rcX.d directories.13 So, first we have to take an init script and modify it to run JBoss.