If you were to just install the Linux operating system on your hard disk, you
would not be able to do very much. What actually makes Linux so useful is all
of the extra things which are brought with it. This is essentially true for
every operating system.
What makes Linux so useful as well as powerful are all the of services,
which are generally referred to as daemons. These daemons typically run without
user intervention providing everything from printing to file services to Web
pages and beyond. Because they are not part of the operating system
proper they are normally loaded separately from the kernel.
Although many of these services could be made part of the kernel,
they are mostly separate programs. Because
they are separate programs something needs to configure and start them.
In most cases, simply installing a particular package is sufficient to
activate the appropriate daemon.
However, there are times when you need to
make changes to how these demons behave, which often means changing the way the
program starts up. In order to be able to do that, you obviously need to know
just how and where these daemons are started in the first place. That's exactly
what we're going to talk about here.
Once the kernel
is loaded, one of the last things it does is to start the
init process. The job of the init
process (or simply init) is to start all of
the daemons at the appropriate time. What the appropriate time is depends on a
number of different things. For example, you may be performing administrative
tasks and you do not want certain daemons to be running. Although you can
stop those demons you do not need, the system provides a mechanism to do this
To understand this mechanism we need to talk about something called "run states"
or "run levels". Most users (and many administrators, for that
matter) are familiar with only one run level. This is the run level in which
the system is performing all of its normal functions. Users can login,
submit print jobs, access Web pages, and do everything else one would expect. This run
level is commonly referred to as multiuser mode. In contrast, maintenance or
single user mode is normally recommended for administrative tasks.
Each run level is referred to by its number.
When the system is not doing anything, that is the system is stopped, this is
run level 0. Single user mode is run-level 1.
Multiuser mode is actually multiple runs levels. Depending on which distribution or
which version of Unix you ahve, this can be run-level 2, run-level 3 and
run-level 5. Most Linux systems automatically booting into run-level 3 when the
system starts. Run level 2 is very similar to run level 3,
although a number of things do not run in level 2. In fact, on some systems
(SCO UNIX for example), run level 2 is the standard
multi-user mode. Run-level 5 is
where the GUI starts automatically.
(For more details on the run levels, take a look at the init(8)
Like many other aspects of the system, init
has its own configuration file: /etc/inittab (see the table below). This file contains
the init table (inittab), which
tells it init
what to do and when to do it. Each activity init does is
represented by a single line in the inittab, which consists of four entries,
separated by a colon. The first field is a unique identifier for that entry,
which enables init to keep track of each daemon as it runs.
The second field is the run level in which each particular entry is run.
The third entry is the action, which tells init
how to behave in regard to
this entry. For example, some entries are only processed when the system boots.
Others are automatically re-started should that particular process stop (such as terminal
logins). The last entry is what program will be started and often a number of
options for that program.
If you take look in inittab on your system you may notice something
peculiar. More than likely, you are not going to find any entries for the
system demons we have been talking about. The reason is quite simply that the
daemons are not started through the inittab, but rather through scripts which
are started from the inittab. These scripts we see as the entries labeled l0
through l6, for run levels 0 through 6 (the letter "ell", not the number one).
In the example below, the "action" is that init waits until the
program has terminated before continuing on and processing other entries for
this run level. This also means that the entry will only be processed once as
the system enters that particular one level.
The key to all of this is the program which is run for each run level. In
every case, it is the shell
script rc, which is given the appropriate run level
as an argument. This script is often called the
"run level master script" as it is responsible for loading all of the other
init scripts. Where this script lies
and what it is called will be different for different Linux distributions. Under
older versions of SuSe it in /etc/rc.d, but now it's in
/etc/init.d/. Under Caldera the script resides under
/etc/rc.d. Note that starting with version 8.0, SuSe also
has an /etc/rc.d directory, which is actually a symbolic
link to /sbin/init.d.
Not just the location of the script is different between distributions, but
so is the actual code. However, the basic functionality is generally the same.
That is, to start other scripts which finally start the daemons we have been
talking about all along.
One of the key aspects is how the system determines which daemon
to start in
which run level. As you might guess, this is accomplished through the run-level
that is passed as an argument
to the RC script. At least that's part of
it. In addition, the system needs a list of which scripts should be started in
which run level. This is accomplished not by a text
file, but rather by separating the programs or scripts into different directories,
one for each run level.
If you look in the /sbin/init.d or
/etc/rc.d directory you'll see a number
of subdirectories of the form rc#.d, where # is a particular run level. For
example, the directory rc3.d is for run level 3. Within the subdirectories are
not the actual scripts, as you might have guessed, but rather symbolic links to
the actual scripts. The primary reason for this is that a script can be started
in more than one run level. If the files were not links, but rather copies, any
change would have to be made to every copy. The reason they are symbolic links,
is that they may point to files on other file systems which is only possible by
using symbolic links.
With SuSe, the /sbin/init.d directory is also where the real scripts reside.
On Caldera, the scripts reside under /etc/rc.d/init.d.
At first glance, the filenames may be a little confusing. Although it is
fairly simple to figure out what daemon
is started by looking at the name, the
way these links are named takes a little explanation.
As you might guess, the link ending in "apache" points to the script which
starts the Apache Web server.
However, you'll see there are two files with this ending. The really odd
thing is that both of these links point to the exact same file. So, what's the
Part of the explanation lies in the first letter of each of these links. As
you see, each starts with either the letter S or the letter K. Those which begin
with the letter S are used to start the particular service and those which begin
with the letter K are used to stop or kill that same service.
That leaves us with just the numbers. These are used to define the order
in which the scripts are run. When the files are listed, they automatically
appear in numerical order. In this way, the system can ensure the scripts are
run in the correct order. For example, you do not want to start the Apache Web
server before you start the network.
Therefore, the linked used to start the
network is S05network whereas the link used to start Apache is S20apache as S05
comes before S20 no matter what comes afterwards.
Note also, the same applies when the system shuts down. K20apache is used to
shut down the Apache server and K40network is used to shut down network. As in the first case, the network
is not shutdown until after Apache has.
It is interesting to note that this system could work even if the name of
the link consisted of just S or K and the appropriate number. That is, it
would still work if the link told us nothing of the service being started. There
is actually more to it than making things simpler for us non-computers. Having
the names at the end allows the system to avoid unnecessary
the unnecessary stopping and starting of the various services.
When a lower level is entered, only those of
services are started which were not started in previous run level. When leaving
a run level, the only services that are stopped are those that
are not started in the new level.
Let's look at an example. In the directory /etc/init.d/rc3.d (for run level 3), there
are links used to both start and stop the network.
However, this means the
network will always be re-started when moving from run level 1 to run level 3.
This also means the network
will always be stopped when moving from run level 3
to run level 1. On the other hand, both links exist in rc.2 (for run level 2).
Therefore, when leaving either run level 2 or 3 and moving to the other,
the network is
not stopped as there is a start link for it in the new run level. When entering the
new run level, the network
is not started, as there was already a start link for
the previous level. However, in moving from a run level when network is running (e.g.
2,3 or 5) to run level 1, the
network is stopped because there is no link to start the network
in run level 1.
We're not done yet.
Since the links to both start and stop a service can be to the exact
same file, the script needs some way of knowing whether it should start or
stop the service.
This is done by passing an argument
to the script:
start to start the service and stop to stop the service (simple, huh?). Inside
each script, this argument
is read (typically $1) and different activities are
performed based on what the argument
Note that for many scripts, you can pass other arguments than just start and
stop. For example, one common argument
is restart. As its name implies, this is
used to stop then start the service again, in other words, restart a running service.
Many will also accept the argument
status, which is used to deliver status
information about that service.
# Default runlevel.
# System initialization.
# What to do in single-user mode
Figure - Excerpts from the /etc/inittab file
On some systems, the scripts we have talked about so far are not the only
scripts which are started when the system boots. Remember that init
inittab to find out what to do, so there are any number of things that "could"
be started through the inittab, as compared to the rc-scripts. Even so, for
people who are used to other versions of UNIX,
the inittab looks pretty barren.
One type of script that is often run from the inittab deals with system
initialization. For example, the boot
script, which is found directly in
/sbin/init.d. The entry in the inittab might look like this:
The run level this script runs in is "I", which is not a traditional run
level, but used by some distributions (i.e. SuSe) to indicate system
initialization. However, because the action is bootwait, the run-level
ignored. Bootwait means that this entry will be processed while the system boots,
will wait until the command or script has completed.
In this case, the script is /sbin/init.d/boot, which performs basic
system initialization such as starting the bdflush
(which writes dirty
buffers to the disk), checking the filesystems (with fsck), mounting
filesystems, starting the kernel
(kerneld), and many other things.
Other versions (as well as other UNIX
dialects) may have several different
entries in the inittab that combine to do the same work as the /sbin/init.d/boot
script under SuSe Linux.
The counterpart to the /sbin/init.d/boot script
These are the procedures that are carried out when the system is brought down.
In general, these are the reverse of the procedures in the boot
scripts, such as
and unmounting filesystems.
SuSe also uses the system configuration file /etc/rc.config. This file
contains a large number of variables that are used to configure the various
services. Reading this file and setting the variables is one of the first things
done by the script /sbin/init.d/rc. The counterpart to this file on Caldera is
/etc/syconfig/daemons. Instead of a single configuration file, you will find
separate files for a number of different daemons.
Creating your own init scripts
Sometimes the scripts your particular distribution provides are not
sufficient and you need to add your own. On a number of systems where I have
needed to add my own system services, I have needed to create my own init
scripts. The method that works on any system is to simply follow the conventions
used by your distribution.
SuSe has realized the need for creating your own init
scripts, so has
provided a template for you. This is the file /sbin/init.d/skeleton and as its name implies, is a "skeleton" init
script. In its default state, this is a completely runnable init
script. At the same time it is completely useless as there is no daemon
behind it. Instead, you simply uncomment the lines you need, change
the name of the daemon
or service and you are ready to run.