There will be a lot of talk about runlevels. So perhaps this is a good time to give a bit of explanation about runlevels. A runlevel is a *nix method to determine the service level of a certain machine. Per runlevel one would be able to define which services will be active and which not. In principle there can be many runlevels. In practice this is limited to 5:
A single user runlevel in which an absolute minimum of services is running. This runlevel is often used for system maintenance.
A multi user runlevel in which all the services run which are to be offered. These services can be a HTTP server , e-mail server, SQL server or what ever else. Just what the sysop (you!) wants.
A multi user runlevel, same as before, only this time with a graphical login manager.
Beside these runlevels there are 2 special runlevels:
A runlevel to halt the system.
A runlevel to reboot the system.
If I ask for a forest view of all the processes on my box, I would get something like this:
bilbo@bilbo:~$ pstree init-+-4*[agetty] |-atd |-bash |-bash---startx---xinit-+-X | `-xinitrc-+-bbmail | `-blackbox-+-mozilla-bin---mozilla-bin---4+ | `-rxvt---bash---pstree |-crond |-dhcpcd |-fetchmail |-gpm |-gvim |-httpd---7*[httpd] |-inetd---in.identd---in.identd---5*[in.identd] |-keventd |-khubd |-klogd |-kreiserfsd |-loop0 |-loop1 |-lpd |-mdrecoveryd |-named |-2*[sendmail] `-syslogd bilbo@bilbo:~$
What pstree shows is a sort of "tree structure" view of all the processes on my box. It looks a bit like a directory structure. What catches the eye (mine at least) is that the "root" in this view is "init". From init all other processes spawn. And that is not by chance.
From the manpage:
INIT(8) Linux System Administrator's Manual INIT(8) NAME init, telinit - process control initialization SYNOPSIS /sbin/init [ -a ] [ -s ] [ -b ] [ -z xxx ] [ 0123456Ss ] /sbin/telinit [ -t sec ] [ 0123456sSQqabcUu ] DESCRIPTION Init Init is the parent of all processes. Its primary role is to create processes from a script stored in the file /etc/inittab (see inittab(5)). This file usually has entries which cause init to spawn gettys on each line that users can log in. It also controls autonomous processes required by any particular system.
There are a few important remarks in here:
Init is the parent of all processes.
Init starts processes from a file /etc/inittab.
Init is in control of autonomous processes (daemons).
But why is it that init is the "mother of all processes"?
From the manpage (regel 43)
BOOTING After init is invoked as the last step of the kernel boot sequence, it looks for the file /etc/inittab to see if there is an entry of the type initdefault (see inittab(5)). The initdefault entry determines the initial runlevel of the system. If there is no such entry (or no /etc/inittab at all), a runlevel must be entered at the system console.
So the last thing the kernel does when it boots is to start init. Init on its turn will work its way through /etc/inittab.
Init's manpage gives a lot more info. But perhaps for us it is a good time to take a look at /etc/inittab. This seems to be a pretty important file.
From the manpage:
INITTAB(5) Linux System Administrator's Manual INITTAB(5) NAME inittab - format of the inittab file used by the sysv-compatible init process DESCRIPTION The inittab file describes which processes are started at bootup and during normal operation (e.g. /etc/init.d/boot, /etc/init.d/rc, gettys...). Init(8) distinguishes multiple run- levels, each of which can have its own set of processes that are started. Valid runlevels are 0-6 plus A, B, and C for ondemand entries. An entry in the inittab file has the following format: id:runlevels:action:process
Whoha, shock!. It says: "Used by the sysv-compatible init process". And this is Slackware?
Yes this is Slackware, and Slackware uses Sys V init. Just for kicks, lets have a look at the Slackware package description:
bilbo@bilbo:~$ head -n 14 /var/log/packages/sysvinit-2.84-i386-18 PACKAGE NAME: sysvinit-2.84-i386-18 COMPRESSED PACKAGE SIZE: 232 K UNCOMPRESSED PACKAGE SIZE: 560 K PACKAGE LOCATION: /var/log/mount/slackware/a/sysvinit-2.84-i386-18.tgz PACKAGE DESCRIPTION: sysvinit: sysvinit (init, the parent of all processes) sysvinit: sysvinit: System V style init programs by Miquel van Smoorenburg that control sysvinit: the booting and shutdown of your system. These support a number of sysvinit: system runlevels, each with a specific set of utilities spawned. sysvinit: For example, the normal system runlevel is 3, which starts agetty sysvinit: on virtual consoles tty1 - tty6. Runlevel 4 starts xdm. sysvinit: Runlevel 0 shuts the system down. sysvinit: bilbo@bilbo:~$
So let nobody ever tell you that Slackware does not use Sys V init. It just uses it in a "BSD style".
Enough fun..... lets have a look at /etc/inittabs format:
Again from the manpage:
id:runlevels:action:process Lines beginning with `#' are ignored. id is a unique sequence of 1-4 characters which iden- tifies an entry in inittab (for versions of sysvinit compiled with libraries < 5.2.18 or a.out libraries the limit is 2 characters). Note: For gettys or other login processes, the id field should be the tty suffix of the corresponding tty, e.g. 1 for tty1. Otherwise, the login accounting might not work correctly. runlevels lists the runlevels for which the specified action should be taken. action describes which action should be taken. process specifies the process to be executed. If the pro- cess field starts with a `+' character, init will not do utmp and wtmp accounting for that process. This is needed for gettys that insist on doing their own utmp/wtmp housekeeping. This is also a historic bug.
The file is consists of lines, each made out of 4 fields, separated by a ":"
id - an identifier for the line
runlevels - a list with zero 1 or more runlevels for which this action should take place
action - the action that should take place, you will find them summarized in inittab's manpage. I'll quote them when appropriate
process - the process which will be started by init
Complex? It is not that bad.... here is my /etc/inittab:
bilbo@bilbo:~$ cat /etc/inittab # # inittab This file describes how the INIT process should set up # the system in a certain run-level. # # Version: @(#)inittab 2.04 17/05/93 MvS # 2.10 02/10/95 PV # 3.00 02/06/1999 PV # 4.00 04/10/2002 PV # # Author: Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org> # Modified by: Patrick J. Volkerding, <volkerdi@slackware.com> # # These are the default runlevels in Slackware: # 0 = halt # 1 = single user mode # 2 = unused (but configured the same as runlevel 3) # 3 = multiuser mode (default Slackware runlevel) # 4 = X11 with KDM/GDM/XDM (session managers) # 5 = unused (but configured the same as runlevel 3) # 6 = reboot # Default runlevel. (Do not set to 0 or 6) id:3:initdefault: # System initialization (runs when system boots). si:S:sysinit:/etc/rc.d/rc.S # Script to run when going single user (runlevel 1). su:1S:wait:/etc/rc.d/rc.K # Script to run when going multi user. rc:2345:wait:/etc/rc.d/rc.M # What to do at the "Three Finger Salute". ca::ctrlaltdel:/sbin/shutdown -t5 -r now # Runlevel 0 halts the system. l0:0:wait:/etc/rc.d/rc.0 # Runlevel 6 reboots the system. l6:6:wait:/etc/rc.d/rc.6 # What to do when power fails. pf::powerfail:/sbin/genpowerfail start # If power is back, cancel the running shutdown. pg::powerokwait:/sbin/genpowerfail stop # These are the standard console login getties in multiuser mode: c1:1235:respawn:/sbin/agetty 38400 tty1 linux c2:1235:respawn:/sbin/agetty 38400 tty2 linux c3:1235:respawn:/sbin/agetty 38400 tty3 linux c4:1235:respawn:/sbin/agetty 38400 tty4 linux c5:1235:respawn:/sbin/agetty 38400 tty5 linux c6:12345:respawn:/sbin/agetty 38400 tty6 linux # Local serial lines: #s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100 #s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100 # Dialup lines: #d1:12345:respawn:/sbin/agetty -mt60 38400,19200,9600,2400,1200 ttyS0 vt100 #d2:12345:respawn:/sbin/agetty -mt60 38400,19200,9600,2400,1200 ttyS1 vt100 # Runlevel 4 used to be for an X window only system, until we discovered # that it throws init into a loop that keeps your load avg at least 1 all # the time. Thus, there is now one getty opened on tty6. Hopefully no one # will notice. ;^) # It might not be bad to have one text console anyway, in case something # happens to X. x1:4:wait:/etc/rc.d/rc.4 # End of /etc/inittab bilbo@bilbo:~$
Only 74 lines of text (just about an A4 (ok folio)), if you would take away the comments there would be only 16 lines left! But you will learn that the comments are worth reading.
Lets start by taking /etc/inittab apart....
# Author: Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org> # Modified by: Patrick J. Volkerding, <volkerdi@slackware.com>
The last version of the file has been made by Miquel van Smoorenburg (sounds dutch) and it is modified for Slackware by Patrick J. Volkerding (Slackware's maintainer(yes Slackware is a one mans job)). The comment does not do much, but it does belong there. Lets call it GPL at work.
# These are the default runlevels in Slackware: # 0 = halt # 1 = single user mode # 2 = unused (but configured the same as runlevel 3) # 3 = multiuser mode (default Slackware runlevel) # 4 = X11 with KDM/GDM/XDM (session managers) # 5 = unused (but configured the same as runlevel 3) # 6 = reboot
Again a piece of comment, which of course does not do anything. But it makes what is to follow a lot clearer. What you see is a description of the 7 runlevels as in use by Slackware. Run levels 2 and 5 are not in use, you will see later on that they use the same scripts as runlevels 3.
# Default runlevel. (Do not set to 0 or 6) id:3:initdefault:
Finally something is actually done. It is a normal inittab line; 4 fields, separated by a ":". The action here is "initdefault", according to the manpage:
initdefault An initdefault entry specifies the runlevel which should be entered after system boot. If none exists, init will ask for a runlevel on the console. The process field is ignored.
Here the default runlevel is configured. But of course that is what it said in the leading comment. So the default runlevel for Slackware is runlevel 3; a multi-user runlevel with console/text login.
This is the runlevel init will enter if its not signaled (by a command like `telinit 1`) to enter an other runlevel, i.e. when the system boots.
# System initialization (runs when system boots). si:S:sysinit:/etc/rc.d/rc.S
The action here is "sysinit" and it's meaning is quite obvious, but lets have a look at the manpage anyway:
sysinit The process will be executed during system boot. It will be executed before any boot or bootwait entries. The runlevels field is ignored.
Allthough the runlevel "S" is stated, it is actually ignored. The program that will run is /etc/rc.d/rc.S, which is a script. You will see that all of Slackware's init scripts are in /etc/rc.d. In /etc/rc.d/rc.S the system will be initialised as we will see when we discuss the script later on.
# Script to run when going single user (runlevel 1). su:1S:wait:/etc/rc.d/rc.K
The action here is wait:
wait The process will be started once when the specified runlevel is entered and init will wait for its termination.
The script (that is what it is) will be called when entering runlevels 1 and S (S for single). The action "wait" makes that init will hold all other actions until the processing of /etc/rc.d/rc.K finishes. In /etc/rc.d/rc.K the services are started needed for a singe user runlevel. Later on you will see those are not a whole lot.
# Script to run when going multi user. rc:2345:wait:/etc/rc.d/rc.M
Again the action is wait. This says the script /etc/rc.d/rc.M is called for the runlevels 2,3,4 and 5. So in essence for all the "normal" runlevels except runlevel 1. In /etc/rc.d/rc.M all the services for a multi-user runlevel are started. Quite a script as we will see in a while.
The lines we have seen so far are used to determine what hapens after a system boots. In all cases init will wait till the started process (the script) terminates. The next couple of lines are actions that init should take in special circumstances and do not really belong to any specific runlevel.
# What to do at the "Three Finger Salute". ca::ctrlaltdel:/sbin/shutdown -t5 -r now
Not just MS knows about the "3 finger salute". But in Linux you can decide for youself what happen when it is given. To be complete here is init's manpage entry about this action:
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.
On a Slackware system the command `/sbin/shutdown -t5 -r now` is executed.
SHUTDOWN(8) Linux System Administrator's Manual SHUTDOWN(8) NAME shutdown - bring the system down SYNOPSIS /sbin/shutdown [-t sec] [-arkhncfF] time [warning-message] DESCRIPTION shutdown brings the system down in a secure way. All logged-in users are notified that the system is going down, and login(1) is blocked. It is possible to shut the system down immediately or after a specified delay. All processes are first notified that the system is going down by the signal SIGTERM. This gives programs like vi(1) the time to save the file being edited, mail and news process ing programs a chance to exit cleanly, etc. shutdown does its job by signalling the init process, asking it to change the runlevel. Runlevel 0 is used to halt the sys tem, runlevel 6 is used to reboot the system, and runlevel 1 is used to put to system into a state where administra tive tasks can be performed; this is the default if nei ther the -h or -r flag is given to shutdown. To see which actions are taken on halt or reboot see the appropriate entries for these runlevels in the file /etc/inittab.
The -r means that a reboot will follow, this is done by signaling init to enter runlevel 6. The delay is 5 seconds from now. If you are a uptime junkie you could make the "3 finger salute" do something completely different, and in effect force a user to give the shutdown command explicitly. (Disabling ctrl-alt-del is not such a bad idea if you have a server farm mix with NT like systems and Linux.)
Off course there is no need for the second field for the runlevel. Init reacts on a signal from the outside world.
# Runlevel 0 halts the system. l0:0:wait:/etc/rc.d/rc.0
Again the action is wait, so init will once again wait for the script to finish. On entering runlevel 0 init will execute /etc/rc.d/rc.0 (that's a zero ;)). What this script does is bring all started processes down in a safe way. Not every program likes when you would simply pull the plug. As a last action it will call poweroff which will shutsdown the system or signal the user that he can pull the plug.
# Runlevel 6 reboots the system. l6:6:wait:/etc/rc.d/rc.6
This entry is verry simular to the previous entry. That simular in fact that /etc/rc.d/rc.0 is a symbolic link to /etc/rc.d/rc.6. The two scripts are identical. The way the script is called determines what the last step will be. In the case of runlevel 6 (this case) the last command will be reboot.
# What to do when power fails. pf::powerfail:/sbin/genpowerfail start # If power is back, cancel the running shutdown. pg::powerokwait:/sbin/genpowerfail stop
These next two entries can be adressed in one go. They have a lot to do with each other. The actions are:
powerokwait This process will be executed as soon as init is informormed that the power has been restored. powerfailnow This process will be executed when init is told that the battery 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).
Both lines have something to do with the action that will be taken as a result of a power faillure (or actually the draining of the UPS battries). `/sbin/genpowerfail start' begins by bringing the system down. `/sbin/genpowerfail stop` tries to interrupt the system going down in case the power is restored. Perhaps you notice that the start action does not wait for the script to finish. If it would have waited, one would not be able to ineterrupt the shutdown. `/sbin/genpowerfail` is a script which uses 'shutdown', if you have an UPS you should read the script /sbin/genpowerfail.
We've now reached the point where the system is just about operational. The sysinit scrip has executed. The default runlevel script(s) have been executed, /etc/rc.d/rc.K for the single user runlevel 1 and /etc/rc.d/rc.M for the multi user runlevels 2,3,4 and 5. All intended daemons are running. And in a multi users runlevel one would be able to logon with telnet or ssh, assuming these daemons have been started in /etc/rc.d/rc.M. If your system is a server without display and keyboard you could actually leave it like this.
What isn't possible at the moment is to logon at the console. And from time to time being able to log in comes in quite handy. Console logons are the next task of init.
# These are the standard console login getties in multiuser mode: c1:1235:respawn:/sbin/agetty 38400 tty1 linux c2:1235:respawn:/sbin/agetty 38400 tty2 linux c3:1235:respawn:/sbin/agetty 38400 tty3 linux c4:1235:respawn:/sbin/agetty 38400 tty4 linux c5:1235:respawn:/sbin/agetty 38400 tty5 linux c6:12345:respawn:/sbin/agetty 38400 tty6 linux
And right away we have a new action, the inittab manpage:
respawn The process will be restarted whenever it termi- nates (e.g. getty).
So the started process, /sbin/agetty, will be restarted when it terminates. And apperently are started for virtual consoles tty1 through tty6 for the runlevels 1,2,3 and 5. These are the runlevels without X. Except for the agetty on tty6 which is allso started for runlevel 4. The runlevel with X.
The agetty man page gives us an idea what agetty actually does:
AGETTY(8) AGETTY(8) NAME agetty - alternative Linux getty SYNOPSIS agetty [-ihLmnw] [-f issue_file] [-l login_program] [-I init] [-t timeout] [-H login_host] port baud_rate,... [term] agetty [-ihLmnw] [-f issue_file] [-l login_program] [-I init] [-t timeout] [-H login_host] baud_rate,... port [term] DESCRIPTION agetty opens a tty port, prompts for a login name and invokes the /bin/login command. It is normally invoked by init(8).
So agetty waits on a tty port untill somebody tries to login, at which moment is will execute /bin/login.
LOGIN(1) LOGIN(1) NAME login - begin session on the system SYNOPSIS login [-p] [username] [ENV=VAR ...] login [-p] [-h host] [-f username] login [-p] -r host DESCRIPTION login is used to establish a new session with the system. It is normally invoked automatically by responding to the login: prompt on the user's terminal. login may be spe- cial to the shell and may not be invoked as a sub-process. Typically, login is treated by the shell as exec login which causes the user to exit from the current shell. Attempting to execute login from any shell but the login shell will produce an error message.
And with login a new session is started on the system.
Lets look back at the output of pstree:
bilbo@bilbo:~$ pstree init-+-4*[agetty] |-atd |-bash |-bash---startx---xinit-+-X | `-xinitrc-+-bbmail | `-blackbox-+-mozilla-bin---mozilla-bin---4+ | `-rxvt---bash---pstree
Shoot! Shouldn't there be 6 agetty's?
Well.... yes, and at one time there actually were 6. But apperantly I have logged in twice via a virtual console. Once without any other program started, and once with an startx running.... an X session it seems.
Agetty wil start again whenever I logout, with that respawn... remember. It would be kinda funny if agetty would start sooner, multiple users that could log in on the same virtual console?
*Nix has allways given different ways to connect to a system. We have allready seen 2 of them:
Via the network - with telnet, ssh or such.
Via the keyboard, monitor and mouse connected to the system directly.
But *nix has yet other ways to connect to the system
# Local serial lines: #s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100 #s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100 # Dialup lines: #d1:12345:respawn:/sbin/agetty -mt60 38400,19200,9600,2400,1200 ttyS0 vt100 #d2:12345:respawn:/sbin/agetty -mt60 38400,19200,9600,2400,1200 ttyS1 vt100
The above 2 blocks start agetty's for serial lines. Those are used for serail terminals or dialin connections via modems.
As you can see they are marked out by default. But this is the code you will have to deal with if lay you hands on one those good old vtxxx terminals or want to dial in to your box.
And at the verry end, there is X to give us a graphical runlevel
# Runlevel 4 used to be for an X window only system, until we discovered # that it throws init into a loop that keeps your load avg at least 1 all # the time. Thus, there is now one getty opened on tty6. Hopefully no one # will notice. ;^) # It might not be bad to have one text console anyway, in case something # happens to X. x1:4:wait:/etc/rc.d/rc.4
The comment first of all gives an explanation for the one getty left over on tty6 running in runlevel 6
It is a "wait" action which executes /etc/rc.d/rc.4. This script will look in sequence for kdm (the kde login manager), gdm (the gnome login manager) and last xdm (a default login manager). It will execute the first it finds. These login managers can be compared to agetty in that they will wait for a user to login an start themselves again when the user logs out.
bilbo@bilbo:~$ man kdm No manual entry for kdm bilbo@bilbo:~$
So far for the kdm manpage, appently they did not get to it at KDE.
bilbo@bilbo:~$ man gdm No manual entry for gdm bilbo@bilbo:~$
And so far for the gdm manpage, and the Gnome people do not care either.
XDM(1) XDM(1) NAME xdm - X Display Manager with support for XDMCP, host chooser SYNOPSIS xdm [ -config configuration_file ] [ -nodaemon ] [ -debug debug_level ] [ -error error_log_file ] [ -resources resource_file ] [ -server server_entry ] [ -session ses- sion_program ] DESCRIPTION Xdm manages a collection of X displays, which may be on the local host or remote servers. The design of xdm was guided by the needs of X terminals as well as The Open Group standard XDMCP, the X Display Manager Control Proto- col. Xdm provides services similar to those provided by init, getty and login on character terminals: prompting for login name and password, authenticating the user, and running a ``session.''
And, finally we have got a hit, here is an abstract from the XDM manpage. Since I am allways in runlevel 3 I can't really tell you a lot about it.
We have seen that "init" - as the mother of all processes - got control over the machine from the kernel. "Init" will than process the file "/etc/inittab". With the input from "inittab" "init" will in sequence:
Set the default runlevel.
Run the sytem initialisation script /etc/rc.d/rc.S, and wait for its completion.
Run the script for the decided runlevel, and wait for its completion.
/etc/rc.d/rc.K for the single user runlevel 1
/etc/rc.d/rc.M for the multi user runlevels 2,3,4 and 5
/etc/rc.d/rc.0 for runlevel 0 (system halt)
/etc/rc.d/rc.6 for runlevel 6 (system reboot)
Determine which action should be taken in special circumstances like; ctrl-alt-del and power failure.
Start agetty's for the consoles in runlevels 1, 2, 3 and 5 so users can logon locally. (And one for runlevel 4 on console 6, but that has a special reason)
Start agetty's for serial connection, not the default behaviour though..
Start a graphical logon manager for runlevel 4.