
Introduction to runlevels
The concept of runlevels goes back to the SysV days of, runlevel for a purpose. Different tasks require various daemons to be running upon system boot. This is particularly useful in server environments, where we try to minimize as much overhead as possible in our servers. We are usually going dedicate a role to a server. In doing so, we cut down on the amount of applications that are required to be installed on a given server. For instance, a web server would usually have an application that serves up content to users and a database used for lookup(s).
Another typical use case is a print server. This is usually only used for managing print jobs. That being said, from the perspective of runlevels, we would usually scale down on the amount of services that are running inside a given server. For those coming from a Windows background, think about Safe Mode. Usually, we would boot in to Safe Mode to minimize the programs and drivers that are loaded. Runlevels take that idea further, whereby we can tell a Linux distribution what we would like to start/stop in a given runlevel. The cool part is that we have a number of runlevels that we can use in a Linux distribution. You will find runlevels in Linux distributions that use SysV init.
Take a look the following table:
Runlevel 0 1 2 3 4 5 6
Daemon off on on on on on off
Based on the preceding table, whenever a daemon is off, it means that the daemon is not going to run in that runlevel. Similarly, whenever a daemon is on, it is configured to run in the particular runlevel(s).
Runlevels usually have various start/stop scripts that are run whenever a runlevel has been selected in a Linux distribution that supports init. We can take a look at a CentOS 6.5 system to see which runlevel is in use. We will look at the /etc/inittab configuration file:
[philip@localhost Desktop]$ cat /etc/inittab
# inittab is only used by upstart for the default runlevel.
#
# ADDING OTHER CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
#
# System initialization is started by /etc/init/rcS.conf
#
# Individual runlevels are started by /etc/init/rc.conf
#
# Ctrl-Alt-Delete is handled by /etc/init/control-alt-delete.conf
#
# Terminal gettys are handled by /etc/init/tty.conf and /etc/init/serial.conf,
# with configuration in /etc/sysconfig/init.
#
# For information on how to write upstart event handlers, or how
# upstart works, see init(5), init(8), and initctl(8).
#
# Default runlevel. The runlevels used are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
id:5:initdefault:
[philip@localhost Desktop]$
From the preceding output, there are seven runlevels supported on the CentOS distribution. In particular, runlevel 5 is the runlevel that presents a graphical user interface to the user.
The other popular runlevels are 0 for halting or shutting down the system, 1 for single user mode (often used for recovery) and 6 for rebooting the system. The line that says id:5:initdefault: is the line that tells CentOS which runlevel to use upon system boot.
Now let's take a look at /etc/inittab on an Ubuntu 6.06 distribution that supports init:
From the preceding output, we can focus on the line that says id:2:initdefault:. The 2 tells the Linux kernel to use runlevel 2 upon system boot. Ubuntu 6.06 is using runlevel 2, by default. In fact, in Ubuntu, runlevels 2-5 are considered to be multi-users; there is no distinction between runlevels 2-5.
In CentOS 6.5, we can check which daemons are running in the various runlevels by using the chkconfig command; this will give a nice summary of the various services:
[philip@localhost Desktop]$ chkconfig
NetworkManager 0:off 1:off 2:on 3:on 4:on 5:on 6:off
abrt-ccpp 0:off 1:off 2:off 3:on 4:off 5:on 6:off
abrtd 0:off 1:off 2:off 3:on 4:off 5:on 6:off
acpid 0:off 1:off 2:on 3:on 4:on 5:on 6:off
atd 0:off 1:off 2:off 3:on 4:on 5:on 6:off
auditd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
blk-availability 0:off 1:on 2:on 3:on 4:on 5:on 6:off
bluetooth 0:off 1:off 2:off 3:on 4:on 5:on 6:off
cpuspeed 0:off 1:on 2:on 3:on 4:on 5:on 6:off
crond 0:off 1:off 2:on 3:on 4:on 5:on 6:off
cups 0:off 1:off 2:on 3:on 4:on 5:on 6:off
dnsmasq 0:off 1:off 2:off 3:off 4:off 5:off 6:off
firstboot 0:off 1:off 2:off 3:on 4:off 5:on 6:off
haldaemon 0:off 1:off 2:off 3:on 4:on 5:on 6:off
htcacheclean 0:off 1:off 2:off 3:off 4:off 5:off 6:off
httpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
ip6tables 0:off 1:off 2:on 3:on 4:on 5:on 6:off
iptables 0:off 1:off 2:on 3:on 4:on 5:on 6:off
irqbalance 0:off 1:off 2:off 3:on 4:on 5:on 6:off
kdump 0:off 1:off 2:off 3:on 4:on 5:on 6:off
lvm2-monitor 0:off 1:on 2:on 3:on 4:on 5:on 6:off
mdmonitor 0:off 1:off 2:on 3:on 4:on 5:on 6:off
messagebus 0:off 1:off 2:on 3:on 4:on 5:on 6:off
netconsole 0:off 1:off 2:off 3:off 4:off 5:off 6:off
netfs 0:off 1:off 2:off 3:on 4:on 5:on 6:off
network 0:off 1:off 2:on 3:on 4:on 5:on 6:off
ntpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
ntpdate 0:off 1:off 2:off 3:off 4:off 5:off 6:off
portreserve 0:off 1:off 2:on 3:on 4:on 5:on 6:off
postfix 0:off 1:off 2:on 3:on 4:on 5:on 6:off
psacct 0:off 1:off 2:off 3:off 4:off 5:off 6:off
quota_nld 0:off 1:off 2:off 3:off 4:off 5:off 6:off
rdisc 0:off 1:off 2:off 3:off 4:off 5:off 6:off
restorecond 0:off 1:off 2:off 3:off 4:off 5:off 6:off
rngd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
rsyslog 0:off 1:off 2:on 3:on 4:on 5:on 6:off
saslauthd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
smartd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
snmpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
snmptrapd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
spice-vdagentd 0:off 1:off 2:off 3:off 4:off 5:on 6:off
sshd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
sysstat 0:off 1:on 2:on 3:on 4:on 5:on 6:off
udev-post 0:off 1:on 2:on 3:on 4:on 5:on 6:off
vmware-tools 0:off 1:off 2:on 3:on 4:on 5:on 6:off
vmware-tools-thinprint 0:off 1:off 2:on 3:on 4:on 5:on 6:off
wdaemon 0:off 1:off 2:off 3:off 4:off 5:off 6:off
winbind 0:off 1:off 2:off 3:off 4:off 5:off 6:off
wpa_supplicant 0:off 1:off 2:off 3:off 4:off 5:off 6:off
[philip@localhost Desktop]$
From the preceding output, we can see a variety of services. Some are running in multiple runlevels, while some are turned off entirely. Take, for example, the network service; it is set to 0:off 1:off 2:on 3:on 4:on 5:on 6:off. This tells the system to start the network service in runlevels 2-5, leaving the network service off on runlevels 0-1 and 6. Most of the services are set to run only in runlevels 2-5.
We can look inside the /etc/rc.d/ to see the various scripts that are set up to either start/stop:
[philip@localhost Desktop]$ ls -l /etc/rc.d
total 60
drwxr-xr-x. 2 root root 4096 Jun 20 01:49 init.d
-rwxr-xr-x. 1 root root 2617 Nov 22 2013 rc
drwxr-xr-x. 2 root root 4096 Jun 20 01:49 rc0.d
drwxr-xr-x. 2 root root 4096 Jun 20 01:49 rc1.d
drwxr-xr-x. 2 root root 4096 Jun 20 01:49 rc2.d
drwxr-xr-x. 2 root root 4096 Jun 20 01:49 rc3.d
drwxr-xr-x. 2 root root 4096 Jun 20 01:49 rc4.d
drwxr-xr-x. 2 root root 4096 Jun 20 01:49 rc5.d
drwxr-xr-x. 2 root root 4096 Jun 20 01:49 rc6.d
-rwxr-xr-x. 1 root root 220 Jun 20 01:48 rc.local
-rwxr-xr-x. 1 root root 19688 Nov 22 2013 rc.sysinit
[philip@localhost Desktop]$
Based on the preceding output, there are various directories for each of the respective runlevels, 0-6. Additionally, we can go even further down the filesystem hierarchy and expose the child directories. Let's pick /etc/rc.d/rc5.d and expose its content:
[philip@localhost Desktop]$ ls -l /etc/rc.d/rc5.d/
total 0
lrwxrwxrwx. 1 root root 16 Jun 20 01:44 K01smartd -> ../init.d/smartd
lrwxrwxrwx. 1 root root 17 Jun 20 01:44 K05wdaemon -> ../init.d/wdaemon
lrwxrwxrwx. 1 root root 16 Jun 20 01:44 K10psacct -> ../init.d/psacct
lrwxrwxrwx. 1 root root 19 Jun 20 01:41 K10saslauthd -> ../init.d/saslauthd
lrwxrwxrwx. 1 root root 22 Jun 20 01:41 K15htcacheclean -> ../init.d/htcacheclean
lrwxrwxrwx. 1 root root 15 Jun 20 01:41 K15httpd -> ../init.d/httpd
lrwxrwxrwx. 1 root root 17 Jun 20 01:41 K50dnsmasq -> ../init.d/dnsmasq
lrwxrwxrwx. 1 root root 20 Jun 20 01:40 K50netconsole -> ../init.d/netconsole
lrwxrwxrwx. 1 root root 15 Jun 20 01:41 K50snmpd -> ../init.d/snmpd
lrwxrwxrwx. 1 root root 19 Jun 20 01:41 K50snmptrapd -> ../init.d/snmptrapd
lrwxrwxrwx. 1 root root 17 Jun 20 01:47 K73winbind -> ../init.d/winbind
lrwxrwxrwx. 1 root root 14 Jun 20 01:41 K74ntpd -> ../init.d/ntpd
lrwxrwxrwx. 1 root root 17 Jun 20 01:41 K75ntpdate -> ../init.d/ntpdate
lrwxrwxrwx. 1 root root 19 Jun 20 01:44 K75quota_nld -> ../init.d/quota_nld
lrwxrwxrwx. 1 root root 24 Jun 20 01:44 K84wpa_supplicant -> ../init.d/wpa_supplicant
lrwxrwxrwx. 1 root root 21 Jun 20 01:40 K87restorecond -> ../init.d/restorecond
lrwxrwxrwx. 1 root root 15 Jun 20 01:40 K89rdisc -> ../init.d/rdisc
lrwxrwxrwx. 1 root root 14 Jun 20 01:44 K99rngd -> ../init.d/rngd
lrwxrwxrwx. 1 root root 17 Jun 20 01:43 S01sysstat -> ../init.d/sysstat
lrwxrwxrwx. 1 root root 22 Jun 20 01:43 S02lvm2-monitor -> ../init.d/lvm2-monitor
lrwxrwxrwx. 1 root root 22 Jun 20 01:49 S03vmware-tools -> ../init.d/vmware-tools
lrwxrwxrwx. 1 root root 19 Jun 20 01:41 S08ip6tables -> ../init.d/ip6tables
lrwxrwxrwx. 1 root root 18 Jun 20 01:40 S08iptables -> ../init.d/iptables
lrwxrwxrwx. 1 root root 17 Jun 20 01:40 S10network -> ../init.d/network
lrwxrwxrwx. 1 root root 16 Jun 20 01:44 S11auditd -> ../init.d/auditd
lrwxrwxrwx. 1 root root 21 Jun 20 01:38 S11portreserve -> ../init.d/portreserve
lrwxrwxrwx. 1 root root 17 Jun 20 01:41 S12rsyslog -> ../init.d/rsyslog
lrwxrwxrwx. 1 root root 18 Jun 20 01:44 S13cpuspeed -> ../init.d/cpuspeed
From the preceding output, there are a number of daemons for runlevel 5. The way by which we identify the daemon would be by the naming convention in use. The files that start with K are used to kill/stop the process and the files that start with S are used to start a process. Also, most of the scripts are symbolic links pointing to the /etc/rc.d/init.d/ directory.
Similarly, we can expose the various start/stop scripts in a later CentOS distribution. For instance, let's choose CentOS 6.5 and dissect one of its directories. On the CentOS 6.5 system, here is one of the stop scripts being displayed:
[philip@localhost Desktop]$ cat /etc/rc.d/rc5.d/S13irqbalance
#! /bin/sh
### BEGIN INIT INFO
# Provides: irqbalance
# Default-Start: 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop irqbalance daemon
# Description: The irqbalance daemon will distribute interrupts across
# the cpus on a multiprocessor system with the purpose of
# spreading the load
### END INIT INFO
# chkconfig: 2345 13 87
# This is an interactive program, we need the current locale
# Source function library.
. /etc/init.d/functions
As we can see, the scripts are a lot more involved. Moving down, we can see the following code:
# Check that we're a privileged user
[ `id -u` = 0 ] || exit 0
prog="irqbalance"
[ -f /usr/sbin/irqbalance ] || exit 0
# fetch configuration if it exists
# ONESHOT=yes says to wait for a minute, then look at the interrupt
# load and balance it once; after balancing exit and do not change
# it again.
# The default is to keep rebalancing once every 10 seconds.
ONESHOT=
[ -f /etc/sysconfig/irqbalance ] && . /etc/sysconfig/irqbalance
case "$IRQBALANCE_ONESHOT" in
y*|Y*|on) ONESHOT=--oneshot ;;
*) ONESHOT= ;;
esac
RETVAL=0
start() {
if [ -n "$ONESHOT" -a -f /var/run/irqbalance.pid ]; then
exit 0
fi
echo -n $"Starting $prog: "
if [ -n "$IRQBALANCE_BANNED_CPUS" ];
then
export IRQBALANCE_BANNED_CPUS=$IRQBALANCE_BANNED_CPUS
fi
daemon irqbalance --pid=/var/run/irqbalance.pid $IRQBALANCE_ARGS $ONESHOT
RETVAL=$?
echo
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
killproc irqbalance
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/irqbalance
return $RETVAL
}
restart() {
stop
start
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status irqbalance
;;
restart|reload|force-reload)
restart
;;
condrestart)
[ -f /var/lock/subsys/irqbalance ] && restart || :
;;
*)
echo $"Usage: $0 {start|stop|status|restart|reload|condrestart|force-reload}"
exit 1
;;
esac
exit $?
[philip@localhost Desktop]$
Finally, from the preceding output, we can clearly see that the scripts are programmatic in nature.