Linux System Initialization

Mr. Bandel takes a look at system initialization for various distributions.
inittab Specifics

Reading inittab, we'll be skipping any lines that begin with a “#”, since these are comments and ignored by init. The rest of the lines can be easily read as many other typical UNIX-like configuration tables, i.e., each column is separated by a “:” (id:runlevel:action:process) and can be read as follows:

  • id: This first column is a unique identifier for the rest of the line. On newer Linux systems, it may be up to four alphanumeric characters long, but is typically limited to two. Older systems had a two-character limitation, and most distributions have not changed that custom.

  • runlevel: The second column indicates what runlevel(s) this row is valid for. This column may be null or contain any number of valid runlevels.

  • action: This can be several different things, the most common being respawn, but can also be any one of the following: once, sysinit, boot, bootwait, wait, off, ondemand, initdefault, powerwait, powerfail, powerokwait, ctrlaltdel or kbrequest.

  • process: This is the specific process or program to be run.

Each row in inittab has a specific, unique identifier. Normally, you will want this to be something easily associated with the specific action performed. For example, if you want to put a getty on the first serial port, you might use the identifier s1. When I execute w to see what processes are running, I can more easily identify who is logged in via the modem on com1 when that user is identified as being on s1.

The runlevels are identified as 0 to 6 and A to C by default. Runlevels 0, 1 and 6 are special and should not be changed casually. These correspond to system halt, maintenance mode and system reboot, respectively. Changing runlevel 1, for example, can have far-reaching consequences. Note that to enter maintenance mode (state 1), you can pass init (via telinit2) the argument 1. Alternately, you can use S or s for maintenance mode. If you change what transpires for state 1, the same changes will apply when S or s is passed. However, runlevels 2 through 5 can be customized as desired.

Many systems have the command runlevel (usually found in /sbin). Executing this command will output the previous runlevel and the present runlevel as follows: N 2. The N indicates no previous runlevel. If you make a change, say, to state 3 and then reissue the runlevel command, you'll see 2 3.

Since a good demonstration will illustrate better than just telling you about it, try this on your system. (Note that I have done this successfully on Debian 1.3 and a few others, such as an older Red Hat [perhaps 3.0], but not many others, so your mileage may vary.) As root (only root can tell init to change states), issue the init command. You should see a usage message telling you to pass init an argument consisting of a number from 0 to 6, the letters A to C or S or Q. Lowercase letters are syntactically the same as their uppercase counterparts. If you pass init anything other than legal values, you should receive this same usage message. Now pass init the argument 8, as in init 8 (or telinit 8, if you wish). If nothing appears to happen, don't worry. Now type runlevel again, and you should see 2 8. If you don't have runlevel on your system, try ps ax | grep init and you may see init [8]. You may or may not see the runlevel listed in square brackets. Once you have confirmed that you actually did change to runlevel 8, change back to your previous runlevel. Note that, should your gettys die, they won't respawn at this runlevel, so you could have a problem logging in again after you log out. If you are unsure what your default runlevel is, look in inittab near the top for a line where the first column is id and the third is initdefault. The second column in this line is the default runlevel. An example line looks like this:


This demonstration was designed to show you that while runlevels 7 to 9 are undocumented, they actually are available for use should you need them. (I'll explain later why nothing happened when you changed states). They aren't used only because it's not customary. The customizable states for Linux (2 through 5) are usually more than sufficient for anyone.

The letters A to C are used when you want to spawn a daemon listed in inittab and have this “runlevel” designation on a one-time basis (on demand). Therefore, telling init to change to state C doesn't change the runlevel, it just performs the action listed on the line where the runlevel is listed as C. Perhaps you want to put a getty on a port to receive a call, but only after receiving a voice call first (not every time). Let's further suppose you want to be ready to receive either a data call or a fax call, and when you get the voice message, you'll know which you want. You can put two lines in inittab, each with its own ID, and each with a runlevel such as A for data and B for fax. When you know which you need, you simply spawn the appropriate one from a command line: telinit A or telinit B. The appropriate getty will be put on the line until the first call is received. Once the caller terminates the connection, the getty will drop, because by definition, an on-demand process will not respawn.

The other two letters, S and Q, are special. As I noted earlier, S will bring your system to maintenance mode which is the same as changing state to runlevel 1. The Q is necessary to tell init to reread inittab. inittab may be changed as often as required, but will be read only under certain circumstances: one of its processes dies (do we need to respawn another?), on a powerfail signal from a power daemon (or the command line), or when told to change state by telinit. So the Q argument will tell init, “I've changed something, please reread the inittab.”

Before I delve into sections grouped by distribution, I'd like to emphasize that they don't stand alone. Each of the following sections will complement the others.