sections in this module City College of San Francisco - CS260A
Unix/Linux System Administration

Module: StartupShutdown I
module list

Subsystems

init could manage the fine points of system initialization. However, this would be incredibly difficult. Instead, init is used to trigger scripts, whose task is to manage the finer details. 

To allow for easy customization, system initialization for legacy System5 initialization is divided into discrete subtasks called subsystems. Then a fairly simple scheme is used to orchestrate the initialization of these subsystems and to handle interdependencies. The scripts, which are started by the rc scripts (see below) run by init, then manage the initialization of these subsystems.

Before we look at the intricacies of this scheme, let's consider a simple example. Suppose we had a simple system that had three tasks that required initialization, A, B, and C. We create a custom script for each (we will call these scripts the same as the tasks, A, B, and C) and release this script with the task's program. Since we will call these 'tasks' subsystems, we will call the script that initializes each subsystem a subsystem initialization script or just subsystem script. Thus, to initialize subsystem A we just run script A.

Now suppose we want subsystem A and B to be initialized. A simple solution would be to create a master script that knows about a directory, and, when run, executes each command (script) in that directory. We call this script the 'run commands' script, or rc script, and place it under the control of init to be run when the system starts. Then, if we want subsystems A and B to be initialized when the system starts, we simply place their scripts in the directory. At system start, init runs the rc script, and it executes each script in its special directory.

This technique seems a bit complex but it has some benefits. First, we can modify whether a subsystem is to run on the system by simply placing it in (or removing it from) the subsystem directory. Second, the intricacies of controlling individual subsystems is hidden in its subsystem script, which distributed with the subsystem itself. Not bad. Before this scheme is usable, however, we need a few more features.

Runlevels are used to manage overall system state. Thus, some subsystems should be active at certain runlevels and not at others. (Usually, if a subsystem is running at a lower runlevel, it will also be running at higher runlevels.) This can be accomplished by replacing the single directory that our rc script uses with one directory per runlevel. Then, on entry to runlevel 1, the scripts in the runlevel 1 directory (rc1.d) are executed. On entry to runlevel 2, the scripts in rc2.d are executed, etc.

It is easy to follow this scheme when progressing from a lower runlevel to a higher one, as you would simply start more subsystems. But what needs to happen when we decrease the runlevel? In this case, we need to stop certain subsystems. Thus, the subsystem script must know how to stop a subsystem as well as start it. This is accomplished by defining a few arguments that every subsystem script must understand:

These are the only arguments needed by the rc scripts. For the use of root, a few other arguments are supported as well

For example, the command

./A start

where ./A is the subsystem script for subsystem A, would start subsystem A.

Now we need a way to indicate which argument (start or stop) to use when each subsystem script is run. Suppose we had six subsystems, A-F, and the first three needed to be started at runlevel 2, but the last three needed to be stopped. Thus, we need to somehow indicate to the rc script that when it runs A, it should use the argument start, and when it runs D it should use the argument stop. This is done by indicating the argument to use by a prefix on the script name. The prefix that is used is S for start and K (kill) for stop.

A simplified listing of the directory for runlevel 3 might look like that below (note: this is simulated):

Kavahi-dnsconfd
Kconman
Kcapi
Knfs
Sanacron
Sbluetooth
Scpuspeed

In this directory, then, there are four scripts to run with the stop directive, and three to run with the start directive. The rc script would effectively execute the following commands in this directory 

./Kavahi-dnsconfd stop
./Kconman stop
./Kcapi stop
./Knfs stop
./Sanacron start
./Sbluetooth start
./Scpuspeed start

Since there are very few runlevels, there must be a way of imposing order on the starting of subsystems. For example, two subsystems are named network and httpd. It would probably be a good idea to initialize the network before starting the web server.

The order of subsystem start (and stop) is imposed by another naming trick. A two-digit integer is encoded in the name of the subsystem just after the S or K. Lower-numbered subsystems are started (or stopped) first. This numbering scheme is intentionally sparse; new subsystems are assigned numbers by their author that are higher than the numbers of any subsystems that must be started before them and lower than the numbers of any subsystems that must be started after them. (In the majority of cases there are very few dependencies. It doesnt matter, for example, whether the ssh daemon is started before or after the web server, but both must be started after the network!) It is also perfectly legal for two subsystems to share the same number. This just means that they are not dependent on each other.

After understanding this, let's look at the real names of the above subsystems in the rc3.d directory:

K02avahi-dnsconfd
K05conman
K20nfs
K91capi
S06cpuspeed
S25bluetooth
S95anacron

Note that the number imposes the order for us so that a simple listing of the K names gives an ordered list of what to stop! Very cute! All the rc script must do, then, is to

The attentive reader might notice here that configuring one subsystem to be started at several runlevels requires the replication (and appropriate renaming) of the subsystem script for each runlevel. This replication, of course, creates maintenance issues. Instead, a single version of each subsystem script exists and symbolic links are created to it, prefixed with K or S as appropriate and with the ordering number, and placed in each subsystem directory. To see this, let's look at the long listing for our partial list of subsystems from rc3.d:

$ ls -l *{avahi-dns*,conman,nfs,capi,cpuspeed,anacron,blue*}
lrwxrwxrwx 1 root root 24 Jul  1  2008 K02avahi-dnsconfd -> ../init.d/avahi-dnsconfd
lrwxrwxrwx 1 root root 16 Jun  1  2008 K05conman -> ../init.d/conman
lrwxrwxrwx 1 root root 13 Jun  1  2008 K20nfs -> ../init.d/nfs
lrwxrwxrwx 1 root root 14 Jun  1  2008 K91capi -> ../init.d/capi
lrwxrwxrwx 1 root root 18 Jun  1  2008 S06cpuspeed -> ../init.d/cpuspeed
lrwxrwxrwx 1 root root 19 Jun  1  2008 S25bluetooth -> ../init.d/bluetooth
lrwxrwxrwx 1 root root 17 Jun  1  2008 S95anacron -> ../init.d/anacron

And at the root directory for the subsystem scripts, /etc/rc.d:

$ ls -F /etc/rc.d
init.d/  rc0.d/  rc2.d/  rc4.d/  rc6.d/     rc.sysinit*
rc*      rc1.d/  rc3.d/  rc5.d/  rc.local*
$

Last, let's look at the complete configuration for one subsystem, anacron:

$ ls rc?.d/*anacron
rc0.d/K05anacron  rc2.d/S95anacron  rc4.d/S95anacron  rc6.d/K05anacron
rc1.d/K05anacron  rc3.d/S95anacron  rc5.d/S95anacron

You can see a few things from this output

For one last check, let's look at the long output of anacron's symlinks:

$ ls -l rc?.d/*anacron
lrwxrwxrwx 1 root root 17 Jun  1  2008 rc0.d/K05anacron -> ../init.d/anacron
lrwxrwxrwx 1 root root 17 Jun  1  2008 rc1.d/K05anacron -> ../init.d/anacron
lrwxrwxrwx 1 root root 17 Jun  1  2008 rc2.d/S95anacron -> ../init.d/anacron
lrwxrwxrwx 1 root root 17 Jun  1  2008 rc3.d/S95anacron -> ../init.d/anacron
lrwxrwxrwx 1 root root 17 Jun  1  2008 rc4.d/S95anacron -> ../init.d/anacron
lrwxrwxrwx 1 root root 17 Jun  1  2008 rc5.d/S95anacron -> ../init.d/anacron
lrwxrwxrwx 1 root root 17 Jun  1  2008 rc6.d/K05anacron -> ../init.d/anacron
$

It may cause problems to start a subsystem that is already running. Thus, when a subsystem is started it must ensure that it is not already running. Most subsystems keep track of this by a lock file, and, possibly, an accompanying pid file. The existence of the lock file indicates that the subsystem is up. Lock files are kept in /var/lock/subsys. Some subsystems that control daemons also create a pid file to keep track of the process id of the daemon (or daemons) associated with the subsystem. These pid files are kept in /var/run. All of the /var/run and /var/lock/subsys files are deleted when the system is started.

Ok, this is fine, but what is a subsystem?

A subsystem is simply a definable task that must be initialized. Most subsystems involve the management of one or more daemon programs. A daemon is a program (usually) started by root at system boot that runs in the background to do some system-administration function. Daemons are not attached to a terminal. 

Most system daemons' names end in the letter d (for daemon). Thus, you can do a quick check for daemons on your system using the command ps -e | grep 'd$'  On the linux system that I am currently on we find 56 running. 

$ ps -e | grep 'd$'| wc -l
56

Examples of system daemons currently running on this system are  hald, smartd, ypbind, sshd and nfsd. (Daemons are used to manage a network connection as well. Each time you connect to a remote linux system, it spawns a new instance of sshd to manage your connection. (Yes, you are talking to a daemon anytime you ssh to a linux system)) In addition to system daemons, some applications use user daemons. One common example of this is the desktop manager.

Some subsystems do not have a daemon associated with them. These subsystems may simply have some commands executed from their subsystem script when the subsystem script is run. In these cases, nothing is required the stop the subsystem, and K links may not exist.

Most subsystem scripts output a message about their status both to standard output and (until recently) to a system log file. For example,

[root@milhouse ~]# /etc/rc.d/init.d/atd stop
Stopping atd:                                              [  OK  ]
[root@milhouse ~]#

Starting and stopping a subsystem by hand

As root, you can start and stop a subsystem by invoking the subsystem scripts directly. Even an unprivileged user can usually inquire about the status of a subsystem by executing the subsystem script with the argument status. Rather than using a path to the subsystem script, whose location may vary between systems, it is often easier to use the service command, which is in /sbin:

As root

service crond stop

is equivalent to 

/etc/rc.d/init.d/crond stop

An interesting experiment is to inquire about the status of all subsystems as a normal user using 

/sbin/service --status-all

Preview question: As you may imagine, the configuration of subsystems mainly involves the creation, name and location of the symbolic links in the rcX.d directories. This configuration would be unmanageable were it not for chkconfig. Look at its man page (chkconfig(8)).

Prev This page was made entirely with free software on linux:  
the Mozilla Project
and Openoffice.org      
Next

Copyright 2012 Greg Boyd - All Rights Reserved.