3. Init

3.1. Runlevels.

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:

One of these multi user runlevels will be the normal operation state of the machine. It is up to you to define extra runlevels. For instance a single user runlevel with network support for remote maintenance.

Beside these runlevels there are 2 special runlevels:

3.2. Init, the mother of all processes.

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:

In the pstree view above you can see those autonomous processes. They are all direct children of init. Among them are agetty (4x), sendmail (2x), lpd and syslogd to name a few.

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.

3.3. /etc/inittab

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 ":"

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....

3.4. Comments to start with

# 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.

3.5. The Slackware runlevels

# 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.

3.6. The default runlevel

# 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.

3.7. System initialisation

# 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.

3.8. The runlevel scripts

# 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.

3.9. Special circumstances

# 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.

3.10. A way to logon

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?

3.11. Another way to logon.

*Nix has allways given different ways to connect to a system. We have allready seen 2 of them:

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.

3.12. And then there is X.

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.

3.13. Where did that get us.

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:

This in fact is all there is to it for init. What rests are "just scripts". But they can be fun to look over; otherwise you still would not know where your modules get loaded and the network started.