Purchase | Copyright © 2002 Paul Sheer. Click here for copying permissions. | Home |
This chapter explains how LINUX (and a UNIX system in general) initializes itself. It follows on from the kernel boot explained in Section 31.2. We also go into some advanced uses for mgetty, like receiving of faxes.
After the kernel has been unpacked into memory, it begins to execute, initializing hardware. The last thing it does is mount the root file system, which necessarily contains a program /sbin/init, which the kernel executes. init is one of the only programs the kernel ever executes explicitly; the onus is then on init to bring the UNIX system up. init always has the process ID 1.
For the purposes of init, the (rather arbitrary) concept of a UNIX run level was invented. The run level is the current operation of the machine, numbered run level 0 through run level 9. When the UNIX system is at a particular run level, it means that a certain selection of services is running. In this way, the machine could be a mail server or an X Window workstation depending on what run level it is in.
The traditionally defined run levels are:
0 | Halt. |
---|---|
1 | Single-user mode. |
2 | Multiuser, without network file system (NFS). |
3 | Full multiuser mode. |
4 | Unused. |
5 | X Window System Workstation (usually identical to run level 3). |
6 | Reboot. |
7 | Undefined. |
8 | Undefined. |
9 | Undefined. |
The idea here is that init begins at a particular run level that can then be manually changed to any other by the superuser. init uses a list of scripts for each run level to start or stop each of the many services pertaining to that run level. These scripts are /etc/rc? .d/KNNservice or /etc/rc? .d/SNNservice [On some systems /etc/rc.d/rc? .d/... .], where NN, K, or S is a prefix to force the order of execution (since the files are executed in alphabetical order).
These scripts all take the options start and stop on the command-line, to begin or terminate the service.
For example, when init enters, say, run level 5 from run level 3, it executes the particular scripts from /etc/rc3.d/ and /etc/rc5.d/ to bring up or down the appropriate services. This may involve, say, executing
|
/etc/rc3.d/S20exim stop |
and similar commands.
init has one config file: /etc/inittab which is scanned once on bootup.
A minimal inittab file might consist of the following.
5 10 15 20 |
id:3:initdefault: 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 ud::once:/sbin/update 1:2345:respawn:/sbin/getty 38400 tty1 2:2345:respawn:/sbin/getty 38400 tty2 3:2345:respawn:/sbin/getty 38400 tty3 4:2345:respawn:/sbin/getty 38400 tty4 S0:2345:respawn:/sbin/mgetty -n 3 -s 115200 ttyS0 57600 S4:2345:respawn:/sbin/mgetty -r -s 19200 ttyS4 DT19200 x:5:respawn:/usr/bin/X11/xdm -nodaemon |
The lines are colon-separated fields and have the following meaning (lots more can be gotten from inittab(5)):
If you modify the inittab file, init will probably not notice until you issue it a SIGHUP. This is the same as typing
|
telinit q |
which causes init to reread /etc/inittab.
You get a respawning too fast error when an inittab line makes no sense [These errors are common and very irritating when you are doing console work, hence an explicit section on it.]: like a getty running on a non-functioning serial port. Simply comment out or delete the appropriate line and then run
|
telinit q |
Switching run levels manually is something that is rarely done. The most common way of shutting down the machine is to use:
|
shutdown -h now |
which effectively goes to run level 0, and
|
shutdown -r now |
which effectively goes to run level 6.
You can also specify the run level at the LILO: prompt. Type
|
linux 1 |
or
|
linux single |
to enter single-user mode when booting your machine. You change to single-user mode on a running system with:
|
telinit S |
You can forcefully enter any run level with
|
telinit <N> |
The getty man page begins with:
getty opens a tty port, prompts for a login name and invokes the /bin/login command. It is normally invoked by init(8).Note that getty, agetty, fgetty and mingetty are just different implementations of getty.
The most noticeable effect of init running at all is that it spawns a login to each of the LINUX virtual consoles. It is the getty (or sometimes mingetty) command as specified in the inittab line above that displays this login. Once the login name is entered, getty invokes the /bin/login program, which then prompts the user for a password.
The login program (discussed in Section 11.7) then executes a shell. When the shell dies (as a result of the user exiting the session) getty is just respawned.
Together with Chapter 31 you should now have a complete picture of the entire bootup process:
The original purpose of getty was to manage character terminals on mainframe computers. mgetty is a more comprehensive getty that deals with proper serial devices. A typical inittab entry is
|
S4:2345:respawn:/sbin/mgetty -r -s 19200 ttyS4 DT19200 |
which would open a login on a terminal connected to a serial line on /dev/ttyS4. See page for information on configuring multiport serial cards.
(The LINUX devices /dev/tty1 through /dev/tty12 as used by getty emulate classic terminals in this way.)
mgetty will log to /var/log/mgetty.log.ttyS?. This log file contains everything you need for troubleshooting. It is worthwhile running tail -f on these files while watching a login take place.
Running mgetty (see mgetty(8)) is a common and trivial way to get a dial login to a LINUX machine. Your inittab entry is just
|
S0:2345:respawn:/sbin/mgetty -n 3 -s 115200 ttyS0 57600 |
where -n 3 says to answer the phone after the 3rd ring. Nothing more is needed than to plug your modem into a telephone. You can then use dip -t, as done in Section 41.1.1, to dial this machine from another LINUX machine. Here is an example session: [This example assumes that an initialization string of AT&F1 is sufficient. See Section 3.5.]
5 10 15 |
[root@cericon]# dip -t DIP: Dialup IP Protocol Driver version 3.3.7o-uri (8 Feb 96) Written by Fred N. van Kempen, MicroWalt Corporation. DIP> port ttyS0 DIP> speed 57600 DIP> term [ Entering TERMINAL mode. Use CTRL-] to get back ] AT&F1 OK ATDT5952521 CONNECT 19200/ARQ/V34/LAPM/V42BIS Red Hat Linux release 6.1 (Cartman) Kernel 2.2.12-20 on an i686 remote.dialup.private login: |
Note that this is purely a login session having nothing to do with PPP dialup.
mgetty receives faxes by default, provided your modem supports faxing [If your modem says it supports faxing, and this still does not work, you will have to spend a lot of time reading through your modem's AT command set manual, as well as the mgetty info documentation.]and provided it has not been explicitly disabled with the -D option. An appropriate inittab line is,
|
S0:2345:respawn:/sbin/mgetty -x 4 -n 3 -s 57600 -I '27 21 7654321' ttyS0 57600 |
The options mean, respectively, to set the debug level to 4, answer after 3 rings, set the port speed to 57600, and set the fax ID number to 27 21 7654321. Alternatively, you can use the line
|
S0:2345:respawn:/sbin/mgetty ttyS0 57600 |
and instead put your configuration options in the file mgetty.config under /etc/mgetty+sendfax/:
|
debug 4 rings 3 speed 57600 fax-id 27 21 7654321 |
Faxes end up in /var/spool/fax/incoming/ as useless .g3 format files, but note how the command
|
strings /sbin/mgetty | grep new_fax |
gives
|
/etc/mgetty+sendfax/new_fax |
which is a script that mgetty secretly runs when new faxes arrive. It can be used to convert faxes into something (like .gif graphics files [I recommend .png over .gif any day, however.]) readable by typical office programs. The following example /etc/mgetty+sendfax/new_fax script puts incoming faxes into /home/fax/ as .gif files that all users can access. [Modified from the mgetty contribs.] Note how it uses the CPU-intensive convert program from the ImageMagic package.
5 10 15 20 25 30 |
#!/bin/sh # you must have pbm tools and they must be in your PATH PATH=/usr/bin:/bin:/usr/X11R6/bin:/usr/local/bin HUP="$1" SENDER="$2" PAGES="$3" shift 3 P=1 while [ $P -le $PAGES ] ; do FAX=$1 BASENAME=`basename $FAX` RES=`echo $BASENAME | sed 's/.\(.\).*/\1/'` if [ "$RES" = "n" ] ; then STRETCH="-s" else STRETCH="" fi nice g32pbm $STRETCH $FAX > /tmp/$BASENAME.pbm \ && rm -f $FAX \ && nice convert -colorspace gray -colors 16 -geom \ '50%x50%' /tmp/$BASENAME.pbm /home/fax/$BASENAME.gif \ && rm -f /tmp/$BASENAME.pbm \ && chmod 0666 /home/fax/$BASENAME.gif shift P=`expr $P + 1` done exit 0 |