Skip to main content
p. 157

6.5 System V init

The System V init implementation is among the oldest used on Linux; its core idea is to support an orderly bootup to different runlevels with a carefully constructed startup sequence. System V init is now uncommon on most server and desktop installations, but you may encounter it in versions of RHEL prior to version 7.0, as well as in embedded Linux environments, such as routers and phones. In addition, some older packages may only provide startup scripts designed for System V init; systemd can handle those with a compatibility mode that we’ll discuss in Section 6.5.5. We’ll look at the basics here, but keep in mind that you might not actually encounter anything covered in this section.

A typical System V init installation has two components: a central configuration file and a large set of boot scripts augmented by a symbolic link farm. The configuration file /etc/inittab is where it all starts. If you have System V init, look for a line like the following in your inittab file:

id:5:initdefault:

This indicates that the default runlevel is 5.

All lines in inittab take the following form, with four fields separated by colons in this order:

  1. A unique identifier (a short string, such as id in the previous example).
  2. The applicable runlevel number(s).
  3. The action that init should take (default runlevel to 5 in the previous example).
  4. A command to execute (optional).

To see how commands work in an inittab file, consider this line:

l5:5:wait:/etc/rc.d/rc 5

This particular line is important because it triggers most of the system configuration and services. Here, the wait action determines when and how System V init runs the command: run /etc/rc.d/rc 5 once when entering p. 158 runlevel 5 and then wait for this command to finish before doing anything else. The rc 5 command executes anything in /etc/rc5.d that starts with a number (in numeric order). We’ll cover this in more detail shortly.

The following are some of the most common inittab actions in addition to initdefault and wait:

respawn

The respawn action tells init to run the command that follows and, if the command finishes executing, to run it again. You’re likely to see something like this in an inittab file:

1:2345:respawn:/sbin/mingetty tty1

The getty programs provide login prompts. The preceding line is used for the first virtual console (/dev/tty1), which is the one you see when you press ALT-F1 or CTRL-ALT-F1 (see Section 3.4.7). The respawn action brings the login prompt back after you log out.

ctrlaltdel

The ctrlaltdel action controls what the system does when you press CTRL-ALT-DEL on a virtual console. On most systems, this is some sort of reboot command using the shutdown command (discussed in Section 6.6).

sysinit

The sysinit action is the first thing that init should run when starting, before entering any runlevels.

note

For more available actions, see the inittab(5) manual page.

6.5.1 System V init: Startup Command Sequence​

Now let’s look at how System V init starts system services, just before it lets you log in. Recall this inittab line from earlier:

l5:5:wait:/etc/rc.d/rc 5

This short line triggers many other programs. In fact, rc stands for run commands, which many people refer to as scripts, programs, or services. But where are these commands?

The 5 in this line tells us that we’re talking about runlevel 5. The commands are probably in either /etc/rc.d/rc5.d or /etc/rc5.d. (Runlevel 1 uses rc1.d, runlevel 2 uses rc2.d, and so on.) For example, you might find the following items in the rc5.d directory:

S10sysklogd S20ppp S99gpm
S12kerneld S25netstd_nfs S99httpd
S15netstd_init S30netstd_misc S99rmnologin
S18netbase S45pcmcia S99sshd
S20acct S89atd
S20logoutd S89cron
p. 159

The rc 5 command starts programs in the rc5.d directory by executing the following commands in this sequence:

S10sysklogd start
S12kerneld start
S15netstd_init start
S18netbase start
--snip--
S99sshd start

Notice the start argument in each command. The capital S in a command name means that the command should run in start mode, and the number (00 through 99) determines where in the sequence rc starts the command. The rc*.d commands are usually shell scripts that start programs in /sbin or /usr/sbin.

Normally, you can figure out what a particular command does by viewing the script with less or another pager program.

note

Some rc*.d directories contain commands that start with K (for “kill,” or stop mode). In this case, rc runs the command with the stop argument instead of start. You’ll most likely encounter K commands in runlevels that shut down the system.

You can run these commands by hand; however, normally you’ll want to do so through the init.d directory instead of the rc*.d directories, which we’ll look at next.

The contents of the rc*.d directories are actually symbolic links to files in yet another directory, init.d. If your goal is to interact with, add, delete, or modify services in the rc*.d directories, you need to understand these symbolic links. A long listing of a directory such as rc5.d reveals a structure like this:

lrwxrwxrwx . . . S10sysklogd -> ../init.d/sysklogd
lrwxrwxrwx . . . S12kerneld -> ../init.d/kerneld
lrwxrwxrwx . . . S15netstd_init -> ../init.d/netstd_init
lrwxrwxrwx . . . S18netbase -> ../init.d/netbase
--snip--
lrwxrwxrwx . . . S99httpd -> ../init.d/httpd
--snip--

A large number of symbolic links across several subdirectories like this is called a link farm. Linux distributions contain these links so that they can use the same startup scripts for all runlevels. This is a convention, not a requirement, but it simplifies organization.

p. 160

Starting and Stopping Services​

To start and stop services by hand, use the script in the init.d directory. For example, one way to start the httpd web server program manually is to run init.d/httpd start. Similarly, to kill a running service, you can use the stop argument (httpd stop, for instance).

Modifying the Boot Sequence​

Changing the boot sequence in System V init is normally done by modifying the link farm. The most common change is to prevent one of the commands in the init.d directory from running in a particular runlevel. You have to be careful about how you do this, however. For example, you might consider removing the symbolic link in the appropriate rc*.d directory. But if you ever need to put the link back, you might have trouble remembering its exact name. One of the best approaches is to add an underscore (_) at the beginning of the link name, like this:

# mv S99httpd _S99httpd

This change causes rc to ignore _S99httpd because the filename no longer starts with S or K, but the original name still indicates its purpose.

To add a service, create a script like those in the init.d directory and then create a symbolic link in the correct rc*.d directory. The easiest way to do this is to copy and modify one of the scripts already in init.d that you understand (see Chapter 11 for more information on shell scripts).

When adding a service, choose an appropriate place in the boot sequence to start it. If the service starts too soon, it may not work due to a dependency on some other service. For nonessential services, most systems administrators prefer numbers in the 90s, which puts the services after most of the services that came with the system.

6.5.3 run-parts​

The mechanism that System V init uses to run the init.d scripts has found its way into many Linux systems, regardless of whether they use System V init. It’s a utility called run-parts, and the only thing it does is run a bunch of executable programs in a given directory, in some kind of predictable order. You can think of run-parts as almost like a person who enters the ls command in some directory and then just runs whatever programs are listed in the output.

The default behavior is to run all programs in a directory, but you often have the option to select certain programs and ignore others. In some distributions, you don’t need much control over the programs that run. For example, Fedora ships with a very simple run-parts utility.

Other distributions, such as Debian and Ubuntu, have a more complicated run-parts program. Their features include the ability to run programs based on a regular expression (for example, using the S[0-9]{2} expression p. 161 for running all “start” scripts in an /etc/init.d runlevel directory) and to pass arguments to the programs. These capabilities allow you to start and stop System V runlevels with a single command.

You don’t really need to understand the details of how to use run-parts; in fact, most people don’t know that it even exists. The main things to remember are that it shows up in scripts from time to time and that it exists solely to run the programs in a given directory.

6.5.4 System V init Control​

Occasionally, you’ll need to give init a little kick to tell it to switch runlevels, to reread its configuration, or to shut down the system. To control System V init, you use telinit. For example, to switch to runlevel 3, enter:

# telinit 3

When switching runlevels, init tries to kill off any processes not in the inittab file for the new runlevel, so be careful when changing runlevels.

When you need to add or remove jobs, or make any other change to the inittab file, you must tell init about the change and have it reload the file. The telinit command for this is:

# telinit q

You can also use telinit s to switch to single-user mode.

6.5.5 systemd System V Compatibility​

One feature that sets systemd apart from other newer-generation init systems is that it tries to do a more complete job of tracking services started by System V–compatible init scripts. It works like this:

  1. First, systemd activates runlevel<N>.target, where N is the runlevel.
  2. For each symbolic link in /etc/rc<N>.d, systemd identifies the script in /etc/init.d.
  3. systemd associates the script name with a service unit (for example, /etc/init.d/foo would be foo.service).
  4. systemd activates the service unit and runs the script with either a start or stop argument, based on its name in rc<N>.d.
  5. systemd attempts to associate any processes from the script with the service unit.

Because systemd makes the association with a service unit name, you can use systemctl to restart the service or view its status. But don’t expect any miracles from System V compatibility mode; it still must run the init scripts serially, for example.