| | {{infobox |
| | | title = Inside a Linux System |
| | | chapter = Linux Handbook, chapter 17 — the boot sequence, init, services, the anatomy |
| | | core | kernel + initramfs + PID 1 + services + login — the whole arc |
| | | paths = SysVinit (the readable path) · systemd (the standard path) |
| | | skills | boot chain · runlevels/units · service management · logs |
| | | next | Networking — the system's window outward |
| | }} |
| | |
| | **A Linux system is an arc**: firmware hands to a bootloader, the bootloader hands to a kernel, the kernel mounts a rootfs and execs PID 1, PID 1 brings up services, services reach a login. This chapter walks the whole arc — both init paths (SysVinit's readable rc scripts and systemd's unit graph) — and teaches you to read and control the machine's own machinery. |
| | |
| | ## The boot chain — six handoffs |
| | |
| | ``` |
| | firmware → bootloader → kernel (+initramfs) → rootfs → PID 1 → services → login |
| | ``` |
| | |
| | 1. **Firmware** — BIOS or UEFI — POSTs, finds a boot device, loads the bootloader. UEFI reads the ESP's `EFI/` tree. |
| | 2. **Bootloader** — GRUB (usually) — presents the menu, loads `vmlinuz` + `initramfs` into memory, hands over with a kernel command line (`root=/dev/sda3 ro quiet`). |
| | 3. **Kernel** — decompresses, initializes drivers, mounts the rootfs, runs `/sbin/init` as **PID 1**. (The initramfs — a temporary rootfs in RAM — carries drivers the kernel needs to *reach* the real rootfs.) |
| | 4. **PID 1** — init — the ancestor of every process; brings the system to a usable state. |
| | 5. **Services** — gettys, daemons, network, logging — all spawned by init. |
| | 6. **Login** — a getty prompts; `login` checks `/etc/passwd`+shadow; a shell starts. |
| | |
| | Each handoff is inspectable: `dmesg` is the kernel's own log of stage 3; `journalctl` or `/var/log/messages` covers stages 4–6. |
| | |
| | ## PID 1 — the two paths |
| | |
| | ### SysVinit — the readable path |
| | |
| | ```sh |
| | cat /etc/inittab # the runlevel map — id:3:initdefault: |
| | ls /etc/rc.d/ # rc.S (sysinit) rc.M (multiuser) rc.6 (reboot) rc.inet1 rc.sshd |
| | /etc/rc.d/rc.sshd restart # the interface — scripts you can READ |
| | ``` |
| | |
| | Inittab defines **runlevels** — 0 halt, 1 single-user, 3 multiuser (Slackware default), 4 X11, 6 reboot. `telinit 3` changes them. Services are `rc.*` shell scripts, started in order. The beauty: **it's all shell** — `cat /etc/rc.d/rc.M` shows you *exactly* what boot does. Slackware's entire init system fits in a few readable scripts. |
| | |
| | ### systemd — the standard path |
| | |
| | ```sh |
| | systemctl status sshd # state of a unit |
| | systemctl start sshd # bring up |
| | systemctl enable sshd # start at boot |
| | systemctl list-units --type=service |
| | systemctl list-dependencies # the dependency graph |
| | systemctl isolate multi-user.target # the "runlevel" equivalent |
| | journalctl -u sshd # the unit's log |
| | journalctl -b # this boot's whole log |
| | journalctl -f # follow live |
| | ``` |
| | |
| | Systemd replaces scripts with **units** — declarative files in `/etc/systemd/system/` + `/usr/lib/systemd/system/` — started by dependency order, not sequence. Faster, parallel, self-logging — and opaque in ways SysVinit never is. `.service`, `.mount`, `.socket`, `.timer`, `.target` — the unit types; `.target`s are the runlevel analogues (`multi-user.target` ≈ runlevel 3). |
| | |
| | ## The runlevels — the complete map |
| | |
| | ```sh |
| | # SysV: 0 halt · 1 single-user · 2 unused · 3 multiuser · 4 X11 · 5 unused · 6 reboot |
| | runlevel # where you are — "N 3" |
| | telinit 1 # single-user — the maintenance mode |
| | telinit 3 # multiuser text |
| | telinit 4 # X11 — the graphical level |
| | telinit 6 # reboot |
| | init 0 # halt — the older spelling |
| | |
| | # systemd's target equivalents: |
| | systemctl isolate rescue.target # single-user |
| | systemctl isolate multi-user.target # = runlevel 3 |
| | systemctl isolate graphical.target # = runlevel 4/5 |
| | systemctl get-default # the default target |
| | systemctl set-default multi-user.target # change it |
| | systemctl reboot / poweroff / suspend |
| | shutdown -h now / shutdown -r +5 "message" / shutdown -c |
| | ``` |
| | |
| | Runlevel 1/rescue = single-user: minimal services, no network, root shell — where fsck, password resets, and surgery happen. |
| | |
| | ## The init scripts — SysV's readable machinery |
| | |
| | ```sh |
| | ls /etc/rc.d/ # Slackware's scripts |
| | # rc.S — system init (early) |
| | # rc.M — multiuser — the main one |
| | # rc.0/6 — halt/reboot |
| | # rc.inet1 — network |
| | # rc.sshd rc.mysqld ... — services |
| | /etc/rc.d/rc.sshd restart # the interface |
| | /etc/rc.d/rc.local # the local-hacks script — last in boot |
| | /etc/rc.d/rc.local_shutdown # and on shutdown |
| | ``` |
| | |
| | Each is a plain shell script — `cat /etc/rc.d/rc.M` shows the *entire* multiuser boot sequence in a page of readable commands. The `K`/`S` symlink convention (`rc3.d/S10sysklogd` = start at priority 10) orders them. |
| | |
| | ## The services' plumbing |
| | |
| | **gettys** — the login prompts: one per virtual console (`Ctrl-Alt-F2` switches). Inittab's `c1:12345:respawn:/sbin/agetty tty1` or systemd's `[email protected]` — `respawn` is the self-healing restart. |
| | |
| | **Daemons** — long-running services — daemonize by detaching from the terminal (setsid, no tty); systemd manages them as units. Logs to syslog (`/var/log/messages`) or journald. |
| | |
| | **Cron** — the scheduler: `crontab -e` — `0 3 * * * /usr/local/bin/backup` — minute hour day month weekday. `/etc/cron.daily/` et al. for the system. systemd **timers** are the modern unit-based equivalent. |
| | |
| | ## systemd units — the anatomy |
| | |
| | ```ini |
| | # /etc/systemd/system/myservice.service — a complete unit |
| | [Unit] |
| | Description=My service |
| | After=network.target |
| | Wants=network-online.target |
| | |
| | [Service] |
| | Type=simple # simple|forking|oneshot|notify|dbus|idle|exec |
| | ExecStart=/usr/bin/myservice --flag |
| | ExecReload=/bin/kill -HUP $MAINPID |
| | Restart=on-failure # always|on-success|on-failure|no |
| | RestartSec=5 |
| | User=mysvc |
| | Group=mysvc |
| | WorkingDirectory=/var/lib/mysvc |
| | Environment=VAR=val |
| | ExecStartPre=/usr/bin/precheck |
| | ExecStartPost=/usr/bin/post |
| | LimitNOFILE=65536 |
| | ProtectSystem=strict # read-only / |
| | PrivateTmp=true # own /tmp |
| | NoNewPrivileges=true |
| | |
| | [Install] |
| | WantedBy=multi-user.target # enable → symlink into the target's .wants/ |
| | ``` |
| | |
| | The sections: `[Unit]` dependencies, `[Service]` the process config, `[Install]` how `enable` wires it into boot. `Type=` is the contract — `simple` (foreground), `forking` (daemonizes), `oneshot` (runs once), `notify` (sd_notify protocol). `systemctl daemon-reload` after editing; `systemctl cat` shows the composed unit. |
| | |
| | ## The unit types |
| | |
| | `.service` processes · `.socket` socket-activation · `.timer` cron-replacement · `.mount` mounts · `.automount` lazy-mounts · `.target` runlevel-groups · `.path` inotify triggers · `.slice` cgroup buckets · `.device` udev-derived. `systemctl list-units --type=service` enumerates. |
| | |
| | ## The journal — structured logging |
| | |
| | ```sh |
| | journalctl --list-boots # every boot, ever — pick one to read |
| | journalctl _PID=1234 # by process |
| | journalctl -g 'pattern' # grep the journal |
| | journalctl -o json-pretty # structured output |
| | journalctl --priority=emerg..err # level band |
| | journalctl _SYSTEMD_UNIT=sshd.service _COMM=sshd |
| | ``` |
| | |
| | Fields are queryable (`_PID`, `_COMM`, `_SYSTEMD_UNIT`) — journald is a queryable database, not text files. |
| | |
| | ## The boot stages' detail — what actually fires when |
| | |
| | ```text |
| | 0. Firmware — UEFI/BIOS POST → reads GPT → loads bootloader |
| | 1. Bootloader — GRUB loads kernel + initramfs → jumps to start_kernel |
| | 2. Kernel — init/main.c → start_kernel() → scheduler + mm + drivers |
| | → rest_init() → kernel_init → run_init_process("/sbin/init") |
| | 3. Initramfs — early root: unpack → its init loads modules → mounts real root |
| | → switch_root → the real root takes over |
| | 4. PID 1 — /sbin/init (SysV) or /usr/lib/systemd/systemd |
| | 5. Services — SysV: rc.S → rc.M → gettys |
| | systemd: targets → units → [email protected] |
| | 6. Login — getty/agetty → login → PAM → /etc/profile → shell |
| | ``` |
| | |
| | `dmesg` shows stage 2-3 verbatim — the `BIOS-e820` map, the mount, the `Run /sbin/init as init process` line. `journalctl -b` shows stage 4-5. The kernel cmdline (`cat /proc/cmdline`) is stage 1's record. |
| | |
| | ## The PID-1 contract — what init must do |
| | |
| | - Reap orphans — every reparented child ends at PID 1 |
| | - Never exit — the kernel panics if PID 1 dies |
| | - Handle SIGCHLD — collect zombies |
| | - Be the root of the cgroup tree — every process descends |
| | - Start the world — mount the filesystems, bring up services, spawn login |
| | |
| | SysVinit does it via `/etc/inittab` + rc scripts — readable shell. systemd does it via unit-graph + journald — structured. Both satisfy the contract; the argument is about *how*. |
| | |
| | ## The kernel's own interfaces |
| | |
| | - **`dmesg`** — the kernel ring buffer: hardware detection, driver loads, oopses — boot's transcript |
| | - **`/proc`** — processes + kernel state as files |
| | - **`/sys`** — devices/drivers as a browsable object tree |
| | - **`sysctl`/`/proc/sys`** — live kernel knobs: `sysctl -w net.ipv4.ip_forward=1` |
| | - **`modprobe`**/`lsmod`/`modinfo` — loadable modules — the driver's hotplug layer |
| | |
| | ## Runlevels / targets — the modes |
| | |
| | ```sh |
| | runlevel # SysV — where you are |
| | telinit 1 # single-user — maintenance mode (the rescue level) |
| | telinit 3 # multiuser text |
| | telinit 6 # reboot |
| | systemctl isolate rescue.target # systemd's single-user |
| | systemctl reboot / poweroff # the controlled shutdowns |
| | shutdown -h now # traditional halt |
| | ``` |
| | |
| | Runlevel 1 / `rescue.target` — single-user mode — is the maintenance door: minimal services, root shell, the place filesystem checks and password resets happen. The kernel command line's `single` or `init=/bin/bash` boots straight there — the rescue technique of last resort. |
| | |
| | ## The LFS system's boot — what you built |
| | |
| | The LFS SysVinit path installs `sysvinit` + `sysklogd` + the boot scripts — `/etc/rc.d/init.d/` scripts for cleanfs, modules, network, sysklogd — a minimal but *legible* init. Chapter 6's `/etc/inittab` + fstab + rc scripts are the whole machine's waking machinery — you wrote them from nothing. |
| | |
| | ## Where the system goes wrong |
| | |
| | | Symptom | Cause | |
| | | --- | --- | |
| | | Boots to `grub>` or rescue | Bootloader/config — chapter 6 territory | |
| | | Kernel panic — can't mount root | rootfs driver/filesystem not built-in | |
| | | Boots, no login prompt | getty not spawning — inittab/agetty | |
| | | Service won't start | `systemctl status`/`journalctl -u` — or the rc script's exit code | |
| | | Slow boot | `systemd-analyze blame` — or a blocking rc script | |
| | | `dmesg` flooded with errors | Driver/hardware — `dmesg -l err` filters | |
| | | Can't change runlevel | systemd targets ≠ SysV runlevels — wrong tool for the init | |
| | |
| | ## Exercises |
| | |
| | 1. `dmesg | less` — read your kernel's boot transcript. |
| | 2. `cat /etc/inittab` (SysV) or `systemctl list-dependencies` (systemd) — the boot plan. |
| | 3. `pstree -p | head -20` — the fork family from PID 1. |
| | 4. `journalctl -b` or `less /var/log/messages` — this boot's log. |
| | 5. Switch a virtual console (Ctrl-Alt-F2); identify the getty that owns it. |
| | 6. `sysctl -a | less` — the kernel's tunable mind. |
| | |
| | ## Timeline |
| | |
| | | Handoff | The mechanism | |
| | | --- | --- | |
| | | firmware | BIOS/UEFI → ESP/boot sector | |
| | | bootloader | GRUB → vmlinuz + initramfs + cmdline | |
| | | kernel | init → mount rootfs → /sbin/init | |
| | | PID 1 | rc scripts or unit graph | |
| | | services | gettys, daemons, network, logging | |
| | | login | getty → login → shell | |
| | |
| | ## See also |
| | |
| | - [[Linux]] · [[LFS Kernel and Boot]] · [[Processes]] · [[Filesystem]] |
| | |
| | [[Category:Linux]] |
| | [[Category:Handbook]] |
| | [[Category:Boot]] |
| + | [[Category:Linux Handbook]] |
| | |