Understanding the rc Scripts in Linux

The rc script

When init enters a runlevel, it calls the rc script with a numeric argument specifying the runlevel to go to. rc then starts and stops services on the system as necessary to bring the system to that runlevel. Though typically called at boot, the rc script can be called by init to change runlevels. For example, the following can be used to change the system to runlevel 3:

# init 3

When changing to runlevel 3, rc brings the system into the new runlevel by stopping all services which are not supposed to run in runlevel 3 and starting all services which run in runlevel 3 which are not already running.

You’ll find all the system initialization scripts in /etc/rc.d. This subdirectory has more subdirectories, one for each runlevel: rc0.d–rc6.d and init.d. Within the /etc/rc.d/rc#.d subdirectories (where the # is replaced by a single-digit number) are symbolic links to the master scripts stored in /etc/rc.d/init.d.

# ls -lrt /etc/rc.d
total 60
-rwxr-xr-x  1 root root   889 Jan 29  2015 rc.local
-rwxr-xr-x  1 root root 20199 Oct  4  2017 rc.sysinit
-rwxr-xr-x  1 root root  2617 Oct  4  2017 rc
drwxr-xr-x. 2 root root  4096 Mar 20 16:49 init.d
drwxr-xr-x. 2 root root  4096 Mar 20 16:49 rc1.d
drwxr-xr-x. 2 root root  4096 Mar 20 16:49 rc0.d
drwxr-xr-x. 2 root root  4096 Mar 20 16:49 rc6.d
drwxr-xr-x. 2 root root  4096 Mar 20 16:54 rc4.d
drwxr-xr-x. 2 root root  4096 Mar 20 16:54 rc3.d
drwxr-xr-x. 2 root root  4096 Mar 20 16:54 rc2.d
drwxr-xr-x. 2 root root  4096 Mar 20 16:54 rc5.d

The scripts in init.d take an argument of start or stop, and occasionally of reload or restart.

Runlevel Implementation

Runlevels are implemented as directories on the system which contain shell scripts to start and stop specific daemons, e.g. /etc/rc1.d/. Most systems have directories for runlevels 0-6.

The scripts within each directory are named with either a capital S, or a capital K, followed by a two-digit number, followed by the name of the service being referenced. The files beginning with capital S represent scripts which are started upon entering that runlevel, while files beginning with capital K represent scripts which are stopped. The numbers specify the order in which the scripts should be executed.

For example, a daemon might have a script named S35daemon in rc3.d/, and a script named K65daemon to stop it in rc2.d/. Having the numbers at the beginning of the file name causes them to sort, and be processed, in the desired order.

/etc/rc

When the /etc/rc program is called by init to change runlevels, it does so by going to the directory for the target runlevel and works through all the K##script files to stop currently running services that should not be in the target runlevel and S##script files for services that should be, but are not currently, running in the target runlevel.

Because of the way the /etc/rc program works Linux, the individual /etc/rc#.d/ directories will only have either an S##script or a K##script symlink for each service. There will also be a symlink for each service in each of the seven /etc/rc#.d/ directories. With the exception of the S99local file (symlink to ../rc.local), which only appears in /etc/rc1.d/ through /etc/rc5.d/ and has no corresponding kill symlink, there should always be the same number of files in each of the runlevel directories.

Order Dependencies At Boot

Having the scripts start and stop in the proper order is important. For example, in order for NFS and NIS to work properly, the RPC portmapper daemon rpcbind must be started first.

/etc/init.d/

To avoid script duplication, the files in the rc#.d/ directories are actually symbolic links to script files located in the /etc/init.d/ directory. Every service installed on the system installs a script in this directory which can be used to control that service. These scripts are written to take start options specifying that they should start the service, and stop options specifying that they should stop the service.

Upstart and SysV Runlevel Compatibility

Since Upstart doesn’t have any internal notion of runlevels, support for them is defined by the /etc/init/rc.conf file. This support exists to provide backwards compatibility for the Single Unix Specification, and previous SysV Init implementations.

/etc/rc.local

Custom scripts to carry out tasks on the system can be created in the /etc/init.d/ directory and then symbolic links to those scripts can be created in the /etc/rc#.d/ directories to start or stop the scripts as necessary. For some tasks, however, creating full-blown System V-style init scripts, complete with start and stop options, is overkill; some tasks, for example, need to be executed once when the system boots up, but never need to be killed, or do not need to be run every time the system changes runlevels, or for other reasons are not totally amenable to execution from a System V Init script.

Related Post