< Day Day Up > |
16.4. Boot ScriptsDuring a system boot, shell scripts are run to perform tasks such as starting daemons and network services, starting database engines, mounting disks, and so on. They are also run during system shutdown. These scripts are known as boot scripts, startup and shutdown scripts, init scripts, or run control scripts, depending on which documentation you are reading and to whom you are talking. They are frequently called boot scripts, and that term will be used to refer to these scripts for the rest of the chapter. On almost all UNIX/Linux systems, the boot scripts are written in Bourne or Bash shells. A UNIX installation will come with a starter set of boot scripts so that administrators are not required to write the scripts themselves, but they should be able to debug and modify scripts when required. For those familiar with the differences between System V and BSD-style UNIX systems, this section will focus on the System V-style boot scripts, mainly because they are the most commonly used. 16.4.1 A Little TerminologyThroughout this text, we have used the terms such as the kernel, init, processes, PIDs, deamons, and initialization scripts in relation to the shell. This section provides some further clarification of these terms as they relate to the boot-up process and the scripts that are started during system initialization. The Kernel and initWhen the system boots, the UNIX/Linux kernel is loaded from disk. It is the program that manages the operating system from boot-up to shutdown. Initially it initializes device drivers, starts the swapper, and mounts the root filesystem (/). The kernel then creates the first process, called init, the parent of all processes, with a PID (process identification number) number 1. When init starts, it reads from an initialization file called /etc/inittab. This file defines what processes to start during boot-up as well as during normal operation, supervises logins on serial ports, and defines run levels to determine what processes or groups of processes should be started. What Is a Run Level?A run level, also called a system state, determines which set of processes are currently available on a system. Usually there are eight run levels: 0–6 and s or S. The run levels fit into three general categories: halted, single-user, and multiuser. In the halted system state, UNIX is not running—it is halted. Moving to a halted state shuts down the system. Run level 0 is a halted state. On some versions of UNIX, notably Solaris, run level 5 is also a halted state and unlike run level 0, the machine is automatically powered off after UNIX is halted. The single-user run level is either S or 1. In single-user mode, the system console is opened, and only root is logged on. (See "Single-User Mode" on page 1033.) The multiuser run levels are 2–5. The multiuser mode allows users to log into the system. The run level numbers for multiuser vary quite a bit from one version of UNIX/Linux to another. To complicate things even more, there may be more than one multiuser run level on a particular system. For example, under SuSE Linux, run levels 2 and 5 are both multiuser levels. Level 2 allows users to log in, but they will log into a text-only, single-screen session. Level 5 allows login, and additional processes are started including window managers such as KDE (the K Desktop Environment). As superuser, you can change to a different run level with the init (or telinit) command. For example init 0 would move the system into run level 0, thus shutting it down. The run level numbers can be frustrating since each vendor has a different definition of what the run levels will do. The only consistent values seem to be 0 for halted and 2 and 3 for multiuser. The who –r command lists the current run level. See Table 16.1.
Example 16.7.$ who -r . run-level 3 Mar 18 14:24 3 0 S EXPLANATION The who –r command displays the current run level of the init process, which in this case is run level 3, multiuser mode (Solaris). Single-User ModeIn the single-user states, UNIX is running, but users cannot log in. Either init 1 or init s will bring your system into a single-user state. The only interaction with the system is through a root-owned shell that is started automatically on a particular window or workstation. Single-user states are for maintenance and not all system processes will be started. For example, networking and database processes will usually not be running. Generally, the system administrator will change the machine to a single-user state to fix a serious software problem, install software, or perform any other task where logged in users might see a partially functioning system (and be confused) or might interfere with system performance (e.g., you don't want users to access files while you're trying to upgrade the operating system). Boot ScriptsEach of the run levels defined on a system should contain a directory of scripts that are run for a particular run level. These scripts manage such services as mail, cron, network services, lpd, and more. The directory name reflects the run level: The rc5.d directory contains scripts for run level 5, the rc3.d directory contains scripts for run level 3, and so on. These directories are located in different places depending upon your UNIX/Linux version. For example, the scripts for run level 3 are usually stored in one of the following directories: /etc/rc3.d, /sbin/rc3.d, /etc/init.d/rc3.d, or /etc/rc.d/rc3.d. Once you find the correct directory, almost all versions of UNIX/Linux use the same general scheme for the names of the scripts within those directories. The script names start with one of the letters S or K, followed by a number, and then a name describing what the script does. The scripts take an argument of either start or stop. A start argument asks the script to start services; a stop argument asks it to shut down services. If a script name starts with an S, that script will be run with a start argument. If the script name starts with a K, the script is run with a stop argument. The K scripts are useful when the system is brought to a lower run level, stopping processes, as the machine is brought down. The scripts are run in the order they are listed with the ls command. Example 16.8.$ cd rc3.d $ ls README S34dhcp S77dmi S89sshd s15nfs.server S13kdc.master S50apache S80mipagent S90samba s99idled S14kdc S52imq S81volmgt S99fixkde S16boot.server S76snmpdx S84appserv S99snpslmd EXPLANATION This example was taken from a system running Solaris 5.9. The contents of the rc3.d directory (run level 3) are displayed. Check the documentation on your system. Example 16.9.$ cd rc3.d $ ls K001inuxconf K25squid K55routed K92iptables S55sshd K03rhusd K28ams K61dap K95kudzu S56rawdevices K05anacron K30mcserv K65identd K95reconfig ig S56xinetd K05innd K30sendmail K65kadmin K96irda S60lpd <not all output is shown> EXPLANATION This example was taken from a system running Red Hat Linux. The partial contents of the rc3.d directory (run level 3) are displayed. Check the documentation on your system. What Is a Daemon?A daemon[1] is a process that runs in the background and performs one or more tasks on a user's behalf. For example, the printer daemon, lpsched, sends files one at a time to a printer. If the lpsched daemon is not running on systems that use it for printing, then files will not be sent to the printer. A Web server, such as Apache, is a daemon; it stays dormant until it is asked for a Web page. The cron (called crond on some systems) program is also a daemon. It checks the cron instruction files (called crontab files) once a minute to see if it is time to run any commands specified there. When the correct time comes, the cron daemon automatically runs the program specified in the crontab file. For a complete discussion on the cron utility, see "An Example Boot Script—The cron Utility," below. Many daemon programs, such as cron, are started during the boot process and run the whole time the system is booted. Other daemons, such as telnet, are under the control of a master daemon and are only started when they are needed (the master daemon does need to run all the time).
16.4.2 An Example Boot Script—The cron UtilityIn this section, we will look at a sample boot script from Red Hat Linux. This script starts the cron daemon during the system boot. The script can also be run manually to control the daemon. The cron boot script is a good example because it is relatively easy to understand and the cron program exists on virtually every UNIX version. Before we look at the boot script for cron, it's helpful to know what cron does. The cron utility allows root and other users to schedule system commands, shell scripts, programs, and more to run at preset times. The user does not need to be present to interact with the system; cron will run commands from the user's crontab file, a file that contains a table specifying a list of commands and specified dates and times when the commands should be executed. The following example shows that the Solaris cron daemon is running as root. Example 16.10.$ ps -ef | grep cron | grep -v grep root 202 1 0 Mar 18 ? 0:03 /usr/sbin/cron Red Hat Linux starts the crond daemon at boot-up. $ ps aux | grep cron | grep -v grep root 436 0.0 0.5 1552 700 ? S 06:13 0:0 crond Creating a cron Instruction File (crontab File)The cron daemon reads the crontab files that have been submitted by system users. Each line in the crontab file consists of six fields separated by spaces. The first five fields tell the cron daemon when to run the command that is contained in the sixth field. The values in the first five fields are: minutes (00–59), hours of the day (00–23), day of the month (1–31) and months of the year (1–12), and weekday (0–6). The sixth field is the command that will be executed at the time specified in the first five fields. See Table 16.2.
The first five fields can also use any one of the following formats.
The sample below shows a crontab file submitted to cron using the crontab command. Example 16.11.1 # crontab -l > instructions 2 # vi instructions . (There might or might not be lines at the top of this file. You can ignore any lines except the one added below.) 3 25 1 * * * /root/checkpercent 4 # crontab instructions 5 # crontab -l . (There may not be lines above the entry that was added in item 3.) . 25 1 * * * /root/checkpercent EXPLANATION
The cron Boot ScriptBefore we look at the contents of the cron boot script, let's look at the layout of boot scripts in general. The following example displays a partial list of boot scripts for run level 5 on a Red Hat system. Although most other UNIX versions have a similar layout for their boot scripts, some, such as Darwin in Mac OS X, are quite different. Below is a truncated listing of the directory containing the boot scripts for run level 5 under Red Hat Linux. Example 16.12.1 # pwd /etc/rc5.d 2 # ls . K20nfs K45named S55sshd S90crond .. K35smb S12syslog S80sendmail 3 # ls -l /etc/rc5.d/*cron* lrwxrwxrwx 1 root 15 Oct 13 21:19 /etc/rc5.d/S90crond -> ../init.d/crond 4 # ls -l /etc/init.d/cron* -rwxr-xr-x 1 root 1316 Feb 19 2004 /etc/init.d/crond EXPLANATION
The cron boot script, called crond, can be run manually to start or stop the cron daemon. On some releases, it can also be used to check the status or restart cron. Other releases allow additional arguments. Traditionally, boot scripts are run by preceding the script name with the shell for which the script was written, followed by the name of the script. The examples below run the master copy of the crond script from the /etc/init.d directory. Because they are linked, you could accomplish the same thing by running the /etc/rc5.d/crond script instead. Example 16.13.1 # cd /etc/init.d 2 # ls crond crond 3 # sh crond stop Stopping crond: [OK] 4 # sh crond start Starting crond: [OK] 5 # sh crond restart Stopping crond: [OK] Starting crond: [OK] EXPLANATION
Below is a simplified version of the boot script for the cron daemon from Red Hat Linux. This script sources another script called functions, which defines daemon and killproc for the script. The daemon function takes a daemon name as an argument. It attempts to start that daemon and will return a success or failure code depending on what happened. Example 16.14.#! /bin/bash # crond Start/Stop the cron clock daemon. # # chkconfig: 2345 90 60 # description: cron is a standard UNIX program that runs # user-specified programs at periodic scheduled times. # config: /etc/crontab # pidfile: /var/run/crond.pid # Source function library. 1 . /etc/init.d/functions 2 RETVAL=0 ; prog="crond" 3 start() { 4 echo -n $"Starting $prog: " 5 daemon crond 6 RETVAL=$? 7 echo 8 [ $RETVAL -eq 0 ] && touch /var/lock/subsys/crond 9 return RETVAL } 10 stop() { 11 echo -n $"Stopping $prog: " 12 killproc crond 13 RETVAL=$? 14 echo 15 [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/crond return RETVAL } 16 restart() { stop ; start } 17 case "$1" in 18 start) start ;; 19 stop) stop ;; 20 restart) restart ;; 21 *) echo $"Usage: $0 {start|stop|restart}" exit 1 ;; esac EXPLANATION
16.4.3 Writing a Portable ScriptSystem administrators often write shell scripts that work on multiple UNIX versions. Because commands change from UNIX to UNIX, your script will need to determine the UNIX version on which it is being run. This can be done using the uname command. Listed below are some popular versions of UNIX and the output of the uname command from each version. To create a script that will port to these different UNIX versions, your script should check the uname output and modify commands accordingly.
A case command is commonly used to check for the operating system you are using. Example 16.15 checks for Linux (any brand), HP-UX, Solaris, FreeBSD, and Mac OS X UNIX. Example 16.15.1 uname_out=`uname` 2 case "$uname_out" in 3 HP-UX) echo "You are running HP-UX" ;; 4 SunOS) echo "You are running Solaris" ;; FreeBSD) echo "You are running FreeBSD" ;; Linux) echo "You are running Linux" ;; Darwin) echo "You are running Mac OS X" ;; 5 *) echo "Sorry, $uname_out UNIX " echo "is not supported by this script" ;; 6 esac EXPLANATION
Example 16.16 is a sample script to tell the administrator when any of a machine's filesystems are getting full. This script does not check for all versions of UNIX, although you can modify the script for any version of UNIX. The sample script changes the form of the df command to accommodate four types of UNIX. Example 16.16.
# cat /root/checkpercent
1 #! /bin/sh
2 rm $HOME/df_output $HOME/message 2> /dev/null
3 uname_out=`uname`
4 case "$uname_out" in
5 HP-UX)
6 bdf | awk '{print $5,$6}' | awk -F% '$1>90 {print $0}' \
> $HOME/df_output
;;
7 SunOS)
8 df -k | awk '{print $5,$6}' | awk -F% '$1>90 {print $0}' \
> $HOME/df_output
;;
9 Linux)
10 df | awk '{print $5,$6}' | awk -F% '$1>90 {print $0}' \
> $HOME/df_output
;;
11 Darwin)
12 df | awk '{print $5,$6}' | awk -F% '$1>90 {print $0}' \
> $HOME/df_output
;;
13 *)
echo "Sorry, $uname_out UNIX not supported by this script"
;;
esac
14 if [ -s $HOME/df_output ]
then
15 echo "** WARNING **" > $HOME/message
echo "The following file systems are filling up." >> $HOME/message
echo "You may want to look into the situation." >> $HOME/message
cat $HOME/df_output >> $HOME/message
16 cat $HOME/message
17 echo "This warning message is stored in the file $HOME/message"
echo "You should create a copy of the file now if you would"
echo "like to save this message."
fi
18 rm $HOME/df_output
EXPLANATION
16.4.4 User-Specific Initialization FilesWhen user accounts are initially created, the administrator normally places login files, such as .profile and .login, in the user's home directory. The administrator must understand the syntax of the shells in order to write a version of these files that will be suitable for their users. Each shell has one or more initialization files that can be placed in a user's home directory. As administrator, you may wish to place a starter copy of these initialization files in your user's home directory when it is first created. Most versions of UNIX help you automate this process through the /etc/skel directory, although sometimes the directory name is slightly different. When creating a new account using the useradd command, all files from /etc/skel are copied to a user's home directory. Example 16.17.1 # ls -a /etc/skel . .. .profile .cshrc 2 # useradd -m newguy1 3 # ls -a /home/newguy1 . .. .profile .cshrc 4 # useradd newguy2 5 # ls -a /home/newguy2 ls: /home/newguy2: No such file or directory EXPLANATION
Possible Files for /etc/skelYou should put a set of starter initialization files in the home directory of a new user when you create his or her home directory. A chart of the initialization files used by the five major UNIX shells is listed in Table 16.3. You might want to create a generic version of all of these files and place them in the /etc/skel directory. These files will be copied into a user's home directory whenever a new account is created, giving the user a starter copy of the initialization files needed for his or her login shell. See the other chapters for individual shells for more details on the initialization files.
16.4.5 System-Wide Initialization FilesThe system administrator is responsible for maintaining a set of system-wide initialization files used by various login shells. The administrator will often perform tasks such as setting an initial value for the PATH and MANPATH variables in these files. For a login shell, /etc/profile is the system-wide intialization file for the Bourne, Korn, and Bash shells and /etc/.cshrc or /etc/csh.login are system-wide initialization files for the C and TC shells (filenames vary on different systems). See Table 16.4. Most UNIX installations come with a starter set of these files that can be customized for a particular system.
In addition to the system initialization files, the local initialization files are also run when a user logs in. If, for example, a user logs into the TC shell on a Red Hat system, the files listed below will be sourced in the order listed. The first two files are system files and the last two files are local files. The value of the HOME environment variable is the path of the user's home directory. /etc/csh.cshrc /etc/csh.login $HOME/.tcshrc $HOME/.login /etc/profileThe /etc/profile file contains commands that are automatically run when a user logs into a system using the Bourne, Bash, or Korn shell. A starter copy of /etc/profile will be provided during the installation process. This file is normally modified by the system administrator to accomodate the needs of a particular system. Example 16.18.# cat /etc/profile # System-wide environment and startup programs, for login setup # Functions and aliases go in /etc/bashrc 1 pathmunge () { 2 if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then 3 if [ "$2" = "after" ] ; then 4 PATH=$PATH:$1 else 5 PATH=$1:$PATH fi fi 6 } # Path manipulation 7 if [ `id -u` = 0 ]; then 8 pathmunge /sbin 9 pathmunge /usr/sbin 10 pathmunge /usr/local/sbin fi 11 pathmunge /usr/X11R6/bin after 12 unset pathmunge # No core files by default 13 ulimit -S -c 0 > /dev/null 2>&1 14 USER="`id -un`" 15 LOGNAME=$USER 16 MAIL="/var/spool/mail/$USER" 17 HOSTNAME=`/bin/hostname` 18 HISTSIZE=1000 19 if [ -z "$INPUTRC" -a ! -f "$HOME/.inputrc" ]; then INPUTRC=/etc/inputrc fi 20 export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC 21 for i in /etc/profile.d/*.sh ; do 22 if [ -r "$i" ]; then 23 . $i fi done unset i EXPLANATION
/etc/bashrcThe /etc/bashrc file is used on some UNIX releases, such as Red Hat Linux, to run bash commands whenever a bash shell is run. This file should contain settings that are not passed automatically to child processes, such as command aliases. Example 16.19.
1 $ cat /etc/bashrc
2 alias ls="ls -F"
3 alias grep="grep -i"
EXPLANATION
If you wish to use /etc/bashrc and your UNIX doesn't source it automatically, you can include it in the user's personal .bashrc file in his or her home directory. Example 16.20.
1 $ cat .bashrc
2 if [ -f /etc/bashrc ]
then
3 . /etc/bashrc
fi
4 alias dir=ls
EXPLANATION
/etc/csh.loginThe /etc/csh.login file is sourced by the C and TC shells during the login process. Example 16.21 is an /etc/csh.login file from a Red Hat Linux system. Like the .login file, this file is run at login time by the login shell, and not by any child shells spawned thereafter. It is used to set environment variables for the shell and any other commands that will be executed by the login shell. Example 16.21.# cat /etc/csh.login # System-wide environment and startup programs, for login setup 1 if ($?PATH) then 2 setenv PATH "${PATH}:/usr/X11R6/bin" else 3 setenv PATH "/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin" endif 4 limit coredumpsize unlimited 5 setenv HOSTNAME `/bin/hostname` 6 set history=1000 7 if ( -f $HOME/.inputrc ) then 8 setenv INPUTRC /etc/inputrc endif 9 if ( $?tcsh ) then 10 bindkey "^[[3~" delete-char endif EXPLANATION
/etc/csh.cshrcThe /etc/csh.cshrc file is sourced by the C and TC shells whenever they are run. C and TC shells can be started at login time (if it has been specified as a user's login shell) when running a C or TC shell script, or when opening a shell window that runs the C or TC shell. The example /etc/csh.cshrc file given below is from a Red Hat Linux system. The /etc/csh.cshrc file should include items that are not exported to child processes, such as setting a umask or setting the prompt. Note that in the C and TC shell the prompt variable is local, which means it will not be passed to child processes. Example 16.22.
# cat /etc/csh.cshrc
1 umask 022
2 if ($?prompt) then
3 if ($?tcsh) then
4 set prompt='[%n@%m %c]$ '
else
5 set prompt=\[`id -nu`@`hostname -s`\]\$\
endif
endif
6 if ( -d /etc/profile.d ) then
7 set nonomatch
8 foreach i ( /etc/profile.d/*.csh )
9 if ( -r $i ) then
10 source $i
endif
end
11 unset i nonomatch
endif
EXPLANATION
|
< Day Day Up > |