Linux
Linux is, at its strictest, a kernel — the program that owns the machine. But nobody runs a kernel alone. What people call "Linux" is a distribution: the kernel plus a userland of tools, libraries, a shell, an init system, and a package manager, assembled by a project that made choices for you. This chapter is the handbook's map: what Linux is, where it came from, how a running system is actually structured, and the plan for the journey ahead — which ends, if you take it, with you building a complete Linux system from source code with your own hands.
Part 1 — What Linux actually is
The kernel
The word kernel refers to the single program that runs in privileged mode — kernel space — and mediates everything. When you press a key, open a file, start a program, or send a packet, the kernel is involved. Its jobs are exactly five:
- Processes — it decides which running program gets the CPU next (scheduling), creates processes, and destroys them.
- Memory — it hands out memory, enforces that no process can touch another's, and conjures virtual memory so each program sees a private address space.
- Devices — it contains the drivers that talk to disks, keyboards, network cards, screens.
- Filesystems — it turns raw block devices into the tree of files and directories you navigate.
- The interface — it defines the system calls: the fixed set of requests (
open,read,write,fork,exec,socket, ...) through which every program asks it for anything.
That last point is the whole architecture: programs never touch hardware directly. A program lives in user space and can only ask the kernel, through syscalls. The syscall boundary is the contract — and Linux's contract is POSIX-shaped, inherited from Unix.
The userland
A kernel alone does nothing you can see. Around it sits the userland:
- libc — almost always glibc, the C standard library: the actual code behind
printf,malloc, and the syscall wrappers. Musl libc is the lean alternative found in Alpine and tiny systems. - Core utilities —
ls,cp,mv,cat,grep,sh. On most systems these are GNU coreutils; on minimal systems, BusyBox implements them all in a single binary. - The shell —
sh, and usuallybash: the program that reads your commands, runs programs, and glues utilities together with pipes. - Init — PID 1, the first userspace process the kernel starts; everything else descends from it. SysV init (Slackware/Slint's style) and systemd are the two living approaches.
- Everything else — editors, compilers, servers, desktop environments.
The distribution
A distribution (distro) is a packaging of all this: kernel + userland + an installer + a package manager that keeps software installable and updatable. Debian, Fedora, Arch, Slackware, Gentoo, Alpine — same kernel, different choices. Slackware (1993) is the oldest surviving distro and keeps the traditional, hand-editable Unix feel; its derivative Slint is the accessible variant built for blind users. We will use Slackware/Slint as this handbook's featured system because it is the closest thing on a shelf to what LFS produces — no systemd, BSD-style init scripts, software you can see.
GNU/Linux
Purists — and they have a point — say "GNU/Linux." The kernel is Linux; most of the tools wrapped around it (the shell, the compiler, the C library, coreutils) come from the GNU Project, launched by Richard Stallman in 1983 to build a complete free Unix. By 1991 GNU had everything except a working kernel — when Linus Torvalds's kernel appeared, the two fit together like parts of a whole they'd both been building toward. The result is GNU tools on a Linux kernel; the name credit is contested, but the debt is real.
Part 2 — Where it came from
Unix: the ancestor (1969)
Unix's own ancestor was Multics — the enormous, ambitious time-sharing system Bell Labs helped build in the mid-1960s. When Bell pulled out of the project in 1969, Ken Thompson was left with experience, ideas, and a spare PDP-7 — and wrote a deliberately small multi-user operating system: everything Multics wasn't, the beginnings of Unix. Dennis Ritchie joined him, and in 1972–73 they rewrote the system in C, Ritchie's new language — a decision that changed computing: an OS written in a portable high-level language could move to new machines by recompiling, not rewriting. Unix's ideas — processes, a hierarchical filesystem, devices-as-files, pipes, small tools joined by streams — became the permanent architecture of serious computing.
The pipe itself has a birthday: Doug McIlroy spent years lobbying Thompson for the mechanism to join programs — and in one night in 1973 Thompson implemented |. The next morning, McIlroy wrote, "was the night everything changed." The same McIlroy wrote the philosophy this handbook keeps quoting.
AT&T could not sell software (a 1956 consent decree barred it from the computer business), so Unix spread to universities nearly free — including BSD at Berkeley, which added TCP/IP and became a parallel lineage. When AT&T was broken up in 1984 it could finally sell Unix — and it locked it down. The free-software response was already underway.
Unix grows up, and gets locked down (1970s–84)
Through the 1970s Unix spread on nearly free tapes to universities — and mutated at Berkeley into BSD (Berkeley Software Distribution), which added the pager, vi, the C shell, and TCP/IP networking. Two lineages now existed: AT&T's System V and BSD, and their friction — the "Unix wars" — kept the 1980s fragmented into vendor flavors: SunOS, AIX, HP-UX, Ultrix. POSIX (1988) emerged to standardize the mess — the specification Linux later conformed to without being certified against.
GNU and the missing kernel (1983)
In 1983 Richard Stallman announced the GNU Project: recreate Unix, entirely free. By 1990 GNU had produced an editor (Emacs), a compiler (GCC), a debugger (GDB), the shell (bash), the core utilities, a C library — everything except its kernel, Hurd, which pursued a microkernel design that took years and never landed production-ready. GNU was a bakery with every ingredient but the oven.
MINIX — the classroom that lit the fuse (1987)
Andrew Tanenbaum's MINIX (1987) was a teaching kernel — 12,000 lines, microkernel architecture, deliberately non-commercial, distributed with his Operating Systems: Design and Implementation. It ran on the 386 PCs students could afford, its source was book-legible, and its newsgroup — comp.os.minix — became the world's amateur kernel laboratory. But its teaching license forbade redistribution of modified versions, and Tanenbaum refused features that would complicate the pedagogy. The students wanted a real OS. One of them was Linus Torvalds.
Linux: the hobby that won (1991)
In 1991 a 21-year-old University of Helsinki student, Linus Torvalds, owned a 386 PC and wanted something better than MINIX — Andrew Tanenbaum's teaching kernel, deliberately small and non-commercial. Torvalds began writing his own kernel as a hobby and, on 25 August 1991, posted the famous Usenet announcement:
Version 0.01 followed on 17 September 1991 — 10,239 lines, dumped to ftp.funet.fi, the FTP server Ari Lemmke ran, in a directory Lemmke named "linux" over Torvalds's preferred "Freax." By version 0.10 in November the kernel could self-host — compile itself on itself, the milestone every system software dreams of — and by 0.95 (March 1992) it ran the X Window System. It grew with terrifying speed as contributors arrived on the mailing lists. In 1992 Torvalds relicensed it under the GPL, the decision that made Linux belong to everyone: anyone may read the source, modify it, and redistribute — but derivatives must carry the same freedom. The same year brought the era's great engineering argument — the Tanenbaum–Torvalds debate: MINIX's creator called monolithic kernels a "giant step back into the 1970s"; the 22-year-old answered that practical working code beats theoretical purity. Version 1.0 came in March 1994.
The early contributors became the field's nobility — Ted Ts'o (first North American contributor; ext2/ext3/ext4 filesystems), Alan Cox (networking, 2.x-era co-maintainer), Ingo Molnár (scheduler), David Miller (networking), Greg Kroah-Hartman (drivers, stable trees, USB) — and hundreds more rising through patches, not credentials.
The development model that grew around it is itself historic: thousands of contributors on the Linux Kernel Mailing List, subsystem maintainers acting as reviewers, patch submission by email, releases every ~9–10 weeks, stable trees backporting fixes for years (LTS kernels). When BitKeeper — the proprietary version-control system kernel devs used — revoked free use in 2005, Torvalds wrote git in weeks; the tool built to manage kernel patches now manages the world's software. The kernel is tens of millions of lines, and Torvalds still shepherds releases decades later. In 1996 Larry Ewing's penguin Tux became the mascot — Torvalds reportedly chose penguins after being bitten by one at a Canberra zoo.
How the kernel is made — and numbered
Kernel versions tell a story of discipline. The 1.x era (1994–96) made it credible; 2.x (1996–2003) added SMP multiprocessing and loadable modules as first-class citizens; 2.6 (2003–2011) lasted eight years and carried Linux into the data center. Since 3.0 (2011) the major number just rolls forward on a cadence — 4.x, 5.x, 6.x — each release roughly nine weeks, each ~12,000 commits from ~1,500 developers. Stable/LTS trees keep selected releases patched for years; distro kernels are these trees plus the distro's own patch set. Nobody forks "a Linux" — everyone shares one tree, which is why a router and a supercomputer run the same code.
The lawsuit that cleared the runway (1992–94)
The free Unix world nearly died in court: AT&T's Unix System Laboratories sued BSDi and UC Berkeley in 1992 over the BSD source, claiming copied code. The case collapsed when it emerged AT&T itself had stripped copyrights from BSD code — settled 1994, with 4.4BSD-Lite released clean. Had it gone the other way, Linux — a clean-room reimplementation sharing no AT&T code — would still have stood. The legal shadow is exactly why "not Unix, but Unix-shaped" became permanent doctrine.
The distributions arrive (1993–)
Distributions appeared immediately — SLS (Softlanding), then Slackware in July 1993 (Patrick Volkerding's cleanup of SLS — still maintained by him today, the oldest surviving distro), Debian in August 1993 (Ian Murdock's manifesto for a community-built, openly-developed system — Debian's Social Contract and Free Software Guidelines became the definition of open source), and Red Hat the same year. Each distro is a theory about what a system should be: Debian's constitution, Slackware's refusal to change what works, Red Hat's enterprise polish, Arch's rolling minimalism, Gentoo's build-everything-from-source doctrine (the nearest retail relative of LFS).
Growing up corporate (1998–2005)
The late 1990s industrialized the hobby: 1998 saw **Eric Raymond's The Cathedral and the Bazaar articulate the bazaar development model — and the coining of "open source" as the business-friendly term for free software (the same year Netscape freed Mozilla). IBM announced a $1 billion Linux commitment in 2000; Oracle and SAP ported in; OSDL formed in 2000 to fund kernel work (Torvalds became its employee); the Linux Foundation (2007, OSDL+FSG merged) institutionalized stewardship. The schism the naming caused never healed — free software (Stallman's moral frame) vs open source** (ESR's pragmatic frame) — but the artifact itself was uncontestable by then.
What it conquered
- Servers — the web runs on Linux. Most of the internet's infrastructure, nearly all cloud instances.
- Supercomputers — every machine on the TOP500 list runs Linux. All of them.
- Phones — Android is a Linux kernel under a very different userland — the most-deployed Linux in existence.
- Embedded — routers, TVs, cars, Mars helicopters, stock exchanges, the International Space Station.
- Desktops — the one arena where it stayed a minority; yet the desktop is where the learning lives.
Part 3 — The anatomy of a running system
Boot a Linux machine and a precise sequence unfolds: firmware (BIOS/UEFI) → bootloader → kernel → init (PID 1) → services → login. Understanding that chain is understanding the whole OS.
The kernel's innards
Linux is a monolithic kernel — scheduler, memory manager, filesystems, and drivers all run in kernel space in one address space (contrasted with microkernels like MINIX/Hurd, which push services into user space — the famous 1992 Tanenbaum–Torvalds debate). Its major organs:
- The scheduler — time-slices runnable processes across CPUs. The Completely Fair Scheduler models an ideal multitasking CPU and gives each task its fair share of nanoseconds;
nice/reniceshift a process's weight (-20 hungriest … +19 politest).chrttouches real-time classes;tasksetpins to cores. - Memory management — each process gets a private virtual address space; pages materialize on first touch (demand paging); the page cache turns spare RAM into disk speed (watch
free -h— "available," not "free," is what matters); swap spills cold pages to disk; and when memory truly runs out the OOM killer chooses a victim by score (/proc/<pid>/oom_score).vmstatandtopwatch the whole economy live. - VFS — the Virtual Filesystem Switch: a uniform file API layered over ext4 (the standard), XFS (huge files), Btrfs (snapshots/checksums), tmpfs (RAM-backed), NFS (network), and dozens more — plus the pseudo-filesystems
/proc,/sys,devtmpfsthat aren't storage at all. It is the reason "everything is a file" works. - Drivers — loadable kernel modules (
*.ko);lsmodlists them,modprobeloads them with dependencies,modinfoinspects them,/lib/modules/<kernel>/stores them. Many devices also need firmware — binary blobs the driver uploads to the hardware itself, living in/lib/firmware/— the one place closed binaries still hide in the open stack. udev (or Slackware's eudev) populates/devdynamically as hardware appears — plug in a USB stick and the kernel emits an event; udev creates/dev/sdb1in response.udevadminterrogates it. - The syscall table — ~450 numbered entry points;
man 2documents them. The core vocabulary a programmer lives on:
| Call | Asks the kernel to | |
|---|---|---|
open/read/write/close | File I/O — over files, devices, sockets alike | |
fork/execve/wait/exit | Birth, transform, reap, die — the process lifecycle | |
mmap/brk | Memory mapping and heap growth | |
socket/bind/listen/accept/connect | Networking | |
pipe/dup2 | The streams behind `\ | ` |
stat/fstat | Metadata — what ls -l reads | |
chmod/chown | Permission changes | |
kill | Signal delivery | |
ioctl | Device-specific everything-else |
strace shows a program's syscalls live — watching one is a revelation:
$ strace -c ls /tmp
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
28.57 0.000016 2 7 openat
23.21 0.000013 1 9 close
...
Every openat, read, write — the program's whole conversation with the kernel, laid bare.
The initramfs — the kernel's pocket toolkit
Between kernel and real root sits the initramfs — a cpio archive the bootloader loads beside the kernel, unpacked into RAM, containing just enough drivers and tools (mount, udev, maybe an encrypted-root unlocker) to reach the real filesystem. mkinitcpio/dracut/mkinitrd build it; lsinitramfs lists its contents; GRUB's initrd line names it. When a kernel can't find its root disk — "unable to mount root fs" — the initramfs is the suspect: no driver for the controller inside it.
The boot sequence, step by step
From power to prompt, every Linux machine walks the same road:
- Firmware — BIOS or UEFI runs POST and finds a bootable device.
- Bootloader — GRUB (nearly universal) or LILO (Slackware's classic) loads the kernel image and
initramfs— a tiny temporary root filesystem carrying just enough drivers to reach the real root. GRUB reads/boot/grub/grub.cfg— a generated menu of kernel+initrd+root-device triples;grub-installwrites it to the disk's boot sector;grub-mkconfigregenerates it; pressingeat the menu edits a boot entry live — the rescue skill that has saved more systems than any backup.kernel /vmlinuz root=/dev/sda1 rois the whole contract: which kernel, which root filesystem, mounted read-only until init remounts it. - Kernel init — decompresses, probes hardware, mounts initramfs, then pivots to the real root filesystem.
- PID 1 — the kernel execs
/sbin/init(orinit=override, or the initramfs's init whichswitch_roots to the real one). Everything after this is userspace. - Service startup — init runs its startup path: filesystems mounted per
/etc/fstab, daemons launched, runlevel reached. - Login — getty spawns on consoles; you sign in; your shell starts.
You'll rebuild every step by hand in the LFS chapters — the boot sequence stops being abstract when you've configured GRUB yourself.
PID 1 and the boot chain
The kernel's last act of boot is starting init as PID 1. Everything else — login services, network, cron — is init's descendant. Two philosophies compete:
- SysV / BSD-style init (Slackware, Slint, the classic LFS book):
initreads/etc/inittab, walks runlevels — 0 halt, 1 single-user rescue, 3 multi-user console, 4 X11, 6 reboot — and runs shell scripts in/etc/rc.d/.telinit 3changes level. Transparent — services are just scripts you can read. - systemd (Debian, Fedora, Arch, Ubuntu): a modern service manager replacing the script pile with declarative units —
systemctl start sshd,systemctl enable --now,systemctl status; parallel startup, dependency graphs,journaldlogging, socket activation, timers replacing cron. Vastly more capable; vastlier criticized for swallowing more of the system — PID 1, logging, cron, device naming, resolved DNS, boot management.
This handbook teaches concepts first — PID 1, runlevels/targets, service management — then both implementations, because an LFS build can go either way and Slackware/Slint's SysV flow makes the machinery visible in a way systemd deliberately hides. The init debate is the one live culture war in Linux; the chapters give you both sides' working fluency.
SysV internals — the script path
A SysV boot is a cascade of readable shell scripts: /etc/inittab maps runlevels to actions; /etc/rc.d/rc.sysvinit → rc.M (multi-user setup) → rc.S (system init) run services in order; each service is its own script taking start|stop|restart — sh /etc/rc.d/rc.sshd start. Runlevels switch with telinit; /etc/rc.d/rc.local holds your own last-stage commands. Every piece is a file you can cat — that's the pedagogy.
systemd internals — units and targets
systemd thinks in units — typed objects (.service, .socket, .timer, .mount) declared in /etc/systemd/system and /usr/lib/systemd/system — pulled up through dependencies toward targets (multi-user.target, graphical.target — the runlevel's descendants). systemctl status sshd shows state + recent log; systemctl enable --now starts and persists; systemctl list-dependencies draws the graph; journalctl -u sshd -b its logs since boot; systemd-analyze blame times startup. Faster, dependency-aware — and deliberately less readable than a shell script.
The filesystem tree
Unix puts everything in one tree rooted at /. The Filesystem Hierarchy Standard defines the landmarks:
| Directory | Holds |
|---|---|
/bin /sbin | Essential commands; system commands (merged into /usr on modern systems) |
/etc | Configuration — plain text files, all of it |
/home | Users' directories |
/usr | The bulk of the system: programs, libraries, docs |
/var | Variable data: logs, spools, caches |
/dev | Device files — disks, terminals, /dev/null |
/proc /sys | Virtual filesystems — kernel internals exposed as files |
/tmp | Scratch space |
/boot | The kernel image and bootloader files |
/mnt /media | Mount points for other filesystems |
/root | root's home — not /home/root |
The deep rule: everything is a file. Disks appear as /dev/sda; terminals as /dev/tty; the kernel's process table as /proc/<pid>/; randomness itself as /dev/urandom. One interface — open, read, write — covers hardware, data, and the kernel's own guts.
Filesystems earn a second look because they carry the machine's soul: journaling (ext4/XFS/Btrfs all journal metadata — a crash mid-write replays the journal instead of corrupting the tree), copy-on-write (Btrfs/ZFS write new blocks and flip pointers — snapshots become free), and fsck — the checker run at boot when a filesystem wasn't cleanly unmounted (fsck.ext4 /dev/sda1 on an unmounted volume only).
Two more filesystem ideas underpin everything:
- Inodes and links — a filename is just a directory entry pointing at an inode, the real file object.
lnmakes a hard link (a second name for the same inode — delete one name, the data lives while links remain);ln -smakes a symbolic link (a file containing a path — dangling if the target dies).ls -ishows inode numbers;df -icounts them;readlink -fresolves chains;statdumps the inode's whole record — including its three timestamps:mtime(content changed),ctime(metadata/inode changed),atime(last read). - Mounts — other filesystems graft onto the tree at mount points:
mount /dev/sdb1 /mnt/usb.mountalone lists the current tree;/etc/fstabpersists it;df -hshows what's mounted and how full.
Programs, libraries, and the ELF
A compiled program on Linux is an ELF file — Executable and Linkable Format: headers, the code, the data, and the list of shared libraries it needs. file /bin/ls reports ELF 64-bit LSB pie executable; ldd /bin/ls lists the shared libraries it loads — libc.so.6 almost always among them; readelf -h dissects the headers; nm/objdump/strings look inside.
Shared libraries (*.so) load once and serve every program that needs them — the opposite of static linking, which copies the library into each binary. The dynamic linker ld.so resolves them at startup through LD_LIBRARY_PATH and /etc/ld.so.conf; ldconfig rebuilds the cache. When a program says cannot open shared object file, this machinery — not the program — is what's confused. The C Toolchain chapter builds all of this by hand.
Namespaces, cgroups, and why containers aren't magic
Two kernel features created the entire container world:
- Namespaces partition what a process can see — mount, network, PID, user, IPC namespaces let a process believe it owns its own filesystem, its own network stack, its own process tree.
- cgroups bound what a process can use — CPU shares, memory ceilings, I/O bandwidth, enforced by the kernel.
A "container" is nothing more exotic than an ordinary Linux process confined by namespaces and metered by cgroups — Docker and podman are elaborate wrappings around clone() flags. When you reach them, you'll already own the pieces.
The kernel command line — boot parameters
The bootloader hands the kernel a command line — vmlinuz root=/dev/sda1 ro quiet — read at boot, visible afterward in /proc/cmdline. root= names the root filesystem; ro/rw mount it initially read-only or writable; quiet/loglevel=N control boot chatter; init= overrides PID 1 (init=/bin/sh — the classic rescue that drops you into a root shell on a broken system); single/1 boots single-user. The parameters are the kernel's only user input before init runs — and editing them from GRUB's e menu is rescue skill #1.
The kernel's configuration — menuconfig primer
Before compiling, the kernel must be configured — ~20,000 CONFIG_* options choosing drivers, filesystems, and features for your hardware. make defconfig uses your arch's sane defaults; make menuconfig opens the curses menu — / searches options, ? explains each, /space toggles built-in vs module vs off. The output is a .config file — thousands of CONFIG_X=y/m/#not set lines — that the build reads and LFS III walks through properly. make localmodconfig trims to your currently loaded* modules — the shortcut that makes a first kernel build survivable.
The kernel source — you can read it
git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git — or a tarball from kernel.org — drops the entire kernel on your disk. The tree's layout is a map of the subsystem story above: kernel/ scheduler and core, mm/ memory, fs/ the VFS and filesystems, drivers/ the hardware zoo, net/ the stack, arch/ per-CPU code, include/ headers, Documentation/ thousands of pages. drivers/accessibility/speakup/ is in there — the kernel screen reader from our Speakup article.
Building it, in preview: make defconfig (or menuconfig for the curses menu where you choose drivers and features), make -j$(nproc), make modules_install, make install. LFS III walks it properly; for now, know that the operating system you run is a directory of C you can browse, patch, and compile. git log, git blame — the entire history, every commit message, back to 2005.
Reading a live system — /proc and friends
/proc is the kernel wearing its own organs as a filesystem — files that don't exist on disk, generated live when read:
$ cat /proc/cpuinfo # the CPU, in exhaustive detail
$ cat /proc/meminfo # memory accounting
$ cat /proc/uptime # seconds up
$ cat /proc/version # kernel version + compiler that built it
$ ls /proc/1/ # init's own directory
$ cat /proc/self/status # the reader, reading itself
/sys exposes devices and drivers; dmesg shows the kernel's boot ring buffer — the first place to look when hardware misbehaves. Logs live in /var/log/ on SysV systems (syslog, messages, auth) — syslog protocols split messages by facility (auth, kern, mail…) and severity (debug → emerg); logger writes your own. On systemd systems, journalctl queries the journal (journalctl -b = this boot, -u sshd = one service, -p err = errors only, -f = follow). logrotate keeps logs from eating the disk. Learning to read a system — cpuinfo, mounts, logs — is how you stop guessing.
Users, groups, permissions
Every file carries an owner, a group, and a mode — nine permission bits in three triads: read/write/execute for owner, group, others.
$ ls -l /etc/fstab
-rw-r--r-- 1 root root 541 Feb 3 10:22 /etc/fstab
# │└─┴─┴──┘
# │ └──────── others: r-- (read only)
# │ group: r-- (read only)
# └─ owner root: rw- (read+write)
The octal shorthand: r=4, w=2, x=1 — so 644 is owner rw, group r, others r; 755 adds execute everywhere; 600 is owner-only. chmod 755 file and chmod u+x file are the two dialects of the same change. Three special bits extend the model: setuid (run as the file's owner — how passwd lets you edit root-owned /etc/shadow), setgid, and the sticky bit on /tmp (anyone writes, only owners delete).
root — uid 0 — bypasses all of it, which is why you use sudo/su sparingly and never live as root. Users and groups live in /etc/passwd and /etc/group — real text files, readable, that the system actually consults; /etc/shadow holds the password hashes, readable only by root.
umask is the other half of the story — the mask removed from new files' default permissions: umask 022 yields 644 files and 755 directories (666/777 minus the mask); umask 077 makes everything private. It lives per-shell — umask prints yours.
Sessions and the controlling terminal
A session is a login's whole process family — your shell and everything it spawned, sharing a controlling terminal. Log out and the session leader dies; children get SIGHUP — the hangup nohup and tmux exist to defeat. setsid births detached sessions; ps -o sid= reveals the grouping. It's the plumbing under job control — and under why your SSH session's processes die when the connection does.
How a command actually runs
Type ls /tmp and an entire machinery fires in sequence: the shell reads your line, performs expansions (globs, $vars, $(...)), splits it into words, searches $PATH for an executable named ls, fork()s a child copy of itself, and the child exec()s /usr/bin/ls — the kernel's ELF loader maps the program, the dynamic linker resolves its shared libraries, main() runs, ls opens the directory via syscalls, prints to stdout, and exit()s — whereupon the parent wait()s, collects the exit code into $?, and prints you another prompt. Every command — every one — is fork+exec+syscalls+exit. The shell is just the user interface to the kernel's process machinery.
Virtual consoles — six terminals in one box
Linux machines ship with multiple virtual consoles — Ctrl-Alt-F1 through Ctrl-Alt-F6 (F7+ is traditionally the graphical session). Each is an independent login — on the same keyboard. When X freezes, Ctrl-Alt-F3 is the escape hatch to a live text console where you can kill the offender and return. chvt switches programmatically; tty tells you which you're on. Rescue shells, single-user mode, and getty all live on these — on Slackware/Slint you'll meet them constantly.
Nice, limits, and the resource economy
nice -n 10 cmd launches politely; renice +5 -p <pid> adjusts live. ulimit caps a session's resources — ulimit -a shows max open files, stack size, core dump enablement; /etc/security/limits.conf persists per-user bounds. ulimit -c unlimited enables core dumps — the crash artifacts gdb dissects. cgroups (met above) are the kernel-level quota system systemd applies to every service — systemd-cgtop watches them live. The economy is layered: scheduler shares CPU, mm bounds memory, cgroups meter everything.
Processes
A process is a running program: pid, owner, memory, open files. New processes are born by fork+exec — a parent fork()s a copy of itself, then the child exec()s a new program over that copy. Your shell does this for every command you type — which is why bash → ls is literally bash forking and execing ls.
ps aux lists processes; top/htop watch them live; kill sends signals — SIGTERM (polite exit, 15) or SIGKILL (uncatchable termination, 9), plus SIGHUP (terminal hangup — the reason nohup and tmux exist). Job control: Ctrl-Z suspends, bg resumes in background, fg returns to foreground, & launches backgrounded, jobs lists them. Every process except init has a parent — pstree draws the family — and every one is visible as a directory under /proc/<pid>/: cmdline, status, fd/ open files. A zombie is a dead process whose parent hasn't collected its exit code yet — harmless, occasionally diagnostic.
Part 4 — Using it: the practical ramp
Getting a system
Four doors in, ordered by commitment:
- Live USB — write an ISO to a stick (
dd, Rufus, Ventoy), boot a full Linux without touching the disk. The zero-risk way in. - Virtual machine — VirtualBox/QEMU/GNOME Boxes; Linux inside a window on your current OS. The standard laboratory, and this handbook's recommended LFS host — snapshots let you undo anything.
- WSL — Windows Subsystem for Linux puts a real Linux kernel-translation layer inside Windows; ideal for learning tools, though it skips the boot/hardware layers LFS teaches.
- Bare metal — dedicated partition or machine. Where Slackware/Slint's installer shines; the fullest experience, with real consequences.
Choosing your featured install: we use Slackware or Slint — Slackware for the classic path, Slint if you want speech from the first installer prompt. The installer is text-mode, honest, and asks you real questions: partition layout, packages, LILO/GRUB, network, root password — every question a lesson.
First commands
$ whoami # who you are
$ pwd # where you are
$ ls # what's here
$ ls -la # everything, long format
$ cd /etc # move
$ cd # (no args = home)
$ cat fstab # read a file
$ less fstab # read it page by page — q quits
$ man ls # the manual — always the manual
$ mkdir test && cd test
$ echo hello > f.txt && cat f.txt
$ rm f.txt && cd .. && rmdir test
The shell — sh, and its big brother bash — is the interface. Commands are programs found in $PATH, the colon-separated directory list the shell searches (echo $PATH; which ls shows where ls lives). Arguments follow the command; -x and --long-flag modify behavior. POSIX sh is the portable baseline every system guarantees; bash adds conveniences (arrays, [[ ]], better history) that are everywhere but not guaranteed — this handbook writes scripts in POSIX sh and flags bash-isms where they appear.
The shell's own anatomy — builtins vs programs
Not everything you type is a program: cd, echo (often), export, alias, read, test/[, kill, umask, jobs are shell builtins — code inside sh itself, because no external program could do the job (cd must change the shell's directory; a child process couldn't). type cmd reveals which is which; help lists builtins; enable -n disables one. External commands live in $PATH directories; builtins need no fork+exec at all — one reason echo is instant. The boundary trips scripts: [/test exist both as builtin and as /usr/bin/[ — literally an executable file named [.
The startup files — where your shell gets its personality
Login shells read /etc/profile then ~/.profile (or bash's ~/.bash_profile); interactive non-login shells read ~/.bashrc. This is where PATH gets extended (export PATH="$HOME/bin:$PATH"), aliases live (alias ll='ls -la'), the prompt is shaped (PS1), and environment variables are exported. The separation trips every beginner: add something to .bashrc and a cron job won't see it — cron isn't interactive. ~/.inputrc tunes readline — the line-editing library behind every bash prompt.
Reading files properly — less, and the pager craft
cat dumps; less is the reader — /pattern searches, n/N next/prev, g/G top/bottom, F follows like tail -f, -N numbers lines, q quits. less is what man itself uses. head -n20/tail -n20/tail -f are the quick edges — tail -f /var/log/syslog is the standard live-log watch. wc -lwc counts lines/words/chars; nl numbers lines; od/xxd/hexdump drop to raw bytes when text tools mislead.
Dotfiles and the hidden half of your home
ls alone hides the interesting half: filenames starting . are invisible without -a. Your home directory is a working archive — .bashrc/.profile your shell's startup, .bash_history your command log, .ssh/ your keys, .config/ the modern XDG config root, .local/ your private installs. The convention is pure mechanism — the tools hide them, nothing forbids them — and ls -la ~ is the honest census of your own environment.
Finding things — find, and the file-toolkit grammar
find is the filesystem's query language — predicates joined by logic:
$ find /etc -name '*.conf' # by name (glob)
$ find . -type f -mtime -7 -size +1M # files, changed this week, over 1MB
$ find . -perm -u+x -type f # executable files
$ find /var -user root -o -group adm # owner or group logic
$ find . -name '*.tmp' -delete # act on results — carefully
$ find . -type f -exec file {} \; # run a command per result
$ find . -name '*.c' | xargs grep -l 'main' # feed results into other tools
Companions: locate queries a pre-built filename database (instant, possibly stale); which/type/command -v locate commands in $PATH; whereis finds binaries+sources+manpages. file identifies contents by magic bytes, not extension — file mystery.bin tells you what a thing is, which on Linux is a property of its bytes, not its name.
The /etc tour — where the system is configured
/etc is the system's readable memory — every answer to "where is X configured" starts here:
| File | Configures |
|---|---|
/etc/passwd, /etc/group, /etc/shadow | Users, groups, password hashes |
/etc/fstab | Filesystems mounted at boot |
/etc/hostname, /etc/hosts, /etc/resolv.conf | Name, local names, DNS servers |
/etc/profile, /etc/skel/ | Login environment; new-user template |
/etc/ssh/sshd_config | The SSH daemon |
/etc/inittab, /etc/rc.d/ | SysV init and its scripts |
/etc/systemd/ | systemd's units and overrides |
/etc/os-release | Which distro this is |
/etc/sudoers | Who may sudo (edit with visudo — always) |
/etc/crontab, cron dirs | Scheduled jobs |
Environment, globs, and quoting
Three mechanisms the shell performs before your command runs — the source of most beginner confusion:
- Environment variables —
NAME=valuesets;export NAMEpasses to children;$NAMEexpands.HOME,PATH,USER,SHELL,TERM,EDITORsteer everything.envdumps them all.PATHdeserves the deep look: a colon-separated directory list searched left-to-right for every unqualified command —echo $PATH,which ls,type -a python(all the pythons).export PATH="$HOME/bin:$PATH"prepends your own bin; order matters — first match wins, which is how tools get shadowed and why.(current directory) should never be in it. - Globbing —
any string,?one char,[abc]a class:ls .c,rm tmp?.log. The shell expands them —lsnever sees the*. - Quoting —
'single'is literal (nothing expands);"double"allows$VARand command substitution;\escapes one char.rm 'file with space.txt'works; unquoted, it deletes three files' worth of trouble.
Pipes and redirection — the superpower
Unix's founding trick: programs read stdin and write stdout and stderr — three streams. Redirect them:
$ ls > files.txt # stdout to file
$ grep error log.txt > errs # filter into file
$ cat a b | sort | uniq -c # the pipeline: output of each feeds the next
$ find / -name '*.conf' 2>/dev/null # stderr to the void
The pipeline is the Unix philosophy executed: each tool does one thing; the stream joins them; composition beats monoliths. grep | sort | uniq -c | sort -rn | head — filtering, counting, ranking in one line — is the grammar of all real command-line work.
The redirection grammar, complete:
| Form | Meaning | |
|---|---|---|
cmd > f | stdout overwrites f | |
cmd >> f | stdout appends to f | |
cmd < f | stdin reads f | |
cmd 2> f | stderr to f — 2>/dev/null discards | |
cmd > f 2>&1 | stdout and stderr both to f | |
| `cmd \ | cmd2` | stdout feeds cmd2's stdin |
| `cmd \ | tee f` | stdout both displayed and saved |
cmd <<'EOF' | heredoc — inline input until EOF | |
cmd <<< "text" | here-string — one line of input |
$ who | awk '{print $1}' | sort | uniq -c # logged-in users by session count
$ grep -rl 'TODO' src/ | xargs wc -l # line counts of every file containing TODO
$ ps aux | grep '[f]irefox' # the bracket trick: grep won't match itself
$ tar czf backup.tar.gz project/ # archive in one move
$ find . -name '*.c' -mtime -7 # C files changed this week
$ dd if=/dev/sda of=disk.img bs=4M status=progress # image a whole disk — carefully
The core toolkit — a map
The chapters ahead treat each properly; for orientation:
- Files:
ls cp mv rm mkdir rmdir ln chmod chown touch file stat - Text:
cat head tail less grep sed awk cut tr sort uniq wc diff - Search:
find xargs locate which whereis - System:
ps top kill free df du mount umount uname dmesg - Network:
ping ssh scp curl wget ip ss - Archive:
tar gzip bzip2 xz - Shell itself:
echo printf test read export alias history type
The complete reference lives in the Core Utilities chapter; grep/sed/awk get their own — they are languages.
Discovering your hardware
$ uname -a # kernel, hostname, arch, build date
$ lscpu # CPU topology: cores, threads, caches
$ lsblk # disks → partitions → mountpoints, as a tree
$ lspci # every PCI device: GPU, NIC, controllers
$ lsusb # USB roster
$ lsmod # loaded kernel modules
$ dmidecode -t memory # the RAM sticks themselves (as root)
$ free -h # memory, human-readable
$ df -h # filesystem space
$ cat /etc/os-release # which distro, exactly
A first session, annotated
Welcome to Slackware 15.0
darkstar login: alice
Password: ••••••••
alice@darkstar:~$ whoami
alice
alice@darkstar:~$ pwd
/home/alice
alice@darkstar:~$ ls -la
drwxr-x--- 5 alice users 4096 Feb 3 10:22 .
drwxr-xr-x 4 root root 4096 Feb 3 09:00 ..
-rw------- 1 alice users 812 Feb 3 10:20 .bash_history
-rw-r--r-- 1 alice users 220 Feb 3 09:00 .bashrc
alice@darkstar:~$ mkdir work && cd work
alice@darkstar:~/work$ echo "hello world" > first.txt
alice@darkstar:~/work$ cat first.txt
hello world
alice@darkstar:~/work$ wc -c first.txt
12 first.txt
alice@darkstar:~/work$ cat first.txt | tr a-z A-Z
HELLO WORLD
alice@darkstar:~/work$ cd /etc && ls | head -5
HOSTNAME
X11
acpi
aliases
bash_completion.d
alice@darkstar:/etc$ man ls
Read it as a story: log in as yourself, land in $HOME, make a directory, write a file, inspect it, transform it through a pipe, wander to /etc, consult the manual. Every habit of the next fifteen chapters is in that transcript already.
Text processing — the heart of the toolkit
A preview of the chapter that gets its own volume. Three tools, three grammars:
- grep — pattern matching:
grep -rn 'error' /var/log(recursive, line numbers);-icase-insensitive;-vinvert;-ccount;-Eextended regex;grep -rllists only filenames. - sed — stream editing:
sed 's/old/new/g'replaces;sed -n '10,20p'prints a range;sed '/^#/d'deletes comments;-iedits files in place. - awk — the column language:
awk '{print $1}'fields;awk -F: '{print $1}' /etc/passwdcustom separator;awk '$3 > 100'conditions;awk '{s+=$1} END{print s}'sums — a full programming language hiding in a command.
These three plus find/xargs/sort/uniq/cut/tr/wc/head/tail/diff/tee are the daily workbench — the Text Processing chapter treats them as the languages they are.
Networking — the tour
$ ip addr # interfaces and addresses (ifconfig's modern replacement)
$ ip route # the routing table
$ ping -c3 alb-lang.org # is it alive?
$ ss -tlnp # what's listening on which ports
$ ssh user@host # the remote shell — THE tool
$ scp file user@host:/tmp/ # copy over ssh
$ curl -I https://site # headers without the page
$ cat /etc/resolv.conf # where DNS lives; /etc/hosts the local overrides
/etc/hostname names the machine; /etc/hosts maps names before DNS; ports under 1024 are privileged. nmap interrogates networks; tcpdump/wireshark watch packets themselves. The Networking chapter goes deeper.
Shell fluency — history, completion, the keys
Interactive muscle memory that pays for itself daily: Ctrl-R reverse-searches history; !! repeats the last command; !grep repeats the last grep; !$ reuses its last argument; history lists (kept in ~/.bash_history). Tab-completion finishes filenames and commands — press it twice for choices. Ctrl-A/Ctrl-E jump line ends; Ctrl-W/Ctrl-U kill word/line; Ctrl-Y yanks them back; Ctrl-L clears; Ctrl-D ends input. alias shortcuts (alias ll='ls -la'); type cmd reports whether a name is an alias, function, builtin, or file.
Job control deep — the full lifecycle
vim f & launches backgrounded; jobs numbers them (%1, %2); fg %1 resumes in foreground; Ctrl-Z suspends (SIGTSTP); bg %1 resumes suspended work in background; kill %1 signals by job; disown frees a job from the shell entirely — it survives logout. nohup cmd & ignores hangup; tmux/screen are the full solution — entire sessions that outlive disconnection.
Exit codes and signals — the error vocabulary
Every command returns an exit status — 0 success, nonzero failure; echo $? reveals the last one. Scripts test it (if grep -q x file; then), &&/|| chain on it (make && make install), set -e aborts scripts on first failure. Signals are the interrupt vocabulary: Ctrl-C sends SIGINT (interrupt), Ctrl-Z SIGTSTP (suspend), Ctrl-\ SIGQUIT (quit with core dump), Ctrl-D sends EOF — not a signal, it ends input. trap lets scripts catch signals for cleanup. The two disciplines — check exit codes, trap signals — separate scripts that work from scripts that merely ran.
Shell scripting — the primer
A script is commands in a file, run by a shell. The grammar in one pass:
#!/bin/sh
# shebang: the kernel reads #! and execs /bin/sh on this file
name="world" # no spaces around =
echo "hello, $name" # ${name} braces when ambiguous
count=$(ls | wc -l) # $(...) command substitution
if [ -f /etc/fstab ]; then # [ is test(1) — a command, not syntax
echo "fstab exists"
elif [ -d /etc ]; then
echo "no fstab, but /etc"
else
echo "nothing"
fi
for f in *.txt; do # for over words/globs
echo "-> $f"
done
i=0
while [ $i -lt 5 ]; do # while with a test
i=$((i + 1)) # $((...)) arithmetic
done
greet() { echo "hi $1"; } # function; $1 first arg
greet alice
exit 0 # exit status: 0 = success
Every idiom: [ expr ] is test (strings =/!=/-z, numbers -eq/-lt/-gt, files -f/-d/-x); $? the last exit code; $#/$@/$1.. the arguments; set -e dies on first error; case switches on patterns. POSIX sh scripts run everywhere; #!/bin/bash scripts reach for arrays and [[ ]]. The Scripting chapter builds real programs from these atoms.
Documentation culture
man is the institution: man ls, man 2 open (syscalls), man 5 fstab (file formats). The page anatomy is itself a convention — NAME, SYNOPSIS, DESCRIPTION, OPTIONS, FILES, SEE ALSO — and the SYNOPSIS grammar is worth one sentence: [brackets] are optional, a|b alternatives, ... repeatable, CAPS or italics placeholders for your values. Reading man tar's synopsis fluently is half of knowing tar.
| Section | Contents |
|---|---|
| 1 | User commands |
| 2 | System calls |
| 3 | C library functions |
| 4 | Devices & special files |
| 5 | File formats (fstab, passwd…) |
| 6 | Games |
| 7 | Overviews & conventions |
| 8 | Admin commands |
man -k network searches descriptions; /pattern searches inside a page; q quits. info holds GNU's longer manuals; --help answers quickly; /usr/share/doc hides more. Learn man first and the system documents itself.
Finding help — the social infrastructure
man covers the system; humans cover the rest. The conventions: RTFM isn't dismissal — it's the community's first tool, and man -k/apropos find pages by keyword when you don't know the name. IRC (Libera.Chat) still hosts the old channels — #linux, #slackware, distro and project rooms. Forums — linuxquestions.org (LFS's home), distro boards, Stack Exchange's Unix & Linux. Mailing lists carry the deepest work — LKML for the kernel, each project's own list. The etiquette that gets answers: say what you ran, paste the exact error, state what you expected, show what you've already tried. Nobody in Linux culture minds beginners; everyone minds questions that ask others to debug blind.
The terminal itself
The text console is a terminal emulator — a program imitating hardware that died decades ago. The name survives: tty is literally teletype. Terminals speak escape sequences — in-band control codes that move the cursor, set colors, clear lines; TERM names your terminal type and terminfo (/usr/share/terminfo/infocmp) describes what codes it understands. tput queries capabilities portably; reset resuscitates a mangled screen. Readline — the library under bash's prompt — gives you Ctrl-A/Ctrl-E line ends, Ctrl-W/Ctrl-U word/line kills, Ctrl-R history search, !! the last command again. tty alone prints your terminal's device file; stty -a dumps its settings; Ctrl-S/Ctrl-Q still freeze and thaw output — a teletype-era handshake that survives into the 21st century.
Printing — the tradition that named lp
Printing survives as a subsystem worth naming once: CUPS owns it — lp file submits, lpstat -t queues, cancel retracts, /etc/cups/ configures, port 631 hosts a web UI. The tool names descend from actual line printers — lp, lpr — the same teletype-era naming that gave us tty.
A tour of a source tree
Before the toolchain chapter makes it routine, crack open any upstream tarball — the shape is always the same: README/INSTALL/COPYING at root, configure (generated by autoconf) probing the system, Makefile.in the template, src/ the code, doc/ documentation, ChangeLog the history, tests/ the suite. configure's output is a log of probes — "checking for gcc… checking whether gcc works… checking for stdio.h…" — building a config.h of #define HAVE_X 1 lines the code consults. make reads the Makefile's dependency graph and rebuilds only what changed — which is why the second make is instant. make check runs the tests; make distclean unwinds to pristine. The whole ritual — probe, build, test, install — is the grammar of every package LFS makes you run.
The graphical layer — X11, Wayland, desktops
Everything graphical sits on userland layers, none of it mandatory: the display server — X11 (1984, network-transparent, aging) or its replacement Wayland (modern, compositor-based, now default in Fedora/Ubuntu) — owns the screen and input. On it sit desktop environments: GNOME (the mainstream default), KDE Plasma (the maximalist), Xfce and LXQt (the lightweights), Cinnamon and MATE (the classicists). Below them, window managers — i3, sway, Openbox, dwm — drop the whole "environment" for pure tiling minimalism. A Linux system can run for years with no graphics at all — servers do — and this handbook's entire curriculum happens at the text console where the real system lives.
Comparing and patching — diff, patch, and friends
diff a.txt b.txt shows the delta; diff -u produces unified diffs — the @@ hunks that patch, git, and every code review on earth consume. diff -r compares directory trees — invaluable for seeing what a build changed. patch < fix.diff applies changes; patch -R reverts them. LFS arrives with patches — upstream tarballs plus correction files — and applying them is part of the ritual. cmp compares bytes; comm compares sorted line sets; od/hexdump/xxd dump raw bytes for when text tools fail.
Archives and compression
tar — tape archiver, and the format open source moves in — bundles trees into single files; compressors wrap them:
| Tool | Extension | Compress | Decompress |
|---|---|---|---|
| gzip | .gz | gzip f / tar czf a.tgz dir/ | gunzip / tar xzf |
| bzip2 | .bz2 | tar cjf | tar xjf |
| xz | .xz | tar cJf — best ratio, slower | tar xJf |
| zstd | .zst | tar --zstd — fast | tar --zstd |
The flags decode as create/xtract, z/j/J codec, file. tar tzf a.tgz lists without extracting. Kernel source, LFS tarballs, every upstream release — all arrive this way.
The file command's magic — how Linux knows what things are
No .exe needed: Linux identifies files by content. file mystery.bin reads the first bytes against /usr/share/misc/magic — a database of magic numbers: ELF's \x7fELF, PNG's \x89PNG, gzip's \x1f\x8b, scripts' #! shebangs, PDF's %PDF-. Executable means a permission bit plus a format the kernel understands — ELF binary, #! script, or binfmt_misc-registered exotic. chmod +x + #!/bin/sh makes a text file a program; the extension is decoration.
Text encodings — bytes versus characters
Linux speaks UTF-8 — ASCII's first 128 bytes unchanged, every other character encoded multi-byte. locale reports your encoding (en_US.UTF-8); LC_ALL=C forces byte-level C locale — the debugging incantation when sort/grep behave strangely on non-ASCII. iconv converts between encodings; file sniffs them. A filename is bytes; what it means is the locale's interpretation — the root of "my script works in C locale but not UTF-8" mysteries.
Time, locale, and identity
date reports and sets the clock; timedatectl manages NTP sync and timezones on systemd systems (TZ=UTC date overrides per-command); hwclock talks to the hardware clock — the RTC that ticks while the machine is off. Time zones live in /usr/share/zoneinfo, symlinked at /etc/localtime. Locales — LANG, LC_ALL, locale -a — control language, collation, and message languages; LC_ALL=C is the debugging incantation that forces traditional English/ASCII behavior when output parsing goes sideways. /etc/os-release answers "what distro"; hostnamectl/hostname the machine's name; id and who/w the people on it.
Administering users
useradd -m alice creates a user with a home; passwd alice sets the password; usermod -aG wheel alice adds a group; userdel -r removes both entry and home. id alice reports uid/gid/groups; groups too. su - becomes another user (with their environment); sudo cmd runs one elevated command — its permissions live in /etc/sudoers, edited only through visudo, which syntax-checks before saving (a broken sudoers locks everyone out). last replays logins; who/w the current population.
Special characters that bite
Shell metacharacters are the reason quoting exists: * ? [ ] { } glob/braces; $ variable expansion; ` ` and $( ) command substitution; | & ; && || > < flow; # comments; ~ home; \ escapes; whitespace itself splits words. file name.txt is two arguments; 'file name.txt' or file\ name.txt is one. ~alice is alice's home; {a,b}.txt expands to a.txt b.txt; Upper: is a character class. When a command "doesn't see" a file with a space or $` in its name, the shell parsed it first — the quoting chapter makes the rules muscle memory.
Working remote — ssh and the multiplexers
ssh is the remote shell and the spine of administered Linux: ssh user@host logs in; scp/rsync/sftp move files; keys in ~/.ssh/ replace passwords (ssh-keygen, ssh-copy-id). ssh -L tunnels ports; ~/.ssh/config names your fleet.
tmux (and its ancestor screen) keeps sessions alive across disconnects — detach, the session lives; reconnect, tmux attach resumes exactly where you left it. Panes split the terminal; windows multiply it. On flaky networks it's not optional.
cron schedules recurring jobs — lines in crontab -e like 30 3 * /usr/local/bin/backup (minute hour day month weekday). at schedules once. systemd timers are the newer mechanism; cron is older, simpler, and everywhere.
Watching the machine work — load, memory, I/O
uptime ends in three numbers — the load average: runnable+uninterruptible tasks averaged over 1, 5, 15 minutes. 2.00 on a 4-core box means half the CPU supply is busy; on a 1-core box it means a queue twice as long as the processor. top shows the live ranking — %CPU, %MEM, TIME+; htop the friendlier version; iotop/vmstat/sar watch disk and memory separately. dstat, mpstat, pidstat are the specialists. The reflex to build: machine slow → uptime → top → iotop → dmesg | tail.
The /dev zoo
| File | Is |
|---|---|
/dev/null | The void — writes vanish, reads return EOF. cmd > /dev/null silences. |
/dev/zero | Infinite zero bytes — dd it to wipe or allocate |
/dev/urandom | The entropy faucet — head -c16 /dev/urandom |
/dev/tty | Your own terminal |
/dev/sda, /dev/nvme0n1 | Whole disks; sda1 partitions |
/dev/stdin /dev/stdout | Your own streams, as files |
/dev/console | The system console — where boot messages go |
mknod creates device nodes by major:minor numbers — the kernel's device-table coordinates. You'll make a handful by hand inside the LFS chroot before udev takes over.
Disks and partitions — the ground floor
Block devices appear as files: /dev/sda (first SATA/SCSI disk), /dev/nvme0n1 (first NVMe), partitions as /dev/sda1, /dev/nvme0n1p1. The vocabulary:
$ lsblk # disks and partitions, drawn as a tree
$ fdisk -l /dev/sda # the partition table
$ df -h # mounted filesystems, human-readable space
$ du -sh /var # what a directory actually consumes
$ mkfs.ext4 /dev/sdb1 # make a filesystem — DESTRUCTIVE
$ mount /dev/sdb1 /mnt # graft it onto the tree
Partitioning divides a disk into regions the installer (or you, later) fills: typically / root, /boot, swap, /home. fdisk, gdisk, and cfdisk carve them; mkfs.* formats; mount/umount attach and detach; /etc/fstab makes mounts permanent; swap extends RAM onto disk. You'll partition by hand for LFS — it's one command away from destroying a disk, so learn it in a VM first.
Editors: vi survives everything
nano is friendly and present on most systems; vi is guaranteed — POSIX requires it, rescue systems and minimal installs have nothing else. vi is modal: it starts in command mode where keystrokes are commands, and i drops you into insert mode where keystrokes are text; Esc returns you. The survival kit:
| Key | Does |
|---|---|
i / a / o | Insert before cursor / after cursor / on new line |
Esc | Back to command mode |
:w :q :wq :q! | Write · quit · write+quit · quit discarding |
x dd yy p | Delete char · delete line · copy line · paste |
u / Ctrl-R | Undo / redo |
/text then n | Search; next match |
0 $ gg G | Line start · line end · file start · file end |
:set number | Show line numbers |
Ten keystrokes that work on every Unix ever made. Emacs is the other camp — vast, programmable, a lifestyle; vim (vimtutor is the built-in lesson) is vi's modern descendant. For this handbook: vi survival suffices until the Editors chapter.
Installing software
Each distro's package manager tracks software, dependencies, and updates. The concepts underneath are universal: a package is a program plus metadata (version, dependencies, file list, install scripts); a repository is a curated collection fetched over the network; dependency resolution pulls in what a package needs; signatures (GPG) verify packages came from the project, not an impostor. Binary distros ship precompiled packages; source distros ship recipes.
| Task | Debian/Ubuntu | Fedora/RHEL | Arch | Slackware/Slint |
|---|---|---|---|---|
| Refresh lists | apt update | dnf check-update | pacman -Sy | slackpkg update |
| Install | apt install x | dnf install x | pacman -S x | slackpkg install x |
| Upgrade all | apt upgrade | dnf upgrade | pacman -Syu | slackpkg upgrade-all |
| Remove | apt remove x | dnf remove x | pacman -R x | removepkg x |
| Search | apt search x | dnf search x | pacman -Ss x | slackpkg search x |
Slackware's pkgtools (installpkg/removepkg/upgradepkg) is famously hands-off — it installs what you give it and assumes you meant it; slackpkg adds network-fetch convenience. Gentoo's emerge compiles from source — the retail rehearsal for LFS.
Inside the formats: a .deb is an ar archive of tarballs (data + control metadata, visible with dpkg-deb -I); an .rpm the RPM equivalent (rpm -qip); a Slackware .tgz/.txz a compressed tar plus install scripts — installpkg just explodes it into / and runs the scripts. The package databases live in /var/lib/dpkg, /var/lib/rpm, /var/log/packages respectively — dpkg -L pkg/rpm -ql/cat /var/log/packages/x list exactly which files a package owns. A package manager is a librarian over tar files — and LFS is the training where you are the librarian.
Beneath every package manager lies the universal method this handbook teaches: download source → configure → compile → install. The package manager just automates what ./configure && make && make install does by hand — and Part II does it by hand until it stops feeling like magic.
Building from source — the preview
$ tar xf program-1.0.tar.xz
$ cd program-1.0
$ ./configure --prefix=/usr
$ make
# make install
Four steps that built nearly every open-source program for thirty years. configure probes your system — which compiler, which headers, which libraries — and writes a Makefile; make reads it and runs the compiler; make install copies results into the tree. The # prompt matters: install as root, build as yourself. --prefix=/usr decides where the program lands; make clean resets for a rebuild; ./configure --help lists every knob. When you reach LFS you will do this a hundred times — to build the system itself.
make itself deserves the peek ahead: a Makefile is targets and recipes — target: dependencies then a tab-indented command — and make rebuilds only what changed by comparing timestamps. make -j8 parallelizes across cores; make -n dry-runs. Autotools (configure+Makefile.in), CMake, and Meson are the three build systems you'll meet; all end at the same place — compiler invocations you could have typed.
And beneath make sits the compiler. The smallest possible C program and its journey:
$ cat > hello.c <<'EOF'
#include <stdio.h>
int main(void){ puts("hello"); return 0; }
EOF
$ gcc hello.c -o hello # preprocess → compile → assemble → link, one command
$ ./hello
hello
$ gcc -c hello.c # just to object code
$ nm hello.o # the symbols inside
$ gdb ./hello # the debugger — the C Toolchain chapter goes deep
gcc hello.c -o hello hides a four-stage pipeline you can run separately: preprocess (gcc -E — expand #include/#define into pure C), compile (gcc -S — C to assembly), assemble (gcc -c — assembly to object code), link (ld — objects + libraries into an ELF executable). -Wall warns; -O2 optimizes; -g embeds debug info for gdb; -static bakes libraries in. The toolchain — binutils (as, ld, ar, nm, objdump), gcc, glibc — is literally what LFS builds first, because everything else compiles through it.
Part 5 — The distro landscape
| Family | Package mgr | Model | Character |
|---|---|---|---|
| Debian / Ubuntu | apt/dpkg | Stable releases | The conservative bedrock |
| Fedora / RHEL | dnf/rpm | Releases / enterprise | The commercial pillar |
| Arch | pacman | Rolling | Minimal, current, DIY-flavored |
| Slackware / Slint | pkgtools/slackpkg | Releases | The oldest living; traditional Unix; our featured system |
| Gentoo | emerge | Rolling, source-built | The retail cousin of LFS |
| Alpine | apk | Rolling, musl+BusyBox | Tiny — the container world's base |
| NixOS | nix | Declarative | The OS as a build recipe |
Rolling distros update continuously; stable distros freeze for years. Source-built distros (Gentoo) prefigure LFS's core idea: you compile what you run.
Choosing is mostly choosing a package manager and a philosophy, since the kernel underneath is the same. Debian chose stability and free-software principle; Arch chose freshness and user assembly; Slackware chose not changing what works — installed in 1993 and still installing the same way, which is why it pairs naturally with this handbook: on Slackware/Slint, services are scripts in /etc/rc.d/ you can read, config is files you can read, and nothing is hidden behind an abstraction layer. That visibility is exactly what makes it the right classroom for a book that ends with you building the layers yourself.
Two special-purpose families worth naming: Alpine — musl libc + BusyBox userland, a few megabytes, the base image of the container world — and the eyes-free distros (Slint, Vinux, the late Sonar, TalkingArch, Adriane) built around Speakup and BRLTTY so the installer and the installed system both talk from the first boot.
What "stable" and "rolling" actually mean
Two release philosophies structure the landscape. Stable distros freeze package versions for years — Debian Stable, RHEL — and backport only security fixes: boring, predictable, production-grade; you trade freshness for the guarantee that nothing moves under you. Rolling distros — Arch, Gentoo, Void, openSUSE Tumbleweed — update continuously: every pacman -Syu brings the newest everything; you trade predictability for never reinstalling. Point-release with backports (Ubuntu LTS) sits between. Slackware splits the difference its own way — a famously conservative -stable alongside a -current development tree that rolls. LFS is the terminal case: no releases at all — the system is whatever you built.
The family tree
Distros beget distros — most of the landscape descends from a few ancestors: Debian → Ubuntu → Mint, Pop!_OS, elementary; Red Hat → Fedora upstream, RHEL downstream → Alma/Rocky (the community rebuilds) → CentOS; Slackware → Slint, Zenwalk, Porteus, and once-openSuSE's DNA; Arch → Manjaro, EndeavourOS; independents — Gentoo, Alpine, NixOS, Void (runit init, musl option), Solus. Choosing a derivative is choosing which defaults someone else made for you; choosing LFS is deciding to make them all yourself.
The standards that hold it together
Three standards keep ten thousand distros interoperable: POSIX (IEEE 1003 — the syscall/library/shell contract any Unix-like shares), the FHS (Filesystem Hierarchy Standard — the /etc /usr /var map this chapter toured), and LSB (Linux Standard Base — ABI-level binary compatibility). None is enforced; all are honored because the ecosystem dies without them. When this handbook says "POSIX sh," it means the dialect the standard guarantees — the subset that runs on every compliant system, not just bash's conveniences.
Part 6 — The philosophy
Unix culture has a thesis, most famously compressed by Doug McIlroy: "Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface." Concretely it means:
- Small composable tools over monoliths —
sortknows nothing ofgrep's job; the pipe joins them. - Text as the interface — config in
/etc, logs in/var/log, output on stdout: all readable, all scriptable, all greppable. - Silence means success — tools say nothing when nothing went wrong; noise is reserved for errors.
- Mechanism, not policy — the kernel provides capability; userland chooses behavior. It's why one kernel serves Android phones and TOP500 machines.
- Store data in flat text — the system's memory is inspectable; nothing hides in a binary blob you can't read.
- Transparency — source available, files readable,
mancomplete.
A sibling doctrine — "worse is better" (Richard Gabriel) — explains the aesthetic: a simple, correct-enough design that spreads beats an elaborate one that ships late. Linux is worse-is-better triumphant; Hurd is the counterexample still incubating forty years on.
And beneath it all sits the GPL — copyleft: the license requiring that whoever distributes the software also distributes its source and the same freedoms. Linux's empire was built not on secrecy but on a legal promise that the code stays inspectable forever. It is the reason you can read your operating system — and the reason this handbook can teach you to build one.
The kernel's own vocabulary
Kernel people talk in a small set of terms worth owning early: context (process vs interrupt), rings (ring 0 = kernel privilege, ring 3 = userspace), userspace boundary (the syscall wall), preemption (the scheduler taking the CPU), blocking (a process sleeping until an event), reentrancy (code safe to re-enter), upstream (the original project a distro packages), downstream (the distro), backport (a fix moved to an older stable tree), merge window (the ~2-week period new features enter the kernel), -stable tree (a maintained release line). You'll meet them all in Documentation and on LKML.
The licensing landscape
The kernel is GPLv2 — deliberately, and Torvalds has kept it there rather than moving to v3. The surrounding software spreads across the free-license map:
| License | Style | Found on |
|---|---|---|
| GPL v2/v3 | Copyleft — derivatives must stay free | kernel, bash, coreutils, gcc |
| LGPL | Weak copyleft — linkable by non-free code | glibc |
| BSD / MIT | Permissive — do anything, keep the notice | X11, many libraries |
| Apache 2.0 | Permissive + patent grant | much modern infrastructure |
| CC | Content licenses | docs, artwork |
Copyleft vs permissive is the field's real philosophical fork — GPL forces freedom forward through derivatives; BSD/MIT trusts the recipient. Linux chose the forcing function; the BSD systems chose the other; the modern world runs on both.
Version control — git
Torvalds wrote git in 2005 when BitKeeper revoked the kernel's free license — ten days to a working tool, now the world's version control. The survival subset: git clone <url> copies a project; git log/git show read history; git diff sees changes; git status orients; git add + git commit -m "why" records; git push/git pull sync. Everything in this handbook — kernel, tarballs, your own scripts — deserves version control. The kernel's own history (git log in a linux.git clone) is the finest real-world engineering log ever committed.
Virtualization and emulation
QEMU emulates whole machines — qemu-system-x86_64 -m 2G -cdrom slint.iso -hda disk.qcow2 boots an installer into a window; -enable-kvm makes it near-native speed. VirtualBox and GNOME Boxes wrap the same idea in GUI polish. Containers (namespaces + cgroups, covered above) virtualize within one kernel; VMs virtualize the whole machine. For LFS, a QEMU/KVM VM with snapshots is the professional laboratory — break it, revert, rebuild.
Security basics
Linux's security model is boring in the best way — the same file permissions, process isolation, and user separation this chapter already covered, plus a few habits:
- Least privilege — do daily work as your user; elevate with
sudoonly for the command that needs it. - Updates —
apt upgrade/dnf upgrade/slackpkg upgrade-allregularly; security fixes ride the same channel. - The firewall —
nftables/iptablesfilter traffic;ss -tlnpaudits what's listening. - ssh hygiene — keys over passwords,
PermitRootLogin no, fail2ban if exposed. - Verify downloads —
sha256sum -cagainst published checksums;gpg --verifywhere signed. - Backups —
rsync -aandtarare the timeless tools; test restores, not just archives.
The deeper model — capabilities, seccomp, SELinux/AppArmor mandatory access control — exists for when you need it; the base layer is the permission bits you already learned.
What Linux is not
- Not an OS by itself — the kernel is one program; the OS is kernel + userland. This handbook keeps the distinction honest.
- Not Unix — a reimplementation of Unix ideas to POSIX shape, sharing no AT&T code — the result of the 1990s lawsuits that proved it.
- Not "the command line" — that's the shell; the kernel doesn't know what a command is.
- Not hard — unfamiliar. Everything in it is inspectable:
man,/proc, the source. Opacity is the only thing it lacks. - Not corporate — no company owns it; the GPL guarantees nobody ever can. Companies contribute enormously — the kernel's biggest funders are Intel, Red Hat, Google — under terms that keep the code free.
Rescue — when it goes wrong
Every Linux user eventually needs the exits, so learn them before the fire: boot a live USB and mount the wounded system's disk — your files are independent of whether it boots. GRUB's e key edits boot entries live — init=/bin/sh or single bypasses broken init. Ctrl-Alt-F3 reaches a console when graphics die. chroot into the installed system from the live environment repairs configs as the system itself sees them. dmesg/journalctl -b -1 reads what the last boot said before it failed. Single-user mode, the initramfs shell (break= parameters), and a rescue image on the same stick cover the rest. The chapters on LFS teach these by making you break things first.
Special files that aren't files — sockets, fifos, and pipes
ls -l reveals a small alphabet beyond - (regular) and d (directory): l symlink, c character device (terminals — byte streams), b block device (disks), s socket, p named pipe. FIFOs (mkfifo mypipe) are named pipes — one process writes, another reads, no file on disk ever existed. Unix sockets (/run/*.sock) are local network endpoints between processes — ss -x lists them; systemd, Docker, and every database speak through them. They all answer to the same verbs — open, read, write — because everything is a file.
Common pitfalls for newcomers
rmhas no recycle bin.rm -rfon the wrong path is permanent — read the command twice before Enter.- Case matters.
File.txtandfile.txtare different files. - Don't paste commands you don't understand — especially anything piped to
sh. sudois a privilege, not an incantation — understand what you're elevating before you elevate it.- Space-free paths only in dreams — quote everything:
"$file", never bare$file. - The command didn't lie — it said nothing. Success is silence. Check
echo $?—0means it worked.
The culture of the console — why text won
The text interface outlived every graphical successor for a reason: it is scriptable, composable, remote-able, replayable, and infinite. One line does what a hundred clicks can't express; a transcript is documentation; a pipe is a program; SSH carries it anywhere on earth with no latency budget. Everything in this handbook happens there — the console isn't the beginner's stepping stone to the real system, it is the real system, the interface the kernel itself speaks.
Part 7 — The road: Linux From Scratch
Linux From Scratch (LFS), Gerard Beekmans's project since 1999, is the destination of this handbook: a book — and now our own parallel path — for constructing a working Linux system entirely from source code. You cross-compile a toolchain, enter a chroot, build the core system package by package, compile the kernel, install a bootloader — and boot a machine that contains nothing you didn't build. It is the deepest systems-education project in the open-source world: finishing it means understanding every layer this chapter surveyed.
Why build it
Because a distribution teaches you to operate a system; LFS teaches you what a system is. After LFS, a package manager is no longer magic (you did what it does, by hand, ~80 times), the boot sequence is no longer mystical (you configured GRUB and compiled the kernel), and "dependency" means something concrete (you hit every one, in order, when the build refused to proceed). Employers know it; kernel developers respect it; more importantly, you will know it.
What the build actually involves
- Prepare the host — a running Linux (Slackware/Slint, a VM, a spare partition) with compiler and dev tools; a fresh partition for the new system; the source tarballs downloaded to
$LFS/sources. - Build the cross-toolchain — binutils and gcc compiled to target the new system; glibc headers; the delicate bootstrap where the new toolchain stops depending on the host's.
- Enter the chroot — change root into the partition: the new system's
/becomes your shell's/, and you're building inside the machine you're constructing. - Build the system — ~80 packages in dependency order: zlib, file, coreutils, gawk, grep, sed, bash, gcc (again, natively), perl, python, util-linux, e2fsprogs…
- Configure —
/etcfiles, fstab, network, timezone, locale; the files Part I taught you to read. - Build the kernel —
make menuconfig: choose the drivers your hardware needs;make; install. - Install a bootloader — GRUB configuration; the
/bootpartition. - Reboot — into a system with your fingerprints on every byte.
It takes a weekend to a week depending on hardware and patience. It fails often at first — every failure is a lesson in what a dependency actually is.
A note on versions and honesty
Everything here describes mainstream 2020s Linux — kernel 6.x, systemd-or-SysV, ext4-on-GPT, UTF-8 locales. Where tools differ across distros this book names the divergence rather than pretending uniformity (apt vs pkgtools, systemctl vs rc.d). Where a detail varies between LFS's two book editions — SysVinit and systemd — this handbook's own LFS chapters cover both, since the choice is the builder's first real architectural decision.
The LFS ecosystem
LFS itself ships as two books — SysVinit and systemd editions — which is why this handbook teaches both init paths. Around it orbit BLFS (Beyond LFS — the ~1,000-package continuation covering X11, desktops, servers), ALFS (automated builds via jhalfs), and HLFS (hardened). The book is versioned — current releases track modern glibc/gcc/kernel — and meticulously maintained; we follow its package order and versions but write our own explanations, our own reference tables, and our own structure: a companion and a distilled path in one, not a copy.
Prerequisites
This handbook's middle chapters are the prerequisites: shell fluency (Part I), the C toolchain and source-building (Part II). Concretely, LFS asks for: a host Linux system (VM fine) with a compiler and ~30 GB free; comfort with tarballs and make; the ability to read a build error; and a weekend's patience. When you can ./configure && make && make install without thinking, LFS is a matter of stamina, not difficulty.
What LFS makes you build
The package sequence is the education — each stage exists because the next can't proceed without it: first a cross-toolchain (binutils→gcc→glibc targeting the new root) built against the host, then a temporary system inside chroot, then the real packages in dependency order — zlib's compression before anything that compresses, file before configure scripts that need it, coreutils before the scripts that call cp, gawk/grep/sed before the build systems that rely on them, perl/python before the packages whose builds script in them, util-linux before filesystem tools, e2fsprogs before the root filesystem's own utilities — and finally gcc rebuilt natively, the kernel configured and compiled, GRUB installed, and a machine rebooted into a system that owes nothing to anyone's installer.
The handbook map
| # | Chapter | Covers |
|---|---|---|
| 1 | Linux | ← this page: the whole landscape |
| 2 | Getting Linux | Host setup; Slackware/Slint install walkthrough |
| 3 | The Filesystem | FHS, mounts, devices, permissions-deep |
| 4 | The Shell | POSIX sh: pipes, redirection, quoting, globbing; bash extensions |
| 5 | Core Utilities | The full command reference |
| 6 | Text Processing | grep, sed, awk as languages |
| 7 | Users & Permissions | uid/gid, mode bits, su/sudo |
| 8 | Processes | ps, signals, jobs, /proc |
| 9 | Shell Scripting | POSIX sh programs, portability |
| 10 | The C Toolchain | gcc, linking, make, gdb |
| 11 | Building from Source | configure/make/install, autotools, patches |
| 12 | Inside a Linux System | kernel + libc + init; the boot sequence |
| 13 | LFS I — Cross-toolchain | binutils, gcc, glibc; the chroot |
| 14 | LFS II — System packages | building the core system |
| 15 | LFS III — Kernel & boot | kernel config, bootloader, first boot |
| 16 | Eyes-free Linux | Speakup, BRLTTY, Slint |
Each chapter ends pointing to the next. When the set is complete, this hub becomes the handbook's front page — the table of contents of a book that exists nowhere else.
Glossary
| Term | Meaning |
|---|---|
| kernel | The privileged core — owns hardware, memory, processes |
| userspace / userland | Everything that isn't the kernel |
| syscall | A program's formal request to the kernel |
| distro | Kernel + userland + package manager, packaged |
| init / PID 1 | First userspace process; ancestor of everything |
| shell | The command interpreter — sh, bash |
| tty / terminal | The text interface; tty survives from teletype days |
| package | A program + metadata managed by the package manager |
| filesystem | How storage becomes files; ext4, XFS, tmpfs… |
| mount | Attaching a filesystem into the tree at a point |
| inode | A file's real identity; names merely point to it |
| daemon | A background service process |
| root | uid 0 — the unrestricted account; also /, the tree's base |
| stdout / stderr / stdin | A process's three standard streams |
| pipe | Connecting one program's stdout to another's stdin |
| glob | Shell wildcard expansion: *, ?, [...] |
| POSIX | The portable OS interface standard Unix-likes share |
| GPL | GNU General Public License — copyleft: source stays free |
| LFS | Linux From Scratch — building the whole OS from source |
| chroot | "Change root" — a directory becomes a process's / |
| runlevel | SysV system state: 0 halt, 1 rescue, 3 multi-user, 6 reboot |
| target | systemd's runlevel descendant — multi-user.target |
| ELF | Executable and Linkable Format — every binary's shape |
| inode timestamps | mtime content · ctime metadata · atime access |
| fork/exec | How every process is born — copy, then overwrite |
| load average | Queued+runnable tasks over 1/5/15 min — uptime's tail |
| firmware | Binary blob a driver uploads to the device itself |
| initramfs | Temporary root fs the kernel mounts before the real root |
| page cache | Spare RAM the kernel spends making disk fast |
| OOM killer | The kernel's last-resort process sacrificer |
| umask | The permission mask new files are born wearing |
| shebang | #! — the kernel's cue for which interpreter runs a script |
| builtin | Command implemented inside the shell itself — cd, echo |
| magic number | Bytes at a file's start that declare its format — file reads them |
| FIFO | Named pipe — inter-process channel that exists as a filename |
| controlling terminal | The tty a session answers to — the thing SIGHUP severs |
| copy-on-write | Filesystem technique making snapshots nearly free (Btrfs/ZFS) |
| journaling | Metadata transaction log — why ext4 survives crashes |
A word on names
"Linux" properly names the kernel; the OS is GNU/Linux to the precise; "Linux" to everyone else. "Unix" — a pun on Multics — trademarked and still capitalized; "Unix-like" or "*nix" the umbrella for its descendants (Linux, the BSDs, macOS's Darwin, Solaris's corpse). "POSIX" the standard; "Free software" the philosophy; "open source" the business rebrand; "FOSS/FLOSS" the compromise terms. And Tux — a penguin chosen because Torvalds was reportedly bitten by one in Canberra — has been the mascot since 1996, drawn by Larry Ewing in GIMP.
Accessibility — Linux's secret strength
The text console is the most accessible interface ever built: pure linear text, infinitely pipeable, no pixels required. Speakup — the kernel-resident screen reader that ships in drivers/accessibility/speakup/ — speaks the console from boot to panic, before any desktop exists; BRLTTY drives refreshable braille displays; Orca speaks the GNOME desktop; espeakup bridges Speakup to software speech. Distributions like Slint (Slackware-based), Vinux, Sonar, TalkingArch, and Knoppix's Adriane mode ship eyes-free installs end-to-end. The blindness lineage runs deep — from the Kurzweil Reading Machine's print-to-speech pipeline, through the Braille 'n Speak notetaker Speakup still drives via its bns module, to a kernel that talks before the desktop loads. Chapter 16 makes the stack concrete.
Why Linux runs the world — the economics of free
The conquest wasn't luck — it was arithmetic. A kernel with no license fee, maintained by a thousand-company consortium that shares the maintenance bill, running identically on a $5 router chip and a million-core supercomputer, auditably free of back doors, customizable to a fault. Proprietary Unix died because it cost money and fragmented; Windows survives on desktop inertia; Linux won everywhere decisions were made by engineers. The GPL's enforced reciprocity — contribute or keep your fork private forever — proved to be the governance model that scales.
The culture
Linux is made by a civilization with its own institutions. LKML — the kernel mailing list — is the supreme court where patches live or die, in public, by argument. Mailing lists and IRC/Libera channels carry most real work; the conventions — reply inline, bottom-post, test before claiming — are learnable etiquette. RFCs standardize the protocols; man pages standardize the interface; kernel.org's Documentation tree explains the internals. Distros are governed variously — Debian by constitution and elected leader, Fedora by Red Hat engineering, Arch by its maintainers, Slackware by Patrick Volkerding, who has run it since 1993. The whole edifice runs on volunteer labor at industrial scale — and the barrier to joining it is fluency in everything this handbook teaches.
How to practice — exercises for chapter 1
- Boot a live USB or VM of Slackware/Slint. Log in.
manfive commands you don't know. - Navigate blind:
cd /and explore using onlyls,cd,pwd,cat— map the FHS tree by foot. - Break nothing safely: in a VM snapshot,
chmod 000a file you made; watch access die; restore it. - Compose: count how many processes are running (
ps aux | wc -l), then refine — how many are yours, how many root's. - Trace:
strace -c lsandstrace -c cat /etc/hostname— compare the syscall conversations. - Script: write
#!/bin/sh+ a loop over*.txtfiles printing each name and size. Make it executable, run it. - Read the kernel's memory: walk
/proc— uptime, cpuinfo, version — until the files tell you what machine you're on. - Interrogate the hardware:
lscpu,lsblk,lspci,lsusb,free -h— write down what your machine contains. - Diff discipline: change a config file after
cp-ing the original;diff -uthem; revert withpatch -R. - Signals: run
sleep 300,Ctrl-Zit,bg,jobs,kill %1— conduct a process through its lifecycle. - The manual habit: every command you used today,
manit and read one option you didn't know.
Timeline
| Year | Event |
|---|---|
| 1969 | Thompson & Ritchie begin Unix at Bell Labs |
| 1973 | Unix rewritten in C |
| 1983 | Stallman announces the GNU Project |
| 1984 | AT&T breakup — Unix commercialized and locked |
| 1987 | Tanenbaum's MINIX — the classroom kernel |
| Aug 1991 | Torvalds announces Linux; v0.01 in September |
| 1992 | Linux relicensed GPLv2; Tanenbaum–Torvalds debate |
| 1993 | Slackware, Debian, Red Hat founded |
| Mar 1994 | Linux 1.0 |
| 1996 | Tux becomes the mascot |
| 1999 | Linux From Scratch project begins |
| 2005 | git written for kernel development |
| 1998 | Cathedral and Bazaar; "open source" coined; Mozilla freed |
| 2000 | IBM's $1B commitment; OSDL founded |
| 2005 | git written for kernel development |
| 2007 | Linux Foundation formed (OSDL + FSG) |
| 2008 | Android 1.0 — Linux reaches pockets |
| 2010 | Speakup enters kernel staging |
| 2010s | Linux takes all of TOP500; cloud infrastructure consolidates on it |
| 2020 | Speakup promoted to mainline (Linux 5.9) |
The shape of the work ahead
Fifteen more chapters carry the map above from theory to a machine you built. The pattern every chapter follows: concepts first, then the commands, then the failure modes, then the exercises. Chapter 2 puts a host system on your desk — a Slackware or Slint install in a VM, partitioned and booted by you. Chapters 3–9 make you fluent in the console grammar — filesystem, shell, utilities, text processing, users, processes, scripting — the material Part 4 surveyed, deepened to muscle memory. Chapters 10–11 hand you the toolchain: compiling, linking, makefiles, debugging, and the configure-make-install ritual repeated until reflexive. Chapter 12 dissects a live system's boot chain organ by organ. Chapters 13–15 are the build itself — cross-toolchain, system packages, kernel and bootloader — ending at a GRUB menu you configured, booting a kernel you compiled, on a system whose every file you placed. Chapter 16 closes with the accessibility stack — the console that speaks from first boot.
Nothing in it requires talent — only the manual habit (man before guessing), the snapshot habit (VMs let you fail safely), and the patience to read errors instead of fearing them. The kernel you read about above — the one running the world's infrastructure — is a directory of C. By the end of this handbook it will also be a directory you compiled.
The commands of chapter 1 — index
| Command | Purpose |
|---|---|
pwd ls cd | Where you are, what's here, going there |
cat less head tail wc nl | Reading files |
cp mv rm mkdir rmdir ln touch | Moving matter |
chmod chown | Permission surgery |
grep sed awk cut tr sort uniq diff comm tee | Text work |
find xargs locate which type file | Finding |
ps top htop kill jobs bg fg nohup pstree | Processes |
free df du vmstat iotop uptime | Resources |
tar gzip bzip2 xz zstd dd | Archives & imaging |
mount umount fdisk gdisk mkfs fsck lsblk | Disks |
uname lscpu lspci lsusb lsmod dmesg dmidecode | Hardware |
ip ss ping ssh scp curl wget nmap | Network |
man info apropos tput stty reset tty | Knowledge & terminal |
useradd usermod userdel passwd su sudo id last | Users |
systemctl journalctl telinit logger journalctl | Services & logs |
export env alias history set source exec | The shell itself |
gcc make ld nm objdump readelf gdb strace ldd | The toolchain |
git patch diff cmp sha256sum gpg | Code & integrity |
References
- Torvalds's comp.os.minix announcement, 25 Aug 1991
- Tanenbaum–Torvalds debate archives, comp.os.minix, 1992
- USL v. BSDi case records — the 1994 4.4BSD-Lite settlement
- linuxfromscratch.org — the LFS books (SysV & systemd editions)
- kernel.org — source and documentation; Documentation/admin-guide
- IEEE POSIX / The Open Group — the interface standard
- Raymond, The Art of Unix Programming; The Cathedral and the Bazaar
- Moody, Rebel Code — Linux's history; Tanenbaum, Operating Systems: Design and Implementation — MINIX
- kernel.org Documentation tree;
man-pages(7)conventions; the FHS and POSIX specs
See also
- Speakup — the kernel-resident screen reader
- MESM · Kiev computer — earlier computer history
- Address programming language — a different software lineage