On Centos/RHEL 6 systems, the grub boot loader will load the kernel and initial RAM disk. Once the kernel has finished its startup procedure, it will hand over control to a startup manager. The SysVinit program is one such startup manager which had been used in Red Hat based systems up until RHEL 6. As of RHEL 7 onwards, the SysVinit system has been replaced in favor of systemd. In this article, we will explain the functioning of init along with run levels which describe the system state. The name SysVinit has derived from system 5 Unix and has been widely adopted in Linux as the replacement for the original BSD init.


What is init?

The kernel starts the init process /sbin/init with the process id 1. The init process is responsible for coordinating the start of the rest of the system services, configuring the user environment and essentially bringing the system to a functional state. Let’s take a look at the init process using the Linux top command:

[sahil@linuxnix:~] $ top -p 1 -n 1
top - 14:51:28 up 210 days, 20:55, 1 user, load average: 0.00, 0.00, 0.00
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
Cpu(s): 1.0%us, 0.3%sy, 0.0%ni, 98.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1921184k total, 1597396k used, 323788k free, 365232k buffers
Swap: 3768316k total, 88800k used, 3679516k free, 770044k cached

1 root 20 0 19356 1396 1136 S 0.0 0.1 0:04.02 init

The init process with PID 1 does govern a lot of the system management, the management process and architecture is referred to as SysVinit. The SysVinit init system follows a serial boot process meaning that all the required services are started serially one after the other. This can cause the system startup process to be relatively slow if there are a number of services that need to be started at boot. In contrast to this, with systemd we can start services in parallel. When the init command starts, it becomes the parent or grandparent of all of the processes that start up automatically on the system.


The inittab file and run levels

Once init loads, it first runs the /etc/rc.d/rc.sysinit script, which sets the environment path, starts swap, checks the file systems, and executes all other steps required for system initialization and then it will read it’s configuration file /etc/inittab. This file specifies what is required and how the system should be configured. Initially, the system starts in single user mode (run level S or run level 1). In single user mode, we configure everything that is required for an absolutely basic system. Following this, the system loads the default run level defined in the /etc/inittab file.

Runlevels are a state, or mode, defined by the services listed in the SysV /etc/rc.d/rcX.d/ directory, where X is the number of the runlevel.

The /etc/inittab file describes the available run levels in which the system can be booted into along with a brief description of the run level. Given below are the contents of the /etc/inittab file on a Centos 6 system.

[sahil@linuxnix:~] $ cat /etc/inittab
# inittab is only used by upstart for the default runlevel.
# 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)

The default run level to which the system boots to is determined by the initdefault directive. In the example file we showed, the default run level is set to 3 since we are working on a system without a graphical environment. If the system had a GUI like Gnome or KDE, then the initdefault would be set to 5 to indicate so. So, to change the default run level you may simply modify the initdefault entry in the file.

To change the run level from the current run level, execute the init command followed by the run level number you want to go to. For example, to transition the system to run level 1, type:

init 1

To check the current run level of your system, use the who command with the -r option as shown below:

[sahil@linuxnix:~] $ who -r
run-level 3 2017-06-20 17:56
[sahil@linuxnix:~] $


Understanding system startup scripts
Having identified the runlevel it proceeds to execute the corresponding startup scripts located in the /etc/rc.d sub-directory. These scripts are responsible for starting up of system services. A service is essentially a process that typically runs in the background to provide specific functionality.

For example, if the default runlevel 3 is configured then the init process will work through the list of startup scripts located in /etc/rc.d/rc3.d.  These startup scripts start either with the letter “S” or “K” followed by a number and then a word describing the service for which the script is intended for.  For example, the startup script for the rsyslog service is S12rsyslog whilst the startup script for the sshd service might be called S55sshd. The script names generally remain the same for most well-known services across different systems.

The startup scripts denoted with the S suffix is executed when the system transitions from a lower runlevel to the run level in which these scripts are located.

The kill scripts denoted with the K suffix are executed when the system transitions from the run level in which these scripts are located to a lower run level.

The number in the filename controls the order in which the script will be executed with that group (either “S” or “K”).

I would like to mention that it isn’t necessary that you will find the startup and kill scripts for a particular service in the same rcX.d subdirectory.

The files in the rc.d sub-directories are not the actual scripts themselves but rather symbolic links to the actual scripts which are used to run the services located in /etc/rc.d/init.d. If we want a service to be available at multiple run levels then we might end up creating many more links than what is actually required. Let’s use the startup script for sshd service to exemplify this.

[sahil@linuxnix:/etc/rc.d] $ sudo find /etc/rc.d -name S55sshd -exec ls -l {} \;
lrwxrwxrwx. 1 root root 14 Feb 5 2013 /etc/rc.d/rc3.d/S55sshd -> ../init.d/sshd
lrwxrwxrwx. 1 root root 14 Feb 5 2013 /etc/rc.d/rc5.d/S55sshd -> ../init.d/sshd
lrwxrwxrwx. 1 root root 14 Feb 5 2013 /etc/rc.d/rc4.d/S55sshd -> ../init.d/sshd
lrwxrwxrwx. 1 root root 14 Feb 5 2013 /etc/rc.d/rc2.d/S55sshd -> ../init.d/sshd

As you can observe from the above output, we have four links representing the same service. The need to remove this type of clutter on the system was one of the major reasons that led to the creation of systemd.

If you decide to open one of these system startup scripts, you will realize that these are just bash shell scripts containing the steps and commands required to bring an individual service to a functional state.

[sahil@linuxnix:/etc/rc.d/init.d] $ pwd
[sahil@linuxnix:/etc/rc.d/init.d] $ ls -l sshd
-rwxr-xr-x 1 root root 4621 Apr 26 2016 sshd
[sahil@linuxnix:/etc/rc.d/init.d] $ file sshd
sshd: Bourne-Again shell script text executable

These scripts generally accept a couple of arguments and one of them is generally the status which tells us if the service is currently running or not. For example, lets check the status of the sshd service.

[sahil@linuxnix:/etc/rc.d/init.d] $ sudo ./sshd status
openssh-daemon (pid 1891) is running...
[sahil@linuxnix:/etc/rc.d/init.d] $

In a future article, we will describe how to configure a service to start up at boot using the SysVinit system manager.
But for the time being, we would like to mention that if you have a script or command that you would like to execute once all the other init scripts have completed execution, then you can add it in the /etc/rc.local file.



In this article, we described the working of the init program, the concept of run levels and how the init program interacts with system startup scripts to bring the system to an operational state. This portion of the boot process covers the tasks which are performed from the time the kernel hands over system control to the init process to the point when we are able to see the login prompt on the screen. We hope that you’ve found the explanation described in this article to be easy and understandable and we look forward towards your feedback.

The following two tabs change content below.

Sahil Suri

He started his career in IT in 2011 as a system administrator. He has since worked with HP-UX, Solaris and Linux operating systems along with exposure to high availability and virtualization solutions. He has a keen interest in shell, Python and Perl scripting and is learning the ropes on AWS cloud, DevOps tools, and methodologies. He enjoys sharing the knowledge he's gained over the years with the rest of the community.