Chapter 6
The init process: the kernel needs company
|
|
|
|
|
|
In this chapter: |
|
|
|
|
Understanding how init bootstraps the system
|
|
A discussion of /etc/inittab, the main configuration file for init
|
|
Learning about runlevels
|
|
An introduction to rc-scripts
|
|
|
|
|
|
As in most other Unix systems, the init process has a dedicated
function in SuSE Linux. It is the parent of all other processes and
cannot be killed. The init process is the most important process in
the entire system. If you run ps ax and you don't see
init, something is terribly wrong. Horror stories aside, we give you
a review of this process step by step.
When init launches, it first reads its configuration file,
/etc/inittab. The inittab determines what
the system will look like after it's completely booted. SuSE's
standard inittab (taken from a SuSE Linux 6.1 system)
is shown below.
|
| # /etc/inittab
#
# Copyright (c) 1996 SuSE GmbH Nuernberg, Germany. All rights reserved.
#
# Author: Florian La Roche <florian@suse.de>, 1996
#
# This is the main configuration file of /sbin/init, which
# is executed by the kernel on startup. It describes which
# scripts are used for the various runlevels.
#
# All scripts for runlevel changes are in /sbin/init.d/. The main
# file for changes is /etc/rc.config.
# default runlevel
id:2:initdefault:
# check system on startup
# first script to be executed if not booting in emergency (-b) mode
si:I:bootwait:/sbin/init.d/boot
# /sbin/init.d/rc takes care of runlevel handling
l0:0:wait:/sbin/init.d/rc 0
l1:1:wait:/sbin/init.d/rc 1
l2:2:wait:/sbin/init.d/rc 2
l3:3:wait:/sbin/init.d/rc 3
#l4:4:wait:/sbin/init.d/rc 4
#l5:5:wait:/sbin/init.d/rc 5
l6:6:wait:/sbin/init.d/rc 6
# what to do in single-user mode
ls:S:wait:/sbin/init.d/rc S
~~:S:respawn:/sbin/sulogin
# what to do when CTRL-ALT-DEL is pressed
ca::ctrlaltdel:/sbin/shutdown -r -t 4 now
# special keyboard request (Alt-UpArrow)
# look into the kbd-0.90 docs for this
kb::kbrequest:/bin/echo "Keyboard Request -- edit /etc/inittab to let this work."
# what to do when power fails/returns
pf::powerwait:/sbin/init.d/powerfail start
pn::powerfailnow:/sbin/init.d/powerfail now
#pn::powerfail:/sbin/init.d/powerfail now
po::powerokwait:/sbin/init.d/powerfail stop
# for ARGO UPS
sh:12345:powerfail:/sbin/shutdown -h now THE POWER IS FAILING
# getty-programs for the normal runlevels
# <id>:<runlevels>:<action>:<process>
# The "id" field MUST be the same as the last
# characters of the device (after "tty").
1:123:respawn:/sbin/mingetty --noclear tty1
2:123:respawn:/sbin/mingetty tty2
3:123:respawn:/sbin/mingetty tty3
4:123:respawn:/sbin/mingetty tty4
5:123:respawn:/sbin/mingetty tty5
6:123:respawn:/sbin/mingetty tty6
# Note: Do not use tty7 in runlevel 3, this virtual line
# is occupied by the program xdm.
# This is for the package xdmsc. after installation and
# and configuration you should remove the comment character
# from the following line:
#7:2:respawn:+/sbin/init.d/rx tty7
# modem getty.
# mo:23:respawn:/usr/sbin/mgetty -s 38400 modem
# fax getty (hylafax)
# mo:23:respawn:/usr/lib/fax/faxgetty /dev/modem
# vbox (voice box) getty
# I6:23:respawn:/usr/sbin/vboxgetty -d /dev/ttyI6
# I7:23:respawn:/usr/sbin/vboxgetty -d /dev/ttyI7
# end of /etc/inittab
|
|
|
|
Be very careful with modifying /etc/inittab. A simple
typo in this file may result in a system that will not boot. If you
run into this problem, use the rescue system to boot your machine, and
restore your inittab. Always keep a copy of a working
version, by making a copy of it prior to editing, until you are
certain that your changes are correct or can be implemented
successfully. Use the version printed above as a reference if you
don't have a working version.
|
|
As you see, comments begin with a hash sign (#) in the first
column. All other lines are formatted as:
|
| id:runlevels:action:process
|
|
Id is a random identifier. The runlevel field tells
init which runlevel these lines should be used. We'll
talk about runlevels in a moment. The action entry can have one of the
following values (taken from inttab(5)):
|
|
|
respawn
The process will be restarted after it terminates (for example, getty).
|
|
wait
The process will run once when the specified runlevel is entered. The
init process will wait for its termination.
|
|
once
The process will be executed once when the specified runlevel is entered.
|
|
boot
The process will be executed during system boot. The runlevels field is ignored.
|
|
bootwait
The process will be executed during system boot,
while init waits for its termination (for example,
/sbin/init.d/boot). The runlevels field is ignored.
|
|
off
Turns this entry off. All fields are ignored.
|
|
ondemand
A process marked with an ondemand runlevel will be executed whenever
the specified ondemand runlevel is called. However, no runlevel
change will occur (ondemand runlevels are a, b, and c).
|
|
initdefault
An initdefault entry specifies the runlevel that should
be entered after system boot. If none exists, init
will ask for a runlevel on the console. The process field is
ignored.
|
|
sysinit
The process will be executed during system boot. It will be executed
before any boot or bootwait entries. The runlevels field is ignored.
|
|
powerwait
The process will be executed when the power goes down. The
init process is usually informed about this by a process
that talks to a UPS connected to the computer; init will
wait for the process to finish before continuing.
|
|
powerfail
Similar to powerwait, except that init does not wait for
the process to end.
|
|
powerokwait
This process will be executed as soon as init is informed
that the power has been restored.
|
|
powerfailnow
This process will be executed when init is told that the
battery power of the external UPS is almost empty and the power is
failing (provided that the external UPS and the monitoring
process are able to detect this condition).
|
|
ctrlaltdel
The process will be executed when init receives the
SIGINT signal. This means that someone on the system console has
pressed the Ctrl+Alt+Del key combination. Typically, one wants to
execute some sort of shutdown either to get into single-user level or
to reboot the machine.
|
|
kbrequest
This process will be executed when init receives a signal
from the keyboard handler that a special key combination was
|
|
|
The documentation for this function is not yet complete; more
documentation can be found in the kbd-packages. Basically, you want
to map some keyboard combination to the "KeyboardSignal"
action. For example, to map Alt+Uparrow for this purpose, use the
following in your keymaps file:
|
| alt keycode 103 = KeyboardSignal
|
|
The last field, process, instructs the command to start the process on
this line. Armed with these facts, you can take a look at the SuSE
inittab and see what it does.
The first line (which is not a remark) specifies the default runlevel:
|
| id:2:initdefault:
|
|
You can see that it's in runlevel two. So, if you don't specify any
parameters for init on the boot prompt (as you have seen
before, you can boot into a certain runlevel by entering its number as
a parameter at the LILO prompt), the system will boot into runlevel
two.
The next line is very important, because the first thing it does is
start the script /sbin/init.d/boot after init is
invoked:
|
| si:I:bootwait:/sbin/init.d/boot
|
|
The action entry is bootwait, so nothing else will happen until this
script is finished. It performs the following tasks in this
order:
|
|
|
Mount /proc.
|
|
Start the kernel daemon kerneld.
This enables module loading on demand. Note that this step is no
longer needed with kernel version 2.2 because the kernel loads
modules itself. But because SuSE Linux 6.0 ships with 2.0 kernels,
the kernel daemon is needed.
|
|
Initialize multiple device handling.
You may have MD devices in your system. MD devices are
filesystems, which are contained on more than one partition,
usually some kind of software RAID.
|
|
Activate swap space.
|
|
Start the update daemon.
This process handles pending events and idle callbacks.
|
|
Check filesystems.
Again, a very important step. Remember that the root file system
is mounted read-only by the kernel before init is
invoked. This is still the case, and no other file system has been
mounted yet.
At this point, all filesystems that will be mounted are checked by
running fsck on each partition. The root file system will be
checked, too. It's safe to do because it's mounted in read-only
mode.
Filesystems are actually checked only if they haven 't been
cleanly unmounted, or if the maximum mount count is
reached. The first precaution may cause trouble, and the latter
is usually performed out of paranoia. In most cases, fsck is able
to repair small glitches on the fly without any user
interaction. Sometimes, this is not possible. If this is the
case, the boot script stops at this point and prompts you with
a password request.
|
|
You must type in the root password and then try to repair the file
system manually. Note that only the root file system is mounted, but
in read-only mode. To remount it writable, use the command:
| | # mount -n -o remount,rw /
|
|
Before you do this, make sure that the file system is
functioning. Writing to a corrupted file system can damage it beyond
any chance of repair. The man page of fsck is printed in
the SuSE manual, which is fortunate because you won't be able to
look it up online if your system is damaged.
|
|
At this point, if you've run into any problems with the file
system, you've been able to repair them. Unmount all filesystems
except / and set the root file system back to
read-only. Now press Ctrl+D to exit the root shell. The system
will reboot and should come up without serious errors.
|
|
Remount the root file system in read-write mode.
|
|
Initialize database for kerneld.
|
|
Mount local filesystems according to /etc/fstab.
|
|
Reinit quota.
This step is performed only if a file system had to be checked
|
|
Rebuild the cache file of the dynamic linker (ld.so).
|
|
Set time zone.
|
|
Initialize the network loopback device.
This device is always present, even if "real" networking is not
available. You can always connect to your local host on the IP
address 127.0.0.1, and you are always (the only) member of the
network 127.0.0.0.
|
|
Set hostname and NIS domainname.
|
|
Set and adjust the CMOS clock.
|
|
Clean up.
All files in /var/lock/, /var/run/, and
all their subdirectories will be removed, as well as all files in
/var/spool/uucp/ starting with LCK and all X lock
files /tmp.
|
|
Initialize /var/run/utmp.
|
|
Reinit /etc/psdevtab.
|
|
Start bootup client scripts.
If there are scripts in /sbin/init.d/boot.d, they
will be executed at this point.
|
|
Setup ISA PnP.
If the file /etc/isapnp.conf exists and PNP is
enabled, then the program /sbin/isapnp will be started to
initialize the PNP hardware.
|
|
Start user-defined bootup script.
SuSE provides the file /sbin/init.d/boot.local for user-defined
startup routines. You can edit this script and put whatever you
need for system initialization in it. Exercise caution because
this is a very sensitive part of the system. Test the script
before you reboot your machine. Keep in mind that no network
services are available at this point. An error here may result
in a nonbootable system.
|
|
Save boot messages in /var/log/boot.msg.
All messages the kernel printed up to this point are stored in
this file. This is useful if you want to view the kernel messages
after your system is up and running.
|
|
Enable the DOS EXE binary format.
If the DOS emulation is installed, the DOS binary format will
be registered as a valid executable format, using the proc file
system (see Chapter 4).
|
|
Enable dynamic IP patch.
|
|
Insert memstat module for xosview.
|
|
Check if this is the first system boot.
During the first boot after the initial system installation, YaST
gets invoked to finalize the installation. This behavior is
controlled by the existence of the file
/usr/lib/YaST/.configured2. If this file is found,
/lib/YaST/bootsetup will be started.
|
|
|
After this script is finished, the system is ready to go into the
default runlevel, as specified by the initdefault line.
|
6.1 | Runlevels |
|
We've talked about runlevels quite a bit up until this point but
haven't fully defined what they are. So what are runlevels, anyway?
You can think of runlevels as system modes. Each runlevel has specific
features that are controlled by the services that are active in each
runlevel. SuSE defines its runlevels as shown in Table 6-1
.
|
Table 6-1 |
Runlevels in SuSE Linux |
|
Runlevel |
Function |
S |
Single-user |
0 |
System halt |
1 |
Multi-user without network |
2 |
Multi-user with network |
3 |
Multi-user with network and graphical login |
4 |
Not used |
5 |
Not used |
6 |
System reboot |
|
|
You'll see that each runlevel has a particular scope, depending on the
kind of services the system offers. You can switch between runlevels
by invoking init with the desired runlevel. For
example:
|
| # init 1
|
|
will shut down network services and go into multi-user mode without a network.
|
6.1.1 | 0: System halt |
|
Runlevel 0 halts the system so that you can power off. This is
usually done by calling:
|
| # shutdown -h now
|
|
|
6.1.2 | S: Single-user mode |
|
Single-user mode is for system maintenance. Everyone knows that you
should avoid shutting down a Unix system at all costs. Normally, you
do not have to reboot. Switching to single-user mode allows you to
install applications, add file systems, or perform any other
administrative tasks that require single-user access. Single-user mode
unmounts all filesystems except the root file system, shuts down all
services, and opens only one console terminal for logins.
|
6.1.3 | 1: Multi-user without network |
|
As the name indicates, all multi-user features are enabled and login
prompts are available on the virtual terminals, but no network
services.
|
|
You'll want to enter this runlevel when you modify your network
settings. Assume that you ordinarily run your machine with the network
enabled but that now you have to change your routing table because the
topology of the network changed. First switch to runlevel 1 so that
all network services are shut down. Now it's safe to make changes,
which in this case is to the routing table file
/etc/route.conf (see Part III for more info). After
you've made your changes, switch back to runlevel 2 or 3, and the
new settings will be active. There's no need to reboot the machine.
|
|
|
6.1.4 | 2: Multi-user with network |
|
This is the default runlevel on most SuSE installations. All
multi-user features and all network features are available.
|
6.1.5 | 3: Multi-user with network and graphical login |
|
This is the same as runlevel 2, except that the X server will be
started automatically, and you'll see a graphical login prompt to
begin your X session. You can make this your default runlevel by
either editing /etc/inittab or using the login configuration of
YaST.
|
6.1.6 | 4,5: not used |
|
These two runlevels are not used by the SuSE setup. This doesn't mean
that they can't be used at all. For example, if you want to run a
database server for your office, you can create runlevel 4 (or 5...)
as your database runlevel. The database engine will be active only in
this runlevel.
|
|
You'll find more on this subject in Chapter 7
.
|
|
|
6.1.7 | 6: System reboot |
|
System reboot is like runlevel 0 (system halt), but the machine will
reboot after everything has been shut down. It can be entered by
executing the command
|
| # shutdown -r now291
|
|
You can check the current runlevel with the command runlevel:
|
| > /sbin/runlevel
N 2
|
|
This command tells what the previous runlevel was and what the current
runlevel is. If there is no previous runlevel (because there was no
runlevel change since the last boot), the letter N will be
printed. The output shown means that the machine is in runlevel 2 and
there was no previous runlevel.
|
6.2 | System V init |
|
Now that you've seen what runlevels are about, we can go into more
detail on how they work. Again, the init process is
the key to understanding this. The inittab shown previously
contains these lines to control the runlevels:
|
| # /sbin/init.d/rc takes care of runlevel handling
l0:0:wait:/sbin/init.d/rc 0
l1:1:wait:/sbin/init.d/rc 1
l2:2:wait:/sbin/init.d/rc 2
l3:3:wait:/sbin/init.d/rc 3
#l4:4:wait:/sbin/init.d/rc 4
#l5:5:wait:/sbin/init.d/rc 5
l6:6:wait:/sbin/init.d/rc 6
# what to do in single-user mode
ls:S:wait:/sbin/init.d/rc S
~~:S:respawn:/sbin/sulogin
|
|
As you can see, init calls /sbin/init.d/rc
whenever there is an indication of a runlevel change. SuSE calls this
script the Master Resource Control. The name is
imposing, but what it does is fairly simple. Master Resource Control
executes other scripts located in subdirectories of
/sbin/init.d to switch runlevels.
Before we go into detail, we need to provide some context. You may
have already guessed that /sbin/init.d holds a central
place in the boot process. Chapter 2 discusses the contents
of /sbin but doesn't say much about this directory. Well,
/sbin/init.d contains scripts that start and stop single
services -- beneath boot, boot.local, and
rc. It also contains one subdirectory for each
runlevel. The runlevel subdirectories are named
rc?.d, where the question
mark is replaced by the runlevel name or number.
Each of these subdirectories contains soft links to the script in
/sbin/init.d. This looks complicated, but it's really
quite easy to understand. The links have a certain name scheme. They
begin with a capital S or a capital K,
followed by a two-digit number and the script name in /sbin/init.d.
For example, the directory /sbin/init.d/rc2.d looks like this (partial
listing):
|
| > ls -l /sbin/init.d/rc2.d/
total 0
[...]
lrwxrwxrwx 1 root root 12 Dec 17 21:21 K27nfsserver -> ../nfsserver
lrwxrwxrwx 1 root root 9 Dec 17 21:21 K27pcnfsd -> ../pcnfsd
lrwxrwxrwx 1 root root 8 Dec 24 15:02 K34named -> ../named
lrwxrwxrwx 1 root root 13 Dec 17 21:21 K35boot.setup -> ../boot.setup
lrwxrwxrwx 1 root root 9 Dec 17 21:21 K35routed -> ../routed
lrwxrwxrwx 1 root root 9 Dec 17 21:25 K35syslog -> ../syslog
lrwxrwxrwx 1 root root 6 Dec 17 21:21 K36nfs -> ../nfs
lrwxrwxrwx 1 root root 6 Dec 17 21:21 K37rpc -> ../rpc
lrwxrwxrwx 1 root root 8 Dec 17 21:21 K38route -> ../route
lrwxrwxrwx 1 root root 11 Dec 24 15:02 K39firewall -> ../firewall
lrwxrwxrwx 1 root root 13 Dec 24 15:02 K39masquerade -> ../masquerade
lrwxrwxrwx 1 root root 10 Dec 17 21:21 K40network -> ../network
lrwxrwxrwx 1 root root 9 Dec 17 21:33 K42pcmcia -> ../pcmcia
lrwxrwxrwx 1 root root 8 Dec 17 21:21 K45dummy -> ../dummy
lrwxrwxrwx 1 root root 9 Dec 17 21:21 K50serial -> ../serial
lrwxrwxrwx 1 root root 11 Dec 17 21:38 K81svgatext -> ../svgatext
lrwxrwxrwx 1 root root 10 Dec 17 21:21 K99kerneld -> ../kerneld
lrwxrwxrwx 1 root root 10 Dec 17 21:21 S01kerneld -> ../kerneld
lrwxrwxrwx 1 root root 9 Dec 17 21:21 S02serial -> ../serial
lrwxrwxrwx 1 root root 9 Dec 17 21:33 S03pcmcia -> ../pcmcia
lrwxrwxrwx 1 root root 8 Dec 17 21:21 S04dummy -> ../dummy
lrwxrwxrwx 1 root root 10 Dec 17 21:21 S05network -> ../network
lrwxrwxrwx 1 root root 11 Dec 24 15:02 S06firewall -> ../firewall
lrwxrwxrwx 1 root root 13 Dec 24 15:02 S06masquerade -> ../masquerade
lrwxrwxrwx 1 root root 8 Dec 17 21:21 S07route -> ../route
lrwxrwxrwx 1 root root 6 Dec 17 21:21 S08rpc -> ../rpc
lrwxrwxrwx 1 root root 6 Dec 17 21:21 S09nfs -> ../nfs
lrwxrwxrwx 1 root root 9 Dec 17 21:25 S09syslog -> ../syslog
lrwxrwxrwx 1 root root 13 Dec 17 21:21 S10boot.setup -> ../boot.setup
lrwxrwxrwx 1 root root 9 Dec 17 21:21 S10routed -> ../routed
lrwxrwxrwx 1 root root 8 Dec 24 15:02 S11named -> ../named
lrwxrwxrwx 1 root root 12 Dec 17 21:21 S13nfsserver -> ../nfsserver
lrwxrwxrwx 1 root root 9 Dec 17 21:21 S13pcnfsd -> ../pcnfsd
lrwxrwxrwx 1 root root 11 Dec 17 21:38 S19svgatext -> ../svgatext
lrwxrwxrwx 1 root root 9 Dec 17 21:42 S20apache -> ../apache
[...]
|
|
Okay, now we're back at /sbin/init.d/rc. This script is
called by indicating the runlevel you want to switch into as a
parameter. First it examines and determines the current runlevel; then
it calls each script that begins with a capital K (kill)
in the directory for the current runlevel, with the parameter
stop. The rc-scripts (the common name for all scripts in
/sbin/init.d) respond to this parameter by shutting down
the service for which they are responsible. Later, in Chapter
7
, you can see what these scripts look like, and how to write new
ones of your own. However, before the script is called,
rc looks in the rc-directory of the new runlevel and
checks to see whether there is a start script for the same
service. If so, the stop script won't be called. This is the first
step toward switching from one runlevel to another by halting all
services from the old runlevel that are not active in the new
runlevel.
The second step is to power up the new services, following the same
procedure as just described. The rc script looks in the
subdirectory for the new runlevel, and executes all scripts (except
those in the old runlevel) that start with a capital S
(start) with the parameter start.
When this is done, all services of the new runlevel are available and
rc terminates -- the new runlevel is reached.
|
|
This is called The System V Init Scheme. Most modern Linux
distributions use this or a slightly modified version to manage
runlevels. Its advantage is that services are easily enabled or
disabled. The previous listing shows that the PCMCIA services are
activated in runlevel 2.
Say that, for whatever reason, you want to disable this feature. To do
so, simply rename or remove the links in
/sbin/init.d/rc2.d. A common practice is to change the
first letter that is uppercase to lowercase. Because the
rc script looks for a capital K or
S, it will ignore the scripts in lowercase. This is easy
to do compared with the task of removing links. If you list the
directory, you see what is supposed to be active but has been
disabled. To restore the original settings, simply capitalize the
links. Of course, you can also have a subdirectory in the runlevel
directories and move unused links there, or add a prefix to them
with a placeholder (a period is common). Unix systems allow you
to accomplish what you want in different ways.
|
|
That's almost everything you need to know about init. The remaining
lines in inittab should be easy to understand now. There is a section
about power failure, which is used if you have a UPS attached to your
system and powerd watching it. In this way, the system is able to shut
down before the power goes out. Some other lines are available for
dialing in on a modem or so that you can use your machine as a
voicemail system.
|
6.3 | Shutting down the system |
|
One of init's major tasks is to shut down the
system. Table 6-1 shows that runlevels zero and six
shut down the system. The primary script responsible for a controlled
shutdown is /sbin/init.d/halt, which is called in both
runlevels. It's sort of the reverse of /sbin/init.d/boot.
And just like boot provides boot.local for
local tasks, halt calls /sbin/init.d/halt.local, which is
meant to be customized for local usage.
The script halt.local is the first thing the halt script
calls. After doing this, halt sends the signal SIGTERM to
all processes left running. After a short waiting period, it sends
a SIGKILL command to those processes that are still active.
No user processes should be left now. The halt script continues by
removing the swap space and unmounting all filesystems. In case this
fails for one or more file systems, it syncs them and tries to
remount them read-only. The last step before actually rebooting or
halting the system is to unregister MD devices.
You see that shutting down the machine is much easier than booting it.
|
|
Summary: |
|
The init process is the parent of all processes running
in the system. It controls which processes will be started at boot
time and so determines the look and feel of the system when active.
The system can be booted into different states, called runlevels. A
runlevel is a collection of active services offered to the local users
and/or the network the machine is part of. SuSE conforms to the System
V Init structure, which means that the runlevels are represented in a
directory structure containing the boot scripts (rc-scripts) for
various runlevels.
|
|