Section 26.1. Objective 1: Customizing System Startup and Boot Processes


26.1. Objective 1: Customizing System Startup and Boot Processes

In Chapter 14, we discussed boot procedures for a Linux system. Specifically, we covered boot-time kernel parameters, boot initialization scripts, and how to change system runlevels. The 201 exam takes this subject a step further and addresses how to customize your system's startup procedures.

When the kernel has mounted the root filesystem, it executes /sbin/init. This program's first task is to read /etc/inittab, which defines everything done thereafter.

26.1.1. /etc/inittab

The /etc/inittab file describes what processes are started at boot time and during normal operation. This file is well-documented. For the examples in this section, we'll use a typical inittab file from a Red Hat system. After some initial comments, the file might contain:

 # 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, with no  networking) #   3 - Full multiuser mode #   4 - unused #   5 - X11 #   6 - reboot (Do NOT set initdefault to this) # id:3:initdefault: 

The comments explain when the various runlevels are used on this machine. The first noncomment line is the one tagged id:, which defines the default runlevel for this system. As explained in the listing, this is multiuser mode with no X Window System. On a Debian system, the default runlevel is 2. Debian specifies only that 25 are multiuser. In virtually all distributions, runlevel 0 is used to halt the system, 1 to run it in single-user mode, and 6 to reboot.

After your system is booted into a particular runlevel, you can change to another runlevel using the init or telinit commands. By issuing init 6 at the root prompt, you can command the system to reboot. Issuing init 1 commands the system to boot into single-user mode. These commands can be issued only by root.

The inittab file continues:

 # 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 

The si line defines that the script /etc/rc.d/rc.sysinit is to run first (because there are no other lines before it). It is run on all runlevels, because the second parameter on the line is empty (::). Debian also uses the sysinit script, but runs /etc/init.d/rcS instead. This in turn runs the contents of the /etc/rcs.d directory and then the /etc/rc.boot directory. Red Hat's script is monolithic.

The six lines following, labeled l0 tHRough l6, execute the /etc/rc.d/rc script with an argument corresponding to the runlevel. This script runs the contents of the corresponding /etc/rcrunlevel.d directory as explained in Chapter 14.

The next section sets specific commands and options. In particular, it maps the Ctrl+Alt+Delete key sequence, which automatically reboots the system. You can disable or change that option here. This section also has some options regarding SmartUPS settings. If the system is connected to a UPS with serial feedback that instructs the system when the UPS will run out of power, the system can automatically shut itself down with this entry. Debian systems have one additional action here for powerfailnow.

 # 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 power 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" 

The next section of the /etc/inittab file sets up your virtual consoles. The setup shown here is the default on Red Hat, and allows up to six virtual consoles. To add additional virtual consoles, duplicate the lines and then change the first field as well as the tty field to represent the appropriate number of your virtual console.

 # 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 

26.1.2. System Initialization Scripts

System initialization scripts, most of which are found under the /etc/init.d directory, are used to boot the system and start daemons and services. The scripts you are looking for are in /etc/rc0.d through /etc/rc6.d (runlevel directories), as well as the all-important initial script, which is named /etc/rc.d/rc.sysinit in Red Hat and /etc/init.d/rcS in Debian.

26.1.2.1. System initialization

On Debian, the /etc/init.d/rcS script is the first startup script. On Red Hat, the corresponding script is /etc/rc.d/rc.sysinit. They do a lot of chores that you might never have thought were needed and are an education to read. Because the Red Hat script is monolithic (indeed, currently more than 800 lines), it is perhaps easiest to read.

One of the most important tasks the script performs is to check all the local filesystems. If a problem is found, the script drops into a sulogin shell to let the administrator intervene and fix the problem. For some kinds of filesystem problems, the machine is now rebooted.

If there is a quota executable and quotas are configured, the rc.sysinit script enables the quotas. The following are some excerpts from the Red Hat rc.sysinit script. The excerpts include the information related to filesystem checking and quotas. If you have a Red Hat system, take a glance at your /etc/rc.sysinit file for a complete tour.

 # Start up swapping.  action "Activating swap partitions" swapon -a -e # Check filesystems if [ -z "$fastboot" ]; then         STRING=$"Checking filesystems"         echo $STRING         initlog -c "fsck -T -R -A -a $fsckoptions"         rc=$?         if [ "$rc" = "0" ]; then                 success "$STRING"                 echo         elif [ "$rc" = "1" ]; then                 passed "$STRING"                 echo         fi         # A return of 2 or higher means there were serious problems.         if [ $rc -gt 1 ]; then                 if [ "$BOOTUP" = "graphical" ]; then                     chvt 1                 fi                 failure "$STRING"                 echo                 echo                 echo $"*** An error occurred during the file system check."                 echo $"*** Dropping you to a shell; the system will reboot"                 echo $"*** when you leave the shell."                 str=$"(Repair filesystem)"                 PS1="$str \# # "; export PS1                 sulogin                 echo $"Unmounting file systems"                 umount -a                 mount -n -o remount,ro /                 echo $"Automatic reboot in progress."                 reboot -f         elif [ "$rc" = "1" -a -x /sbin/quotacheck ]; then                 _RUN_QUOTACHECK=1         fi fi # Mount all other filesystems (except for NFS and /proc, which is already # mounted). Contrary to standard usage, # filesystems are NOT unmounted in single user mode. action $"Mounting local filesystems: " mount -a -t nonfs,smbfs,ncpfs -O no_netdev # check remaining quotas other than root if [ X"$_RUN_QUOTACHECK" = X1 -a -x /sbin/quotacheck ]; then         if [ -x /sbin/convertquota ]; then             # try to convert old quotas             for mountpt in 'awk '$4 ~ /quota/{print $2}' /etc/mtab' ; do                 if [ -f "$mountpt/quota.user" ]; then                     action $"Converting old user quota files: " \                     /sbin/convertquota -u $mountpt && \                         rm -f $mountpt/quota.user                 fi                 if [ -f "$mountpt/quota.group" ]; then                     action $"Converting old group quota files: " \                     /sbin/convertquota -g $mountpt && \                         rm -f $mountpt/quota.group                 fi             done         fi         action $"Checking local filesystem quotas: " /sbin/quotacheck -aRnug fi if [ -x /sbin/quotaon ]; then     action $"Enabling local filesystem quotas: " /sbin/quotaon -aug fi # Configure machine if necessary. if [ -f /.unconfigured ]; then     if [ "$BOOTUP" = "graphical" ]; then         chvt 1     fi     if [ -x /usr/bin/passwd ]; then         /usr/bin/passwd root     fi     if [ -x /usr/sbin/netconfig ]; then         /usr/sbin/netconfig     fi     if [ -x /usr/sbin/timeconfig ]; then         /usr/sbin/timeconfig     fi     if [ -x /usr/sbin/kbdconfig ]; then         /usr/sbin/kbdconfig     fi     if [ -x /usr/sbin/authconfig ]; then         /usr/sbin/authconfig --nostart fi     if [ -x /usr/sbin/ntsysv ]; then         /usr/sbin/ntsysv --level 35     fi     # Reread in network configuration data.     if [ -f /etc/sysconfig/network ]; then         . /etc/sysconfig/network         # Reset the hostname.         action $"Resetting hostname ${HOSTNAME}: " hostname ${HOSTNAME}     fi     rm -f /.unconfigured fi # Clean out /. rm -f /fastboot /fsckoptions /forcefsck /.autofsck /halt /poweroff 

One weakness of the single-user runlevel is that, as you can see from the lines just quoted, all the filesystems are mounted and the operating system itself is almost completely initialized. If you're experiencing bad filesystem or hardware problems, this script may never complete. The only way to avoid this problem is to not run init when booting. This is dealt with in more detail in "Objective 2: System Recovery" later in this chapter.

26.1.2.2. Runlevel directories

The system run-level directories on Red Hat are named /etc/rc0.d through /etc/rc6.d. These directories don't actually contain real files or scripts. Instead, they contain links to scripts that are located in the /etc/init.d directory.


Tip: Due to some silly antics during an earlier release, Red Hat still stores the rc scripts in /etc/rc.d/init.d and /etc/rc.d/rcn.d. But now at least the system provides symbolic links from the more standard paths of /etc/init.d and /etc/rcn.d.

The links in the rcn.d directories run through after the system has completed the system initialization script. Each directory contains symbolic links to real scripts. Here is a list of some of the files in a typical /etc/rc0.d directory:

 lrwxrwxrwx 1 root root 14 Dec 10 10:27 K00cups -> ../init.d/cups* lrwxrwxrwx 1 root root 18 Dec 23 01:07 K05keytable -> ../init.d /keytable* lrwxrwxrwx 1 root root 16 Sep 17  2001 K08autofs -> ../init.d/autofs* lrwxrwxrwx 1 root root 16 Dec 23 00:59 K10psacct -> ../init.d/psacct* lrwxrwxrwx 1 root root 14 Aug 29  2002 K10wine -> ../init.d/wine* lrwxrwxrwx 1 root root 13 Sep 17  2001 K10xfs -> ../init.d/xfs* lrwxrwxrwx 1 root root 16 Sep 17  2001 K12mysqld -> ../init.d/mysqld* lrwxrwxrwx 1 root root 13 Sep 17  2001 K15gpm -> ../init.d/gpm* lrwxrwxrwx 1 root root 15 Dec 23 01:03 K15httpd -> ../init.d/httpd* lrwxrwxrwx 1 root root 15 Sep 17  2001 K15sound -> ../init.d/sound* 

Every symbolic link in each of the rcn.d directories is named with an initial S or K. S indicates that the service is to be started; K indicates that it should be stopped. Following the S or K is a two-digit number that indicates the order in which the scripts are to be run. For example, 10 gets run before 15. In the rc0.d directory just shown, for instance, CUPS starts first and sound support starts last.

26.1.3. Customizing Runlevels

As you can see, quite a lot of a system's behavior is determined through what is in the system startup scripts.

Whenever you add a service to your system, a script should be deposited in /etc/init.d and links to it from the right runlevel directories should be made. In Red Hat and some other distributions, the chkconfig is used for this. On Debian and many others, you can use update-rc.d. Once a script to start and stop services is in /etc/init.d, symbolic links to it can be made in the individual runlevel directories, so that the script runs at the proper runlevels .

26.1.3.1. Customizing runlevels on Red Hat

As said in the previous section, Red Hat and some related distributions use the helper utility chkconfig to make this easy.


Syntax

 chkconfig --list [service] chkconfig --add service chkconfig --del service chkconfig [--level levels] service [on|off|reset] 


Description

chkconfig lets you very simply make the appropriate entries in the appropriate runlevel directories or remove them. Thereby it enables or disables the startup of the service during system boot.


Frequently used options


chkconfig --list [service]

If no service is given, list the status of all services. If the name of a service is given, only that service is shown.


chkconfig --add service

Add a new service rc file to the /etc/init.d directory, then initialize all the right runlevels with links to the service rc script. After this, the service will be started when booting.


chkconfig --del service


chkconfig service off

Disable the startup of the service during boot. Note that this does not stop a running service. To do that, invoke /etc/init.d/servicestop.


chkconfig service on

Enable starting the service during boot. Note that this does not start the service now. To start it now, run /etc/init.d/servicestart.


Examples

Add a service called foo and manipulate it.

 # chkconfig --add foo # chkconfig --list foo foo             0:off   1:off   2:on    3:on    4:on    5:on    6:off# chkconfig foo off # chkconfig --list foo foo             0:off   1:off   2:off   3:off   4:off   5:off   6:off 


Runlevel files

chkconfig can manipulate only rc files that have the correct comment lines. Two lines are needed:

 # chkconfig: 345 99 01 # description: Starts the foo service to contribute toward world foo-ness 

The chkconfig: line has three parameters: the runlevels the service should run at and the sequence numbers the S and K files should have. When a service is started last, it should be stopped first; that is why the start sequence number in the previous example is 99 and the stop sequence number is 01. The description is for human consumption. You will find other such labels used in some of these scripts. They are not documented.


Customizing runlevels on Debian

Debian and a number of other distributions use the script update-rc.d to manipulate the runlevels.


Syntax

 update-rc.d [-n] [-f] service remove update-rc.d [-n] service defaults [nn | nn-start nn-stop] update-rc.d [-n] service start|stop nn runlevel runlevel ...                          [ start|stop nn runlevel runlevel ...] 


Description

update-rc.d is used to manage init script links. Once a service rc script is present in /etc/init.d, it can be manipulated by this command. The command enables or disables the startup of the service during system boot.


Frequently used options


update-rc.dz service defaults nn

Adds the service to the startup of all runlevels at sequence number nn.


update-rc.d servicestart nn 2 3 4 5 . stop mm 2 3 4 5 .

Adds start links with sequence number nn at runlevels 2 through 5 and stop links with sequence number mm at the same runlevels. Note the important use of a period (.) in this command; it's required when you want to make multiple settings in a single command line.


update-rc.d -f service remove

Remove the service from the startup of any runlevels it is present in. The -f option is needed if the service script is present in /etc/init.d. If it is not present, the -f can be left out.


Examples

 # update-rc.d foo defaults 99  Adding system startup for /etc/init.d/foo ...    /etc/rc0.d/K99foo -> ../init.d/foo    /etc/rc1.d/K99foo -> ../init.d/foo    /etc/rc6.d/K99foo -> ../init.d/foo    /etc/rc2.d/S99foo -> ../init.d/foo    /etc/rc3.d/S99foo -> ../init.d/foo    /etc/rc4.d/S99foo -> ../init.d/foo    /etc/rc5.d/S99foo -> ../init.d/foo # update-rc.d -f foo remove update-rc.d: /etc/init.d/foo exists during rc.d purge (continuing)  Removing any system startup links for /etc/init.d/foo ...    /etc/rc0.d/K99foo    /etc/rc1.d/K99foo    /etc/rc2.d/S99foo    /etc/rc3.d/S99foo    /etc/rc4.d/S99foo    /etc/rc5.d/S99foo    /etc/rc6.d/K99foo # update-rc.d foo stop 99 0 1 6 . start 99 2 3 4 5 .  Adding system startup for /etc/init.d/foo ...    /etc/rc2.d/K01foo -> ../init.d/foo    /etc/rc3.d/K01foo -> ../init.d/foo    /etc/rc4.d/K01foo -> ../init.d/foo    /etc/rc5.d/K01foo -> ../init.d/foo    /etc/rc2.d/S99foo -> ../init.d/foo    /etc/rc3.d/S99foo -> ../init.d/foo    /etc/rc4.d/S99foo -> ../init.d/foo    /etc/rc5.d/S99foo -> ../init.d/foo 

The first command shown is almost certainly not what you want. Also note that the policy in Debian is to enter start scripts at all runlevels where a service is to run and to add stop scripts at all other levels, but with the same sequence number. Thus, the list of runlevels for the stop and start links shown in the third command are complementary.

26.1.4. Customizing initrd Images

Chapter 25 discussed how to generate initrd images to enable booting all sorts of hardware with a skinny kernel that contains next to no hardware support. The initrd is not just a ram disk containing some modules, but a standalone root filesystem. The modules in it are loaded by a script or executable on the disk. If they are loaded by a script, it must have an interpreter. The following documentation of the initrd boot process is found in Documentation/initrd.txt in any kernel source tree. We won't include a customization example here, but we'll attempt to explain how initrd boots and what the environments look like on Red Hat and Debian.

  1. The boot loader loads the kernel and the initrd.

  2. The kernel converts initrd into a "normal" RAM disk and frees the memory used by initrd.

  3. The initrd is mounted read/write as root.

  4. The /linuxrc file is executed. This file can be any valid executable, including shell scripts; it is run with UID 0 and can do basically everything init can do.

  5. /linuxrc mounts the real root filesystem.

  6. /linuxrc places the root filesystem at the root directory using the pivot_root command.

  7. The usual boot sequence (the invocation of /sbin/init) is performed on the root filesystem.

  8. The initrd filesystem is removed.

By studying your distribution's mkinitrd script, you can see how the /linuxrc script works and how you can customize it. Additionally, the documentation present in Documentation/initrd.txt is very detailed and extensive. Your most likely reasons to customize an initrd in this way are to support something that is too new to be supported by the mkinitrd script or to construct a universal rescue floppy that autodetects the root filesystem and other interesting things on the computer it boots on.

As you can see from the list of steps just enumerated, the key filename in the boot process is /linuxrc. If you take a copy of the mkinitrd script to customize and look in it for /linuxrc, you will be able to deduce how the bootstrap works. In both Debian and Red Hat, /linuxrc is a script.

26.1.4.1. initrd and /linuxrc on Debian

In Debian, the /linuxrc script interpreter is either dash or, more likely, ash. As you can see in the manpage for the interpreter, it offers a pretty complete set of built-in commands. (It is not, however, the standard command interpreter for the system, as the manpage claimsthat honor goes to bash.) And in the mkinitrd script, you will find which other external commands are available. When /linuxrc starts, it reads configuration data from /linuxrc.conf, which was written by mkinitrd. And then the Debian people have thrown in a twist. The /linuxrc file does not execute pivot_root as it should. Instead, when the kernel sees that /linuxrc has terminated, it executes /sbin/init, which is the script that does the real work. One of the things it does is to execute the contents of the /scripts directory in shell sorting order. After that, the real root filesystem is mounted, pivot_root is executed, and the real init command is executed.

The supported way to modify this process is to put your scripts into /etc/mkinitrd/scripts. They will then be executed in order. This solution requires no changes in the system tools. The alternatives are to change the template /linuxrc, the /sbin/init script it installs, or the /linuxrc.conf file. All these options are fairly straightforward, as long as you recall your limited range of commands until the root filesystem is mounted.

Debian offers the following external commands in addition to the regular shell built-ins listed in the ash manpage:


/sbin/init

The special Debian initrd version of init, from the initrd-tools package


/sbin/modprobe

The familiar modprobe command


/sbin/insmod

The familiar insmod command


/bin/echo

The familiar echo command


/bin/mount

The familiar mount command


/bin/umount

The familiar umount command


/bin/pivot_root

The magical command that rotates away the initrd root filesystem and replaces it with the real one


/bin/cat

The familiar cat command


/bin/mknod

The familiar mknod command


/usr/sbin/chroot

The familiar chroot command

In addition, there is a custom-built /dev directory that matches your hardware pretty well. To support the executables, /lib and /usr/lib are filled with shared libraries. /lib/modules contains a complement of kernel modules that fits your setup. Altogether, Debian offers a pretty rich starting point.

26.1.4.2. initrd and /linuxrc on Red Hat

Red Hat generates the /linuxrc file dynamically, line by line. Customizing it thus becomes a question of generating the lines you need in the place you need. In the Red Hat initrd environment, customization is probably not as easy as in Debian. Few tools are provided. The shell used by Red Hat is /bin/nash, which is linked statically. It has the commands needed in an initrd environment built in, but it has very little in the way of general shell syntax. Therefore, the filesystem contains practically nothing to support it; just the following files:


/bin/insmod

A statically linked version of insmod.


/bin/modprobe

Actually a symbolic link to nash, which exits without doing anything when started as modprobe.


/bin/vgchange

The vg* commands are installed only if you use LVM. These help support for an LVM root disk.


/bin/vgscan

See previous entry.


/bin/vgwrapper

See previous entry.

/dev and /lib/modules have contents suitable for your setup. Red Hat does not need a real modprobe because the mkinitrd script analyzes the module dependencies at build time and makes sure that they are loaded in the correct order. Altogether this environment is very sparse. To customize the Red Hat initrd could turn out to be a great deal of work. But it does support booting off LVM-managed USB disks.



LPI Linux Certification in a Nutshell
LPI Linux Certification in a Nutshell (In a Nutshell (OReilly))
ISBN: 0596005288
EAN: 2147483647
Year: 2004
Pages: 257

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net