Understanding /etc/inittab and SysV Init Runlevels in Linux
Learn how traditional SysV init uses /etc/inittab to select runlevels, start boot scripts, supervise processes, and differ from systemd.
/etc/inittab is the main configuration file used by traditional System V init, commonly called SysV init. It tells the system's initialization process what to do during boot, when changing runlevels, and when supervising long-running processes.
This topic is most relevant to older Linux installations and legacy systems. Many current distributions use systemd instead, so the file may be absent, ignored, or retained only for compatibility.
What Are init and SysV init?
init is the userspace initialization and process-management program. Historically, it runs as PID 1, the first process started after the kernel has initialized enough hardware and mounted an initial root filesystem.
SysV init organizes system operation around runlevels. A runlevel is a defined operating state that determines which services and tasks should be active. The traditional init program reads /etc/inittab and uses its entries to decide how to reach and maintain that state.
The Role of /etc/inittab During Boot
At a high level, a SysV-style boot proceeds as follows:
- The kernel starts the first userspace process, usually init as PID 1.
- Init reads its configuration, including
/etc/inittabwhen that file is used by the implementation. - Init performs early initialization tasks such as those described by
sysinitentries. - Init determines the target runlevel, commonly from an
initdefaultentry unless a boot option or administrator action supplies another one. - Init runs the entries and scripts associated with that runlevel.
- Services such as terminal login programs are started, making the system available for use.
A later runlevel change causes init to process entries applicable to the new operating state. Depending on the implementation and scripts, services associated with the old state may be stopped and services for the new state started.
The /etc/inittab Entry Format
Most entries have four colon-separated fields in this order:
id:runlevels:action:process
| Field | Purpose | Typical contents | Important behavior |
|---|---|---|---|
id | Identifies the entry | One to four characters | Used by init to distinguish entries |
runlevels | States in which the entry applies | One or more digits, such as 2345 | Some actions leave this field empty |
action | Controls when and how init invokes the process | wait, respawn, initdefault | Determines waiting and supervision behavior |
process | Command or script to execute | An absolute path plus arguments | May be empty for actions that do not launch a process |
Lines beginning with # are comments. Blank lines are ignored. Colons are field separators, so removing or adding one can shift all later fields and change the meaning of an entry. Commands containing special shell characters should be written according to the local init implementation's parsing rules.
Understanding the id Field
The id field labels an entry for init's internal use. Traditional implementations commonly limit it to one through four characters. IDs should be distinct where the implementation requires uniqueness and should be meaningful enough to identify the entry's purpose.
An entry ID is not:
- a Linux user name;
- a process ID or PID;
- a runlevel number.
For example, l3 can identify the entry that handles runlevel 3, while co might identify a console login entry.
Understanding the runlevels Field
This field lists the numeric runlevels in which an entry applies. Multiple runlevels can be listed together without separators:
co:2345:respawn:/sbin/agetty tty1 linux
This illustrative entry applies in runlevels 2, 3, 4, and 5. An entry can also name one runlevel, such as 3. Some actions, including initdefault and commonly sysinit, do not use this field and leave it empty.
Runlevel entries often invoke a central runlevel-management script. The runlevel number tells that script which services to start or stop.
Common action Values
| Action | When init runs it | Whether init waits | Typical use |
|---|---|---|---|
initdefault | During normal startup to choose the default runlevel | Not applicable | Selecting the normal boot operating state |
sysinit | During early, one-time initialization | Implementation-dependent, normally completed before ordinary runlevel processing | Basic system setup before the target runlevel |
boot | During boot | No | A boot-time command that need not block later processing |
bootwait | During boot | Yes | A boot-time command that must finish before continuation |
wait | When entering a matching runlevel | Yes | Runlevel scripts that must complete before init proceeds |
respawn | At the applicable operating state and after termination | Init supervises it rather than treating it as a one-time task | Persistent processes such as terminal login programs |
Action names and details can vary slightly between SysV init implementations. Always check the documentation installed on the target system before relying on an uncommon action.
initdefault
An initdefault entry selects the normal startup runlevel. It uses the runlevels field and does not launch a process, so the process field is empty:
id:3:initdefault:
This example conceptually selects runlevel 3. The appropriate value depends on the distribution. Never select runlevel 0 or 6 as the default: 0 normally halts or powers off the system, while 6 normally reboots it.
sysinit, boot, and bootwait
sysinit is intended for early system initialization. A boot entry starts a boot-time process without waiting for it to finish. A bootwait entry also runs during boot but makes init wait for completion. The distinction matters when later initialization depends on the command finishing.
wait
A wait entry runs when its listed runlevel is entered and makes init wait for the command to return. This is common for an rc script that starts and stops groups of services:
l3:3:wait:/etc/init.d/rc 3
Here, l3 is the ID, 3 is the applicable runlevel, wait is the action, and /etc/init.d/rc 3 is the process command. The script receives 3 as an argument and performs the distribution-specific work for entering runlevel 3.
respawn
respawn tells init to start a process and start it again if it exits. This is useful for a persistent terminal login service:
co:2345:respawn:/sbin/agetty tty1 linux
The exact getty path, terminal name, and arguments vary. If the program exits immediately, init may repeatedly restart it. Implementations commonly apply rate limiting or temporarily disable repeated restarts to prevent a respawn loop from consuming resources. Test custom respawn commands and inspect logs before enabling them on a production console.
Traditional Runlevels
| Runlevel | Common convention | Cautions and distribution differences |
|---|---|---|
| 0 | Halt or power off | Destructive transition state; do not use as a normal default |
| 1 | Single-user, maintenance, or rescue mode | Often provides limited services and administrative access |
| 2 | Multi-user mode | Exact service set varies, especially between distributions |
| 3 | Multi-user mode, commonly without a graphical login | Convention is not universal |
| 4 | Often unused | May be locally customized or assigned a special purpose |
| 5 | Multi-user mode, often with graphical services | Graphical-mode meaning is distribution-specific |
| 6 | Reboot | Destructive transition state; do not use as a normal default |
Runlevels 2 through 5 are conventions rather than a universal standard. The actual services active in each state are determined by the distribution's rc directories, scripts, and local configuration.
Runlevel Script Entries
A common configuration has several entries that call one rc script with different runlevel arguments:
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
Each ID combines a lowercase letter with a runlevel number in this illustrative pattern. The same script is reused, but the argument tells it which operating state to enter. The wait action is important because init waits while the script starts or stops services before continuing with later processing.
Runlevel 4 is omitted here to show that it may be unused. Omitting it does not remove the runlevel from init itself; it simply means this particular configuration has no corresponding entry in the example.
Checking the Default and Current Runlevel
On a traditional SysV system, inspect the initdefault line to identify the configured normal startup state:
grep -vE '^[[:space:]]*($|#)' /etc/inittab
The legacy commands below may report the current and previous runlevel:
runlevel
who -r
Availability and output depend on the distribution and init implementation. A boot parameter or an administrator-requested transition can override the normal default, so the configured default and the currently active runlevel are not always identical.
Editing and Applying Changes Safely
- Confirm that the machine actually uses SysV init before assuming
/etc/inittabcontrols boot behavior. - Make a backup before editing a boot-critical file.
- Preserve the four-field structure and check every path, argument, permission, and runlevel.
- Ensure scripts used with
waitorbootwaitcan return; a script that hangs can stall boot or a runlevel transition. - Keep console, serial, out-of-band, or recovery access available before changing login or default-runlevel entries.
- On a supported SysV system, ask init to reread its configuration rather than rebooting unnecessarily.
telinit q
init q
Use only the command supported by the installed init implementation and local documentation. A reload does not necessarily rerun every boot or runlevel action. A controlled runlevel transition or reboot may be needed to observe a particular change, but test destructive states carefully.
Troubleshooting Common Problems
Editing the file has no effect
First identify PID 1 and the active init implementation:
ps -p 1 -o pid,comm,args
readlink -f /sbin/init
The host may use systemd or another init system, or the file may exist only for compatibility. On a SysV host, init may simply need a supported configuration reload.
The system enters an unexpected mode
Review the initdefault entry, check the current runlevel with runlevel or who -r, and verify the distribution's conventions. A boot option or administrator action may have selected a different state.
A service or login prompt continuously restarts
A respawn-managed command may exit immediately because its path, arguments, terminal, permissions, or configuration are wrong. Run the command manually in a safe environment, inspect logs, correct the underlying failure, and disable the failing respawn entry if necessary.
Boot stalls while entering a runlevel
A wait entry may invoke a script that hangs while waiting for storage, networking, a device, or another dependency. Use console or rescue access, inspect init and service logs, and isolate the blocking script.
No console login appears
Check whether the getty or equivalent respawn entry was removed, malformed, restricted to different runlevels, or given an invalid terminal device or command path. Compare it with a known-good configuration using alternate console or recovery access.
The system immediately halts or reboots
This commonly indicates that runlevel 0 or 6 was selected as the default, or that an rc script received the wrong argument. Correct the configuration from a rescue environment and validate it before rebooting.
Modern Linux Compatibility
Most current Linux distributions use systemd rather than traditional SysV init. Systemd uses units and targets; a target groups units to represent an operating state similar in concept to a runlevel.
| Legacy SysV concept | Modern systemd counterpart | Notes |
|---|---|---|
| Default runlevel | Default target | Inspect with systemctl get-default |
| Runlevel service group | Target and its dependencies | The relationship is conceptual, not an exact one-to-one mapping |
| init process as PID 1 | systemd as PID 1 | Both provide initialization and process-management responsibilities, but their models differ |
/etc/inittab | Unit and target configuration | Systemd normally does not use inittab as its controlling configuration |
/etc/init.d service scripts | Native units or generated compatibility units | Legacy scripts may remain even when systemd controls boot |
systemctl get-default
systemctl list-units --type=target
For example, a legacy multi-user runlevel may correspond approximately to multi-user.target, while a graphical runlevel may correspond approximately to graphical.target. The mapping depends on the distribution and enabled services; it is not a guarantee that every runlevel entry has a direct systemd equivalent.
Upstart and other initialization systems use different configuration models as well. The presence of traditional scripts under /etc/init.d does not prove that /etc/inittab controls the machine.
Key Exam Notes
/etc/inittabis associated with traditional SysV init, not automatically with every Linux system.- The four fields are
id:runlevels:action:process. initdefaultselects a default runlevel and does not launch a process.sysinithandles early initialization;bootdoes not wait, whilebootwaitdoes.waitruns a matching command and waits for it to finish.respawnrestarts a process after it exits and is commonly used for getty-style login programs.- Runlevel 0 halts, runlevel 6 reboots, and runlevel 1 commonly provides single-user maintenance mode.
- Runlevels 2 through 5 have distribution-specific meanings.
- Systemd targets are the modern conceptual counterpart to runlevels.
For related Linux command and filesystem fundamentals, see Linux, Show The Full Path Of Shell Commands, and Determine File Type.