Lecture 3

More on System Startup

Startup Scripts

Once in multiuser mode on a Unix system, the init program executes system startup scripts. There are two principal ways of doing this:

BSD Style

Init scripts are in /etc. The file /etc/rc is typically the file that will be executed by init. It is hand-tailored to execute other scripts having names beginning with rc, such as rc.local, rc.boot, rc.tcpip, etc. These scripts usually have a pretty well organized collection of things they do (run all rc scripts for services provided by the local machine, run all services critical to any unix system, start network services, etc.).

This method of starting up a system is relatively unorganized and difficult to manage.

System V startup scripts

There are seven run levels in System V. Why seven init levels? The number was inherited from a phone switch (this was developed by AT&T after all).

In run level 0, the machine is not running.

Single-user mode is init level 1. The run level designated S is used to enter level 1 with root password authentication. (A special password requesting program is spawned upon entering level S.)

In the System V plan, all startup scripts are stored in /etc/init.d (the .d suffix indicates this is a directory). For each run level n, there is directory for links to startup scripts for that run level, namely, /etc/rcn.d, that is, /etc/rc0.d, /etc/rc1.d, /etc/rc2.d, etc.

/etc/inittab plays a critical role. It provides a list of processes that must be spawned (forked and execed) by init.

The inittab is a reasonable facility for starting processes, but not for stopping or restarting them in case of changes of run level or problems with a server process. Hence the use of the /etc/rclevel.d directories.

A typical System V init script looks as follows:

#! /bin/sh

##
#  Script to start food, the foo daemon
#

test -f /usr/local/food || exit 0
case "$1" in
  start)
    echo -n "Starting food: food
    /usr/local/sbin/food
    echo "."
    ;;
  stop)
    echo -n "Stopping food: food"
    kill `cat /var/run/food.pid`
    echo "."
    ;;
  restart)
    echo -n "Stopping food: food"
    kill `cat /var/run/food.pid`
    echo "."
    echo -n "Starting food: food
    /usr/local/sbin/food
    echo "."
    ;;
  *)
    echo "Usage: /etc/init.d/food start|stop|restart"
    exit 1
    ;;
esac
This script is placed in /etc/init.d and linked in whatever run level it is to start. Suppose food should start in run level 3, but should not be running in single-user mode. We can insure the right semantics by creating the links as follows:
# ln -s /etc/init.d/food /etc/rc3.d/S48food
# ln -s /etc/init.d/food /etc/rc0.d/K10food

When init enters level n (higher than the current level) from run level m, it will start all processes by executing the scripts starting with the letter S in levels m+1 through n. When init enters level n (lower than the current level m, it should stop all processes by executing the scripts starting with the letter K in levels m-1 through m. Note, depending on the system, only those scriptsin the new run level may be executed. Be vigilant, be aware.

You can think of these processes as being carried out by scripts similar to these:

for DIR in rc.* ; do
  for SCRIPT in $DIR/S* ; do
    $SCRIPT start;
  done;
done
  

for DIR in rc.* ; do
  for SCRIPT in $DIR/K* ; do
    $SCRIPT stop;
  done;
done
Script Execution Order

Within a given level's startup script directory, the scripts execution is performed lexicographically. Typically, these scripts are named as an S or K followed by two numbers, followed by the name of the service started by the script (such as S34named).

Red Hat Startup scripts

At each run level, init runs /etc/rc.d/rc with the new run level number as its argument. Just before the end of the startup process, rc.local is executed.

Red Hat keeps boot configuration information in /etc/sysconfig. This directory contains files and subdirectories as listed on page 33 of Nemeth, et al. Subdirectories contain special information about devices and so forth, for example, /etc/sysconfig/network-scripts contains configuration parameters for the ethernet interfaces.

SuSE Startup Scripts

In typical German fashion, SuSE has an extremely organized startup method.

In SuSE, environment variables that will be used by startup scripts are set in /etc/rc.config. If some subsystems need very fancy configuration, config files are put in /etc/rc.config.d. The rc.confg file may set parameters (IPADDR_0=192.168.1.101, ROOT_LOGIN_REMOTE="no") or specify options about whether or not to start (START_ROUTED="no").

YaST (Yet another Setup Tool) is a GUI tool for maintaining the contents of /etc/rc.config. In most Unix systems providing GUI administration interfaces, the actual data maintained by the GUI is stored in a file that is amenable to text editing as well. If you use a GUI administration tool such as YAST, you should also look at the files that the tool maintains. This helps you understand the details of the underlying model better.

Debian Startup Scripts

As in Red Hat, Debian executes /etc/init.d/rc when entering a new run level. But unlike SuSE, each script is required to find its owwn configuration information. There is neither a single directory (such as /etc/sysconfig of Red Hat) nor a collection of environment variables (as set by SuSE's /etc/config.rc) to guide the process. You just have to go looking to find out what's really going on. Thus, any file in the system could conceivably contain startup script data. Watch out!

Rebooting and Shutting Down

Unix uses memory buffers to improve filesystem performance. This means that shutting down a running system can wreak havoc on all the open files. Thus the system must be shutdown in a way that preserves the states of open files. As I mentioned before, the use of journalling and logging file systems may eliminate this annoyance in the future, but for now it's still with us.

Although those of you who are familiar with Microsoft operating systems are used to rebooting the machine (or even reinstalling the system) when all else fails, this should be avoided on Unix systems. Even if the unstable file system annoyance is eliminated, terminating services or communication stream will still present a problem. It is usually not necessary to reboot a Unix machine, and you shouldn't do it unless you know it needs to be done. What usually requires a reboot on a Windows system will usually require a user logging in and out on a Unix system.

There are a variety of ways to reboot a Unix system:

The proper way is probably to use shutdown. It can be given parameters to specify a wall (write all) message to be logged and to provide to any users who might be logged in. It can be delayed until an appropriate time. It can be given parameters to specify whether or not to reboot. It can sometimes be told whether or not to run fsck on reboot. If the file systems are unmounted properly (stable when shutdown occurred) the fsck will not be performed.

Examples:

shutdown -h 11:30 "System will be down for scheduled hardware upgrade"
shutdown -h +30 "System going down to replace flaky power supply"
The only way to stop a shutdown is to kill the shutdown process. You can only do this safely during the grace period (before the time specified for the start of shutdown arrives).
Changing Run Level

The telinit command is used to provide init with a new run level. While

# telinit S
is usually used to enter single user mode, an argument of 1 must be provided on Red Hat or else you'll simply start a root shell.