Monday, May 18, 2009

Run Levels

Most users are only familiar with two run states or run levels. The one that is most commonly experienced is what is referred to a multiuser mode. This is where logins are enabled on terminals when the network is running and the system is behaving "normally." The other run level is system maintenance or single-user mode, when only a single user is on the system (root), probably doing some kind of maintenance tasks. Although it could be configured to allow logins by other users, usually the system is so configured that only one login is allowed on the system console.

On every system that I have encountered, Linux will automatically boot into run-level 3. This is the normal operating mode. To get to a lower run level (for example, to do system maintenance), the system administrator must switch levels manually.

It is generally said that the "system" is in a particular run-level. However, it is more accurate to say that the init process is in a particular run level, because init determines what other processes are started at each run-level.

In addition to the run levels most of us are familiar with, there are several others that the system can run in. Despite this fact, few of them are hardly ever used. For more details on what these run levels are, take a look at the init man-page.

The system administrator can change to a particular run level by using that run level as the argument to init. For example, running init 2 would change the system to run-level 2. To determine what processes to start in each run level, init reads the /etc/inittab file. This is defined by the second field in the /etc/inittab file. Init reads this file and executes each program defined for that run level in order. When the system boots, it decides what run level to go into based on the initdefault entry in /etc/inittab.

The fields in the inittab file are:

idunique identity for that entry
rstate run level in which the entry will be processed
action tells init how to treat the process specifically
process what process will be started

One thing I need to point out is that the entries in inittab are not run exactly according to the order in which they appear. If you are entering a run level other than S for the first time since boot-up, init will first execute those entries with a boot or bootwait in the third column. These are those processes that should be started before users are allowed access to the system, such as checking then mounting the status of the file systems.

In run-level 3, the /sbin/mingetty process is started on the terminals specified. The getty process gives you your login: prompt. When you have entered your logname for the first time, getty starts the login process, which asks you for your password. If your password is incorrect, you are prompted to input your logname again. If your password is correct, then the system starts your "login shell. " Note that what gets started may not be a shell at all, but some other program. The term "login shell" is the generic term for whatever program is started when you login. This is defined by the last field of the corresponding entry in /etc/passwd.

Keep in mind that you can move in either direction, that is, from a lower to higher run level or from a higher to lower run level without having to first reboot. init will read the inittab and start or stop the necessary processes. If a particular process is not defined at a particular run level, then init will kill it. For example, assume you are in run-level 3 and switch to run-level 1. Many of the processes defined do not have a 1 in the second field. Therefore, when you switch to run-level 1, those processes and all their children will be stopped.

If we look at the scripts in rc1.d, we see there all the scripts are kill scripts, with the exception of one start script. It is this start script that actually kills all the processes. It does exec init -t1 S, which brings the system into maintenance mode in one (-t1) minute.

To shutdown the system immediately, you could run

which will bring the system immediately into run-level 0. As with run-level 1, there is only one start script for run-level 0. It is this script that kills all the processes, unmounts all the file systems, turns off swap, and brings the system down.

After it has started the necessary process from inittab, init just waits. When one of its "descendants" dies (a child process of a child process of a child process, etc., of a process that init started), init rereads the inittab to see what should be done. If, for example, there is a respawn entry in the third field, init will start the specified process again. This is why when you log out, you immediately get a new login: prompt.

Because init just waits for processes to die, you cannot simply add an entry to inittab and expect the process to start up. You have to tell init to reread the inittab. However, you can force init to reread the inittab by running init (or telinit) Q.

In addition to the run levels we discussed here, several more are possible. There are three "pseudo" run-levels a, b, and c. These are used to start specific programs as needed or "on demand". Any listed in inittab with the approapriate run-level will be started, however no actual run-level change occurs. If you're curious about the details, take a look at the init(8) man-page or the section on init-scripts.

bootExecuted during system boot.
bootwaitExecuted during system boot, but init waits until they have completed.
initdefaultThe default run level init starts after the system boots.
ondemandExecuted when one of the "on demand" run levels is called (a,b, and c)
powerwaitExecuted when the system power fails. Init will wait until the command completes.
powerfailExecuted when the system power fails, but init will not wait for completion.
powerokwaitExecuted when init is informed that power has been restored.
powerfailnowExecuted when init is informed that the external battery is empty.
resumeExecuted when init is told by the kernel that "Software Suspend"
sysinitExecuted during system boot before any boot or bootwait entries.
respawnRestarted if the processes stops.
waitStarted once when the specific run-level is entered and init waits for completion.
onceStarted once when the specific run-level is entered but init does not wait for completion.
ctrlaltdelExecute when someone on the system console presses CTRL-ALT-DEL.

Table - List of inittab actions.

If necessary, you can add your own entries into /etc/inittab. However, what is typically done is that init-scripts are added to the appropriate directory for the run-level where you want to start it. Depending on your Linux distribution, you could simply copy it into /etc/rc.d and use the appropriate admin tool, like Yast2 to add the script to the appropriate directory. For more details see the section on init-scripts.

Note however, that simply changing /etc/inittab is not enough. You need to tell the init process to re-read it. Normally init will re-read the file when it changes run levels or by sending it a hangup signal with

kill -HUP .

Also running the command

telinit q

will tell init to reread it.

Be extremely careful if you edit the /etc/inittab file by hand. An editing mistake could prevent your system from booting into a specific run level. If you use the boot, bootwait or sysinit actions, you could prevent your system from booting at all. Therefore, like with any system file it is good idea to make a backup copy first. If you make a mistake that prevents a particular program from starting, and the action is respawned, init might get caught in a loop. That is, init tries to start the program, cannot, for whatever reason and then tries to start it again. If init finds that it is starting the program more than 10 times within 2 minutes, it will treat this as an error and stops trying. Typically you will get messages in the system log that the process is "respawning too rapidly".

No comments:

Post a Comment