Panel For Example Panel For Example Panel For Example

Understanding the Linux Boot Process

Author : Adrian September 17, 2025

Linux Boot Process

Overview

This article examines the boot sequence of the Linux operating system, focusing on Debian-based systems.

Context: BIOS vs Operating System

During the BIOS stage the computer's behavior is largely fixed and offers limited options for programmers. Once the operating system takes over, most aspects become configurable, so the boot process is closely related to software behavior.

1. Loading the Kernel

After the firmware hands control to the operating system, the kernel image in the /boot directory is read into memory.

Example contents of /boot on the author’s machine:

$ ls /boot config-3.2.0-3-amd64 config-3.2.0-4-amd64 grub initrd.img-3.2.0-3-amd64 initrd.img-3.2.0-4-amd64 System.map-3.2.0-3-amd64 System.map-3.2.0-4-amd64 vmlinuz-3.2.0-3-amd64 vmlinuz-3.2.0-4-amd64

2. Starting the init Process

Once the kernel is loaded, it starts the first userland process: /sbin/init. This process initializes the system environment.

init is the first user process and therefore has process ID 1. Other processes are spawned from it.

3. Determining the Runlevel

Many programs need to start at boot. On Windows these are called "services"; on Linux they are typically daemons. A main task of init is to run these boot-time daemons.

Different use cases require different sets of services. Linux uses runlevels to specify which services should start for a given scenario. During boot, init reads the runlevel setting and starts the corresponding services.

Linux historically defines seven runlevels (0-6). Common conventions are: 0 = halt, 1 = single-user (maintenance) mode, 6 = reboot. Runlevels 2–5 vary by distribution; on Debian they are typically equivalent multiuser modes.

init reads /etc/inittab to determine the default runlevel. For example:

id:2:initdefault:

This sets the default runlevel to 2. Each runlevel has a corresponding directory under /etc that lists the services to start:

/etc/rc0.d /etc/rc1.d /etc/rc2.d /etc/rc3.d /etc/rc4.d /etc/rc5.d /etc/rc6.d

Files in /etc/rcN.d typically follow the naming convention S##name or K##name. S indicates start and K indicates kill (stop). The two digits indicate order: lower numbers run earlier. If numbers match, alphabetical order of the service name is used.

$ ls ?/etc/rc2.d README S01motd S13rpcbind S14nfs-common S16binfmt-support S16rsyslog S16sudo S17apache2 S18acpid ...

4. Loading Boot Services

To avoid duplicating startup scripts across multiple runlevel directories, the entries in /etc/rcN.d are symbolic links pointing to the actual scripts in /etc/init.d. init executes those scripts to start or stop services.

$ ls -l /etc/rc2.d README S01motd -> ../init.d/motd S13rpcbind -> ../init.d/rpcbind S14nfs-common -> ../init.d/nfs-common S16binfmt-support -> ../init.d/binfmt-support S16rsyslog -> ../init.d/rsyslog S16sudo -> ../init.d/sudo S17apache2 -> ../init.d/apache2 S18acpid -> ../init.d/acpid ...

Because the real scripts live in /etc/init.d, administrators can run them directly. For example, to restart Apache:

$ sudo /etc/init.d/apache2 restart

5. User Login

After boot services are loaded, the system prompts for user login. Common login methods include:

  1. local console (command-line) login
  2. ssh login
  3. graphical (display manager) login

Authentication is handled differently depending on the method:

Local console: init invokes getty to prompt for username and password. After credentials are entered, login verifies the password (Debian typically runs PAM modules such as /etc/pam.d/login). On success, the user’s configured shell is read from /etc/passwd and started.

SSH: The sshd daemon handles authentication (Debian typically uses /etc/pam.d/ssh) and then starts the user’s shell.

Graphical: A display manager handles authentication (for GNOME, gdm). On success, the session script such as /etc/gdm3/Xsession is executed to start the user session.

6. Entering the Login Shell

A login shell is the shell started after authentication that reads a set of initialization files. Debian’s default shell is Bash, which reads a sequence of configuration files depending on how the session was started.

For console and SSH logins, Bash reads /etc/profile followed by one of these user files, in order:

~/.bash_profile ~/.bash_login ~/.profile

Only the first existing file in that list is read.

For graphical logins, Bash typically reads /etc/profile and ~/.profile only; ~/.bash_profile is not used in that case.

7. Opening Non-login Shells

A non-login shell is often started when a user opens an additional terminal window. Non-login shells do not read /etc/profile or ~/.profile; instead, they read ~/.bashrc. Because most user customizations are placed in ~/.bashrc, Debian’s default configuration sources ~/.bashrc from ~/.profile so that settings apply consistently.

Example in ~/.profile:

if [ -n "$BASH_VERSION" ]; then if [ -f "$HOME/.bashrc" ]; then . "$HOME/.bashrc" fi fi

If you rely on ~/.bash_profile and it prevents ~/.profile from being read, add the following to ~/.bash_profile to ensure ~/.profile (and thus ~/.bashrc) is sourced:

if [ -f ~/.profile ]; then . ~/.profile fi

The historical split between these files reflects performance and inheritance considerations from earlier systems: /etc/profile for system-wide settings, ~/.profile for user settings inherited by child processes, and ~/.bashrc for interactive, non-inherited settings.

Note: macOS also uses Bash as the default shell in older releases. On macOS, the typical behavior is to load ~/.bash_profile and source ~/.bashrc from there for both SSH and GUI-launched shells.