init is the driving force that keeps our Linux box alive and is also the one that can put it to death. This article summarizes why init is so powerful and how you can instruct it to behave differently from its default behaviour. (Yes, init is powerful, but the superuser rules over init.)
Using /bin/sh as a Minimal Choice

As suggested above, the shell can be used as an init program. Using a bare shell (init=/bin/sh) simply causes a root shell to open in a completely unconfigured system. This section shows how a shell script can perform all of the tasks you need to have in a minimal running system. This kind of tiny init can be used in embedded systems or similar reduced environments, where you must squeeze every single byte out of the system. The most radical approach to embedded systems is directly running the target application as the init process; this results in a closed system (no way for the administrator to interact, should problems arise), but it sometimes suits the setup. The typical example of a non-init-driven Linux system is the installation environment of most modern distributions, where /sbin/init is a symbolic link to the installation program.

Listing 1 shows a script that can perform acceptably as init. The script is short and incomplete; in particular, note that it runs only one getty, which isn't restarted when it terminates. Be careful if you try to use this script, as each Linux distribution chooses its own flavour of getty. Type grep getty /etc/inittab to know what you have and how to call it.

The script has another problem: it doesn't deal with system shutdown. Adding shutdown support, however, is fairly easy; just bring everything down after the interactive shell terminates. Adding the text shown in Listing 2 does the trick.

Whenever you boot with a plain init=/bin/sh, you should at least remount the root file system before you do anything; you should also remember to do umount -a before pressing ctrl-alt-del, because the shell doesn't intercept the three-finger salute.

simpleinit, from util-linux

The util-linux package includes a C version of an init program. It has more features than the shell script and can work well on most personal systems, although it doesn't offer the huge amount of configurability offered by the SysVinit package, which is the default on modern distributions.

The role of simpleinit (which should be called init to work properly) is very similar to the shell script just shown, with the added capability of managing single-user mode and iterative invocation of console sessions. It also correctly processes shutdown requests.

simpleinit is interesting to look at, and well-documented too, so you might enjoy reading the documentation. I suggest using the source distribution of util-linux to get up-to-date information.

The implementation of simpleinit truly is simple, as its name suggests. The program executes a shell script (/etc/rc) and parses a configuration file to determine which processes need to be respawned. The configuration file is called /etc/inittab, just like the one used by the full-featured init; note, however, that its format is different.

If you plan to install simpleinit on your system (which most likely already includes SysVinit), you must proceed with great care and be prepared to reboot with a kernel argument of “init=/bin/sh” to recover from unstable situations.

The Real Thing: SysVinit

Most Linux distributions come with the version of init written by Miquel van Smoorenburg; this version is similar to the approach taken by System V UNIX.

The main idea is that the user of a computer system may wish to operate his box in one of several different ways (not just single-user and multi-user). Although this feature is not usually exploited, it is not so crazy as you might imagine. When the computer is shared by two or more people in one family, different setups may be needed; a network server and a stand-alone playstation can happily coexist in the same computer at different runlevels. Although I'm the only user of my laptop, I sometimes want a network server (through PLIP) and sometimes a netless environment to save resources when I'm working on the train.

Each operating mode is called a “runlevel”, and you can choose the runlevel to use at either boot or runtime. The main configuration file for init is called /etc/inittab, which defines what to do at boot, when entering a runlevel or when switching from one runlevel to another. It also tells how to handle the three-finger salute and how to deal with power failure, although you'll need a power daemon and a UPS to benefit from this feature.

The inittab file is organized by lines, where each line is made up of several colon-separated fields: id:runlevel:action:command.

The inittab(5) man page is well written and comprehensive as a man page should be, and I feel it is worth repeating one of its examples—a stripped-down /etc/inittab that implements the same features and misfeatures of the shell script shown above:

1:1:respawn:/sbin/getty 9600 tty1

This simple inittab tells init that the default runlevel is “1”, at system boot it must execute /etc/rc, and when in runlevel 1 it must respawn forever the command /sbin/getty 9600 tty1. You're not expected to test this script out, because it doesn't handle the shutdown procedure.

Before proceeding further, however, I must fill in a couple of gaps. Let's answer two common questions:

  • “How can I boot into a different runlevel than the default?” Add the runlevel on the kernel command line; for example, type Linux 2 at the LILO prompt, if “Linux” is the name of your kernel.

  • “How can I switch from one runlevel to another?” As root, type telinit 5 to tell the init process to switch to runlevel 5. Different numbers indicate different runlevels.