Controlling which services to auto-run under each runlevel


A typical linux computer has installed on it some set of "services." These are programs that can potentially be launched automatically when the machine is turned on, as part of its boot process. A runlevel is a choice, from among these installed services, of some particular subset actually to be launched.

The set of installed services is represented in /etc/rc.d/init.d, which houses a script (i.e., batch file) for each of them. There's a one-to-one correspondence between the services and the scripts-- each service has its script and each script has a service. The script for a given service contains a conditional branch (that is, an if/else statement) to either run the binary for that service if it isn't running ("start" it), or shut it down if it is ("kill" it). The scripts for almost all services follow this same structural pattern. The purpose of doing things this way is to centralize the startup scripts in one place. Note that the locations of the actual binaries for the service programs can be scattered around different parts of the hierarchical filesystem tree. However, scripts to call them can all be found concentrated in /etc/rc.d/init.d. Here are the scripts, from a Fedora 10 system:

A runlevel expresses a subset of these. It does so in a subdirectory. Each runlevel has a subdirectory of its own for the purpose. For example, runlevel 2 uses /etc/rc.d/rc2.d, while runlevel 3 uses /etc/rc.d/rc3.d. These subdirectories are full of symbolic links ("shortcuts") pointing to the startup scripts shown above. Whether, for a given runlevel, the script for a particular service will be used to start it or kill it can be discerned by whether the name of that service's symbolic link begins with "S" or "K."

Consider bluetooth as an example of a service. Below is the subdirectory for runlevel 2 that expresses how it treats each service. As for bluetooth, on entry into runlevel 2 bluetooth will be killed because runlevel 2's symbolic link ("K83bluetooth") to bluetooth's startup script (/etc/rc.d/init.d/bluetooth) begins with the letter K.

Runlevel 3 by contrast does the opposite. Below is the subdirectory that determines how that runlevel treats each service.  And for  you can see that on entry into runlevel 3 bluetooth will be started because runlevel 3's symbolic link ("S50bluetooth") to bluetooth's startup script (/etc/rc.d/init.d/bluetooth) begins with the letter S.

Note that this only governs startup. The services, and their triggering scripts, are available for running, starting, stopping on a manual basis throughout a session at any time just like any other program.


The in-class exercise:

Manipulate one of the per-runlevel symbolic links that select which services to run and which to kill when entering a runlevel.

Go to the directory that defines what services to run for runlevel 5. There, find out about bluetooth-- examine whether it is to be killed or started when entering runlevel 5. There are at least 2 ways to examine it. Most directly, check whether the symbolic link to its startup script (which is /etc/rc.d/init.d/bluetooth) begins with letter K or S. Alternatively, there's a useful utility for doing this called chkconfig.

Once you know how bluetooth is set, please set it the opposite way. If it's set to be started, set it to be killed instead; if it's set to be killed, set it to be started instead. Again, you can do this directly by deleting the existing symbolic link and creating a new one. Or you can use chkconfig.

After you've reversed it, examine it as you did earlier to verify your change was effective and as you intended. Then finally leave it, or set it, so that it remains off (K as opposed to S) in runlevel 5; and do the same in runlevel 3, so that bluetooth won't run on boot into either runlevel.

Here might be the commands you actually use to do the above, assuming that the symbolic link for bluetooth for runlevel 5 on your system is K08bluetooth (which is probably isn't; adapt for your reality).

# go to the directory for runlevel 5
cd /etc/rc.d/rc5.d

ls | grep bluetooth # direct examination of the symbolic link
chkconfig --list  bluetooth # indirect, by a utility for the purpose

# change it so bluetooth's to be started instead of killed 
rm K08bluetooth
ln -s ../init.d/bluetooth S08bluetooth

ls | grep bluetooth
chkconfig --list  bluetooth

# change it back to its original state
rm S08bluetooth
ln -s ../init.d/bluetooth K08bluetooth

(or instead of removing and recreating, just rename: mv S08bluetooth K08bluetooth)
(or instead of that: chkconfig --level 5 bluetooth off)

After you've finished setting bluetooth not to run on startup in runlevels 3 and 5 as instructed above, make sure it's currently running in your current session:

/etc/rc.d/init.d/bluetooth  status
/etc/rc.d/init.d/bluetooth  start
/etc/rc.d/init.d/bluetooth  status

Understand the difference between the two things you did:
 - making sure it's set to not run at startup, and
 - making sure it is running