Exploring Linux Runlevels and Their Purposes (SysVinit)

Linux relies on runlevels to determine what features are available upon system boot and what aren’t. Runlevels are numbered, from 0 to 9, and each one is assigned a set of services that should be active when entering a particular runlevel.

0 reserved, a transitional runlevel, meaning that it’s used to shift the system from one state to another. On modern hardware, the system should completely power down.
1 reserved, a single-user with local filesystems mounted (read-write). Typically used for low-level system maintenance (resizing partitions etc).
2 – on Debian family operating systems, a full multi-user mode with X running. Usually left undefined on other distributions.
3 – on Red Hat, Fedora, Mandriva, and most other distributions, a full multi-user mode with a console login screen.
4 – usually undefined by default.
5 – on Red Hat, Fedora, Mandriva, and most other distributions, the same behaviour as runlevel 3 with the addition of  X running.
6reserved, an another transitional runlevel, used to reboot the system. Computer is completely shut down, and then reboots automatically.
s, or S – reserved, are the same, used for a single-user mode with only root filesystem mounted (as read-only).
7-9 – are valid runlevel, though not really documented. This is because “traditional” Unix variants don’t use them.
a, b, c – these runlevels can be called on a running system to tell init to process only those /etc/inittab file entries having runlevel a, b or c.

If in doubt about the current runlevel the system is running in, simply type runlevel:

# runlevel 
2 3

Output shows the previous (2) and the current (3) system runlevels.

Changing Runlevels

The following section covers System-V-like init utilities only (Systemd, Upstart? Perhaps at some point in the future).

Editing the /etc/inittab File

In the Linux implementation of SysV startup scripts, the kernel launches a process called init, which reads its configuration file and launches certain scripts. These scripts may and normally do vary from one runlevel to another.

SystVinit determines the default runlevel (if there is any set of course) by examining the /etc/inittab file for an :initdefault: entry.

Working with Debian system, we would normally expect to get the following:

$ grep default /etc/inittab
# The default runlevel.
id:2:initdefault:

On Fedora, the line will likely look a bit different:

$ grep default /etc/inittab
# The default runlevel.
id:5:initdefault:

These default runlevels can be changed by editing the /etc/inittab file. Although the file modification is pretty straightforward, changing the contents of it is best left to experts. Moreover, it’s a rare occasion we actually need to change the default runlevel.

Another thing to mention, changes made to the /etc/inittab file won’t take effect until the system is restarted or telinit q command is run to re-examine the file.

Using the init and telinit Commands

We may more often need to change runlevels on a go – when system is already running.

As we now know, init is the very first process run by the Linux kernel and is the parent of all processes. Its primary role is to create processes from the /etc/inittab script. Init command can be used to change to a new runlevel when system is running. For example, to switch to a single user mode on a running system, we would type:

# init 1

Or to reboot the system:

# init 6

A variant of init is telinit. However, /sbin/telinit is usually linked to /sbin/init:

# ls -l /sbin/telinit 
lrwxrwxrwx 1 root root 4 Jul 14 2013 /sbin/telinit -> init

Using the shutdown Command

Even thought we can reboot or shut down the system with init, it is recommended to use a shutdown program instead. Changing runlevels with init causes an immediate change to the new runlevel, what may be inappropriate for systems having many users connected to it.

The shutdown program sends a broadcast message to all users who are logged into the system, thus giving them some time to save changes when the time parameter is used.

# shutdown -r +5 "Please save your changes"
Broadcast message from root@debian (pts/0) (Mon Nov 11 20:46:15 2013):
Please save your changes 
The system is going DOWN for reboot in 5 minutes!

If we scheduled a shutdown but then changed our mind, we can use the -c option to cancel it:

# shutdown -c "system restart cancelled"

Innittab Entry Formats (for Future References)

Going back to /etc/inittab, the file entries follow a simple format. Each line consists of four colon-delimited fields:

id:runlevels:action:process

The id is a unique sequence of 1-4 characters which identifies an entry in inittab.

The runlevels field consists of a list of runlevels for which this entry applies. For example, 23 means the entry is applicable to runlevels 2 and 3.

Action tells init which action should be taken and how to treat the process. For example, respawn tells init to restart the process whenever it terminates.

The process field is the process to be executed, including any options and arguments that are required.
When entering a runlevel, rc passes the start parameter to all the scripts with names that begin with a capital S and the stop parameter to all the scripts with names that begin with a capital K.

Managing Runlevel Services

To change the system runlevel is relatively easy, but that doesn’t really help us much if we don’t know how to add or remove services which should be started on one or another runlevel.

Using chkconfig

Chkconfig is one of the tools used to enable/disable system services. To install on Debian:

# apt-get install chkconfig

We can list the runlevel configuration of all known services by using the following command:

# chkconfig -l

Output will show the status of the services in all seven runlevels. To modify the runlevels in which the zabbix-agent service runs, we can use a command like this:

# chkconfig --level 3 zabbix-agent on

To remove the zabbix-agent service from all runlevels:

# chkconfig --del zabbix-agent

Using update-rc.d

The update-rc.d command is used on Debian systems to install and remove System-V style init script links. General usage patter is as below:

# update-rc.d <service-name> <option>

Some options that are available:

  1. defaults: make links to start the service in runlevels 2-5 and to stop the service in runlevels 016.
  2. enable: rename stop links to start links in all start runlevels if no start runlevel is specified.
  3. disable: rename start links to stop links in all start runlevels if no start runlevel is specified.
  4. remove: delete any links in the /etc/rc{runlevel}.d/ directories to the script in /etc/init.d/. Avoid using this option unless you know what you’re doing.

The command below will enable the zabbix-agent service on runlevels 2-5:

# update-rc.d zabbix-agent enable

Other Tools

On a Debian system, runlevels can also be configured by using rcconf – Debian runlevel configuration tool. Rcconf displays a menu of all the services which can be started at boot. The enabled ones are marked with asterix (“*”), and simply toggling individual services we can configure them to be on and off.

Another tool is ntsysv (although I used it very little myself), which was created by Red Hat and is used mainly on Red Hat and related distributions.

Last, but not least, my favourite one – sysv-rc-conf. It gives an easy to use interface for managing /etc/rc{runlevel}.d/ symlinks. The interface simply allows to turn services on or off as well as allows for more fine tuned management of the symlinks.

As the man page implies, sysv-rc-conf is a replacement for programs like ntsysv or rcconf mentioned earlier.