Linux Distributions Explained
When people say “I’m running Linux,” they almost never mean the bare Linux kernel — they mean a distribution (or “distro”): a complete, ready-to-use operating system built around that kernel. A distribution bundles the kernel with a package manager, a set of default utilities, configuration tools, and often a desktop environment, all put together and maintained by a specific organization or community. Understanding distributions matters because the command you type, the package manager you use, and even some file locations depend entirely on which one you’re running.
Overview: What Is a Linux Distribution?
“Linux” strictly refers to the kernel — the core program that talks to hardware, manages processes, allocates memory, and enforces permissions. Linus Torvalds started the kernel in 1991, but a kernel alone isn’t an operating system a person can use; it has no shell, no text editor, no way to install software. A distribution takes the kernel and adds everything else: a userland of GNU tools (bash, coreutils, grep), an init system to boot and manage services (almost universally systemd today), a package manager to install and update software, and a set of default configurations and policies. This is why you’ll often see the term GNU/Linux — the GNU project supplied most of the essential userland tools that make the kernel usable.
Distributions are usually grouped into families based on shared package management and heritage:
- Debian family — Debian itself, Ubuntu, Linux Mint, Pop!_OS. Uses
.debpackages and theapt/dpkgtools. - RHEL family — Red Hat Enterprise Linux (RHEL), Fedora, CentOS Stream, Rocky Linux, AlmaLinux. Uses
.rpmpackages anddnf(the modern successor toyum). - Arch family — Arch Linux, Manjaro. Uses
pacmanand a rolling-release model. - Independent/other — openSUSE (
zypper, RPM-based but its own family in practice), Alpine Linux (musl libc,apk, popular for minimal containers), Gentoo (source-based,portage).
Distributions also differ in release model. A fixed/stable release (Debian stable, Ubuntu LTS, RHEL) ships a tested snapshot of software and only backports security fixes, giving you predictability at the cost of older package versions. A rolling release (Arch, openSUSE Tumbleweed) continuously updates packages to their latest versions, giving you newer software at the cost of occasional breakage. Ubuntu’s LTS (Long Term Support) releases, for example, are supported for five years, while its interim releases only get nine months of updates — this affects how long you can safely leave a server unattended before it reaches end-of-life and stops receiving security patches.
Under the hood, every distribution running on the same hardware architecture uses fundamentally the same kernel system calls, the same /proc and /sys virtual filesystems, and the same permission model. What differs is packaging format, default file layout conventions, which init system and service manager is used, and the tooling wrapped around all of it. Once you understand this, switching between distros is mostly a matter of learning a new package manager and a few configuration file locations — the core skills (the shell, permissions, processes, scripting) transfer completely, which is exactly why this course teaches Bash and command-line fundamentals rather than one distro’s quirks.
Syntax: Identifying Your Distribution
Because so much depends on which distro you’re on, the first skill is knowing how to find out. Several commands report this information from different sources:
| Command | What it shows |
|---|---|
cat /etc/os-release |
Standardized distro name, version, and ID — read by scripts and most tools |
lsb_release -a |
Distributor ID, release, codename (Debian/Ubuntu-style; may need installing) |
uname -r |
The kernel version — not the distro version, a common point of confusion |
hostnamectl |
Hostname plus OS and kernel info, via systemd |
Examples
Example 1: Checking distro identity with /etc/os-release
cat /etc/os-release
Output:
PRETTY_NAME="Ubuntu 24.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.1 LTS (Noble Numbat)"
ID=ubuntu
ID_LIKE=debian
UBUNTU_CODENAME=noble
Every modern distribution ships this file at a fixed path, so it’s the most reliable way for a script to detect what it’s running on. The ID field (ubuntu) is the machine-readable name, and ID_LIKE (debian) tells you the family it inherits conventions from — useful when a distro you’ve never heard of is actually Debian underneath.
Example 2: Installing the same tool on two distro families
On a Debian-based system (Ubuntu, Debian, Mint):
sudo apt update
sudo apt install -y htop
Output:
Reading package lists... Done
Building dependency tree... Done
The following NEW packages will be installed:
htop
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
...
Setting up htop (3.3.0-4build1) ...
On a RHEL-based system (Fedora, RHEL, Rocky Linux), the equivalent is dnf, not apt:
sudo dnf install -y htop
Output:
Last metadata expiration check: 0:12:33 ago.
Dependencies resolved.
================================================
Package Arch Version Repository Size
================================================
Installing:
htop x86_64 3.3.0-3.fc40 fedora 124 k
...
Complete!
apt and dnf do the same conceptual job — resolve dependencies, download from configured repositories, and install — but they are different programs with different flags and different package formats, so a tutorial written for Ubuntu will not literally run on Fedora.
Example 3: A script that adapts to the distro it runs on
#!/usr/bin/env bash
set -euo pipefail
if [[ ! -f /etc/os-release ]]; then
echo "Cannot determine distribution: /etc/os-release missing" >&2
exit 1
fi
. /etc/os-release
package="${1:?usage: install-pkg.sh }"
case "$ID" in
ubuntu|debian)
sudo apt update
sudo apt install -y "$package"
;;
fedora|rhel|centos|rocky|almalinux)
sudo dnf install -y "$package"
;;
*)
echo "Unsupported distro: $ID" >&2
exit 1
;;
esac
Output (run as ./install-pkg.sh htop on Ubuntu):
Reading package lists... Done
...
Setting up htop (3.3.0-4build1) ...
This script sources /etc/os-release to load $ID into the shell, then branches with a case statement to call the right package manager. It quotes every variable expansion, checks that /etc/os-release exists before relying on it, and uses set -euo pipefail so any failed command stops the script instead of silently continuing.
How It Works Step by Step
-
Given the allowed-tags list, ordered lists render fine; walking through the script above:
1. set -euo pipefail tells Bash to exit immediately on any error, treat unset variables as errors, and fail a pipeline if any stage of it fails.
2. The [[ ! -f /etc/os-release ]] test checks the file exists before trusting it; if it doesn’t, the script prints an error to stderr (>&2) and exits with status 1.
3. . /etc/os-release (the leading dot is the source builtin) runs that file’s contents in the current shell, which defines shell variables like $ID because the file is written in simple KEY=value shell syntax.
4. ${1:?usage: ...} reads the first positional argument, and if it’s unset or empty, prints the usage message and exits — a safer variant of just referencing $1.
5. The case statement pattern-matches $ID against known distro identifiers and calls the matching package manager, falling back to an error for anything unrecognized.
Common Mistakes
Mistake 1: Assuming apt works on every distro
Following an Ubuntu tutorial on a Fedora machine:
sudo apt install htop
Output:
bash: apt: command not found
apt is Debian-family only. On Fedora/RHEL, use dnf instead:
sudo dnf install -y htop
Mistake 2: Confusing kernel version with distro version
uname -r reports the kernel version, not the distribution’s release number — they’re versioned completely independently, and assuming they match leads to wrong conclusions about what OS you’re on:
uname -r
6.8.0-40-generic
That’s the kernel build, not “Ubuntu 6.8.” To get the actual distro version, use cat /etc/os-release or lsb_release -a as shown earlier.
Mistake 3: Unquoted variable when branching on distro ID
Writing the distro check without quotes can break in subtle ways once $ID is empty or contains unexpected characters:
if [ $ID = ubuntu ]; then
echo "Debian-based"
fi
If $ID is unset, this expands to [ = ubuntu ], which is a syntax error the test command reports at runtime. Quote the expansion and prefer [[ ]]:
if [[ "$ID" == "ubuntu" ]]; then
echo "Debian-based"
fi
Best Practices
- Always check
/etc/os-release(not the distro’s marketing name someone told you) before assuming which package manager or file layout applies. - Prefer long-term-support or stable releases (Ubuntu LTS, Debian stable, RHEL) for servers you don’t want to babysit; use rolling releases only where you actively want the newest packages and can tolerate occasional breakage.
- Know your distro’s end-of-life date and plan upgrades before it arrives — an unsupported distro stops receiving security patches.
- When writing portable scripts, branch on
$IDor$ID_LIKEfrom/etc/os-releaserather than hardcoding one package manager. - Don’t mix instructions from different distro families in the same session — a command that’s safe on Ubuntu (e.g.
aptrepository syntax) is meaningless on Fedora. - Use
sudofor privileged commands rather than logging in asrootdirectly; this is the default and recommended workflow on every major distribution.
Practice Exercises
- Run
cat /etc/os-releaseon your own machine (or a VM/container if you don’t have Linux installed) and identify theID,ID_LIKE, andVERSION_IDfields. Write down which family your distro belongs to. - If you have access to both a Debian-based and an RHEL-based system (two VMs, or Docker containers via
docker run -it ubuntu:24.04 bashanddocker run -it fedora:latest bashwork well), install the same package (e.g.curl) on both and note the exact commands and output differences. - Extend the
install-pkg.shscript from Example 3 to also supportarch(usingpacman -S --noconfirm) in thecasestatement. Test it by changing the script’s logic path manually (you don’t need an actual Arch machine — just verify the syntax withbash -n install-pkg.sh).
Summary
- “Linux” is the kernel; a “distribution” is the kernel plus a package manager, userland tools, and default configuration bundled by an organization or community.
- Major families are Debian-based (
apt,.deb), RHEL-based (dnf,.rpm), and Arch-based (pacman), each with its own package format and conventions. - Distros follow either a stable/fixed release model (predictable, older packages) or a rolling release model (newer packages, less stability).
/etc/os-releaseis the standardized, script-readable way to identify a distro;uname -rreports the kernel version, which is a separate number entirely.- Core Linux skills — the shell, permissions, processes, scripting — are identical across distros; only packaging and some file locations differ.
