Beginner

Getting Started with Linux 2

Linux is built as a layered system: the kernel mediates between hardware and applications; the bootloader (GRUB) and init manager (systemd) bring the system to a running state; a distribu...

Table of Contents

Module 1: Understanding the Linux Ecosystem

The Linux Kernel and Its Origins

The Linux kernel is what Linux itself really is: everything else built on top of it (desktop environments, package managers, applications) is technically a separate layer. The first version of the kernel was written by Linus Torvalds in 1991 as an effort to replicate the functionality of the commercial Unix operating system using free software. Kernel version numbering has advanced steadily since then (modern systems commonly run kernel version 6.x).

The kernel’s job is to act as the interface between a computer’s physical hardware — RAM, physical storage, and CPU processing power — and the software applications that want to use those resources. Application code (for example, the logic behind a spreadsheet program) would be useless without a mechanism to request and receive access to compute resources; the kernel is that mechanism.

flowchart LR
    subgraph HW["Physical Hardware"]
        RAM[RAM Memory]
        CPU[CPU Processing Power]
        DISK[Physical Storage]
    end
    subgraph KERNEL["Linux Kernel"]
        MOD1[Hardware Modules]
        SCHED[Resource Scheduler]
    end
    subgraph APPS["Applications"]
        A1[Spreadsheet Program]
        A2[Web Browser]
        A3[Custom Software]
    end
    HW <--> KERNEL
    KERNEL <--> APPS

The Linux kernel has a modular design: individual software modules can be attached to the kernel to describe hardware devices and how the kernel should interact with them. For example, building a kernel for a smartphone would involve writing or importing modules describing the touch-sensitive glass, cameras, and sensors, plus applications for phone calls, text messaging, and photography. This is precisely what the Android operating system does — the software driving the overwhelming majority of smartphones on Earth is the Linux kernel. Beyond phones, Linux powers the majority of internet servers, network routing devices, supercomputers, and many embedded devices such as thermostats.

The modern Linux kernel consists of roughly 40 million lines of code, counting source code, comments, and documentation. A large portion of that code exists to support the many CPU architectures Linux runs on, including x86, ARM, and RISC-V. Because the kernel is modular, no single installed system uses anywhere near all 40 million lines — only the modules relevant to that machine’s hardware are loaded.

Kernel contribution statistics illustrate how the project is maintained:

Contributor CategoryApproximate Share of Kernel Contributions
Private / anonymous individual developers~15% (largest single group)
Intel~10%
Red Hat~10%
Google~10%
AMD, IBM, Meta, NVIDIA, Microsoft, and othersRemaining contributions

More than 80% of the kernel is authored by developers whose time is funded by technology companies that benefit from Linux. Linus Torvalds and his senior maintainer team actively manage contributions to ensure nothing is broken in the process, but the kernel is best understood as a global community project in which some of the most profitable companies in the world actively participate.

A kernel alone is not useful without an application layer installed on top of it. That combined package — kernel plus applications, utilities, and configuration — is called a distribution (or “distro”). Ubuntu, Debian, Fedora, and Red Hat Enterprise Linux are among the most popular distributions. In practice, installing Linux means downloading a complete distribution package from a distro’s website.

Linux Desktop and Shell Environments

There are many ways to get access to a running Linux environment, including:

  • Installing from a USB drive onto physical hardware
  • Creating a virtual machine (for example, using VirtualBox) running Linux as a desktop or server
  • Launching a virtual Linux instance in a cloud platform such as AWS
  • Running Linux inside Windows using the Windows Subsystem for Linux (WSL)
  • Using someone else’s Linux machine directly

Exploring a graphical desktop. Red Hat Enterprise Linux uses the GNOME desktop manager, which is also used across many other distros, making it a reasonable reference point for understanding a typical Linux desktop layout:

  • A dock (a toolbar, often placed along the bottom of the screen by default but repositionable) provides quick access to frequently used applications.
  • Multiple virtual desktops can run different sets of applications simultaneously; you switch between them by clicking.
  • The software center application is where users find, download, and install packages and extensions from curated software repositories. These repositories handle the full package lifecycle automatically — installation, updates, and security scanning — and typically contain many thousands of free packages.
  • The Files application provides basic file management; a check mark in the software center indicates an app is already installed.
  • The terminal application is where most Linux system administration work is done, since most admins interact with Linux through the command line rather than a graphical session, and most servers do not even have a graphical desktop installed. A simple first command to try is:
pwd

pwd prints the current working directory. Typing exit closes the terminal.

  • A basic text editor app is useful for managing plaintext files such as programming code, without the extra formatting features of a full word processor.
  • A calculator application, often with multiple modes including financial calculations.
  • An application menu icon exposes all installed apps (including ones not pinned to the dock), and supports text search once many applications are installed.
  • System settings, accessible from a gear icon, expose configuration for networking (including multi-display setups), file/media type associations with default applications, online account authentication, keyboard preferences, and automatically detected devices such as network printers.
  • A power icon provides a dialog for choosing the machine’s power state (e.g., power off, restart).

Remote access via SSH. Most admins connect to Linux servers directly through a command line rather than logging into a graphical session, most commonly using the Secure Shell (SSH) protocol:

ssh admin1@192.168.101.71

This establishes a remote session on the target Linux server (identified here by its IP address), authenticating as the admin1 account (which will require a password). SSH clients are available on Linux, macOS, and Windows, so as long as you have valid credentials and network connectivity you can administer Linux servers from virtually anywhere. Once connected via SSH, you land at the same file-system location and shell environment you would reach by opening a terminal window locally inside a graphical desktop session.

flowchart TD
    U[Administrator] -->|Local terminal in GNOME desktop| T[Bash Shell Session]
    U -->|"ssh admin1@192.168.101.71"| S[SSH Remote Session]
    S --> T
    T --> FS[Same Linux File System / Same Working Directory]

How Applications Interact with the Linux Kernel

Beyond the kernel itself, several other layers are involved before a user ever reaches a working desktop or shell:

  1. GRUB (GRand Unified Bootloader) — takes over from the Master Boot Record (MBR), which lives in the first sector of a boot device and is itself loaded by the machine’s BIOS or UEFI firmware. GRUB can present a menu listing each operating system kernel available to boot, but typically it automatically and invisibly loads the latest available kernel; the menu is normally only seen if something has gone wrong during startup.
  2. The Linux kernel loads into memory.
  3. The init manager begins launching system services, background programs, and logging processes — including database servers and application software (for example, on a machine serving a public-facing website) — as well as executing any scheduled automated tasks that the system or its users have configured. On most modern Linux distributions, the init manager is systemd, which comes with its own family of administration tools for customizing and maintaining running systems.
flowchart LR
    BIOS["BIOS / UEFI Firmware"] --> MBR["Master Boot Record"]
    MBR --> GRUB["GRUB Bootloader"]
    GRUB -->|Loads latest kernel automatically, or shows boot menu on failure| KERNEL["Linux Kernel Loaded into Memory"]
    KERNEL --> INIT["Init Manager (systemd)"]
    INIT --> SVC["System Services, Applications, Scheduled Tasks"]

Linux configuration settings are almost always stored in plaintext files somewhere in the file system — in fact, nearly all Linux data of any kind lives in plaintext files within the file system hierarchy. Understanding how to locate important resources and make changes to the system therefore depends on understanding how that file system is organized (covered later in this module).

Example: how a real application is assembled from many file-system locations. Using the Wireshark network packet analyzer as an illustration (the specific application is not important — the point is how many different parts must exist and cooperate to make any Linux application function):

PurposeLocation
Compiled program binary/usr/bin/wireshark
Per-user recent settings (auto-generated)User’s personal file hierarchy
Shared libraries and plugins/usr/lib/x86_64-linux-gnu/
Static data, configuration, dictionaries, documentation/usr/share/wireshark/
HTML documentation manuals/usr/share/doc/wireshark/
Package lifecycle metadata (install/upgrade/removal records)dpkg info files referencing Wireshark
Application icons and other trivial assetsDedicated image files elsewhere in /usr/share

All of this documentation is also reachable through the traditional man system (covered later). The overall picture: from the systemd init manager down to the many scattered files an individual application needs, a large number of layers must work together so that, by the time you log into a graphical desktop or a terminal shell, you have an active, fully functioning system ready to use.

Choosing a Linux Distribution

Every Linux distribution is built around the same official Linux kernel, but each one adds its own set of packages and configuration profiles. Beyond well-known general-purpose distros like Ubuntu and Red Hat, there are hundreds of smaller distros built for specialized use cases.

Ranking distros purely by installation count is not very meaningful, because Linux serves very different purposes across different contexts:

  • Amazon Linux 2 is technically among the top few distros by install count, but primarily because it was built by Amazon specifically for AWS and is heavily used there — not because many people install it on laptops or in local datacenters.
  • Kali Linux does not have anywhere near the raw install numbers of general-purpose distros, but it dominates its niche: cybersecurity and penetration testing. Kali is built on top of Ubuntu, which is itself built on top of Debian — Ubuntu is essentially a customized Debian, and Kali is a customized Ubuntu, each release rebuilt from its respective parent.
flowchart TD
    DEBIAN["Debian (stability-focused, APT package manager)"]
    UBUNTU["Ubuntu (general-purpose, maintained by Canonical)"]
    KALI["Kali Linux (penetration testing / security)"]
    MINT["Linux Mint (desktop-friendly)"]
    ZORIN["Zorin OS (Windows-migration friendly)"]
    ELEM["Elementary OS (macOS-like interface)"]
    XUBUNTU["Xubuntu (lightweight, older hardware)"]

    RHEL["Red Hat Enterprise Linux (commercial license model)"]
    FEDORA["Fedora (free upstream testbed)"]
    CENTOSSTREAM["CentOS Stream (free upstream testbed)"]
    ALMA["AlmaLinux (RHEL-compatible)"]
    ROCKY["Rocky Linux (RHEL-compatible)"]

    ARCH["Arch Linux (independent, minimal, highly customizable)"]
    OPENSUSE["openSUSE (independent, enterprise workloads)"]

    DEBIAN --> UBUNTU
    UBUNTU --> KALI
    UBUNTU --> MINT
    UBUNTU --> ZORIN
    UBUNTU --> ELEM
    UBUNTU --> XUBUNTU

    RHEL --> FEDORA
    RHEL --> CENTOSSTREAM
    RHEL -.compatible clone.-> ALMA
    RHEL -.compatible clone.-> ROCKY

Debian family. Debian’s primary value proposition is stability: updates are infrequent, but reliable, making it attractive for enterprise server workloads. Debian is also the origin of the APT package manager, the front end for Debian’s software repositories. Any distro built on Debian inherits seamless integration with the thousands of open-source packages managed by APT.

  • Ubuntu — a Debian derivative prepared for use anywhere: servers, hypervisors, public/private cloud platforms, routers, desktops, and laptops. Ubuntu is free, though Canonical (its corporate maintainer) sells enterprise-level support plans for large or complex deployments. Every 2 years Ubuntu ships a Long-Term Support (LTS) release, with support lasting up to 10 years — well suited to deployments meant to run for years without reinstallation.
  • Ubuntu itself is a parent to further distros: Linux Mint (popular desktop interface), Zorin OS (aimed at users migrating from Windows), Elementary OS (closer in feel to macOS), and Xubuntu (runs well even on older, lower-powered machines).

Red Hat family. Red Hat Enterprise Linux (RHEL) is built around a commercial licensing model where business users purchase per-machine licenses. Red Hat also supports the free Fedora and CentOS Stream distros, which serve as testbeds for features that eventually make their way into RHEL. CentOS historically mirrored RHEL exactly and was fully open, but Red Hat discontinued that model. Independent projects AlmaLinux and Rocky Linux now provide feature-for-feature compatibility with the latest RHEL releases.

Independent distros.

  • Arch Linux — minimal, highly customizable, and by reputation best suited to serious and experienced administrators; those who adopt it tend to prefer it strongly over alternatives.
  • openSUSE — popular with experienced administrators for enterprise workloads, offering multiple distro variants for a range of applications.
DistroBasePrimary Use Case / Niche
Debian— (Foundational)Long-term server stability
UbuntuDebianGeneral-purpose (desktop, server, cloud)
Kali LinuxUbuntu → DebianCybersecurity / penetration testing
Linux MintUbuntuDesktop-focused interface
Zorin OSUbuntuWindows-to-Linux migration
Elementary OSUbuntumacOS-like desktop experience
XubuntuUbuntuLightweight, older hardware
Amazon Linux 2IndependentOptimized for AWS Cloud
Red Hat Enterprise Linux— (Foundational)Commercial enterprise support
FedoraRHEL upstreamFree testbed for new RHEL features
CentOS StreamRHEL upstreamFree testbed for new RHEL features
AlmaLinuxRHEL-compatible cloneFree, fully RHEL-compatible
Rocky LinuxRHEL-compatible cloneFree, fully RHEL-compatible
Arch LinuxIndependentMinimal, highly customizable
openSUSEIndependentEnterprise workloads

Using Open Source Software Responsibly

“Open source” means that the software, labor, or assets that went into an item have been donated to the world, generally with some conditions attached. It is the responsibility of anyone installing and using open-source software to understand which conditions apply and to respect them. In most cases restrictions are minor and will rarely limit ordinary use, but understanding license categories is still important.

flowchart TD
    OSS["Open Source Licenses"]
    OSS --> PERM["Permissive Licenses"]
    OSS --> COPY["Copyleft / Reciprocal Licenses"]
    OSS --> PUB["Public Domain"]

    PERM --> MIT["MIT License"]
    PERM --> APACHE["Apache 2.0 License"]

    COPY --> STRONG["Strong Copyleft"]
    COPY --> WEAK["Weak Copyleft"]
    STRONG --> GPL2["GNU GPL v2"]
    STRONG --> GPL3["GNU GPL v3"]
    WEAK --> MPL["Mozilla Public License"]

Permissive licenses (MIT, Apache) come with minimal conditions: they permit commercial use and inclusion in closed-source projects. Typically only the original license text and attribution need to be included in redistributions.

  • The Apache 2.0 license includes a patent retaliation clause: usage rights terminate if you or your organization launch a patent lawsuit against anyone involved with the open-source project. The Android Open Source Project and Kubernetes use the Apache license.
  • The MIT license is used by well-known tools such as Node.js and Ruby on Rails.

Copyleft (reciprocal) licenses come in two flavors:

  • Strong copyleft requires any derivative work to be licensed under a compatible license. The GNU GPL versions 2 and 3 are strong copyleft examples; the Linux kernel itself uses GPL v2, and the R programming language is protected by GPL v3.
  • Weak copyleft protects only the core library itself while allowing inclusion in larger proprietary systems, as long as the core remains open. The Mozilla Public License (MPL), used by LibreOffice, is a weak copyleft example — it allows derivative works to include dynamic links to proprietary applications (for example, enabling third-party stock-price API integrations inside a LibreOffice Calc spreadsheet).

Public domain licenses effectively assign full ownership rights to whoever uses the software. Typical limits are only that the software must not be used in the commission of a crime and that its use must not create legal liability for the original creators.

Creative Commons licenses also exist, with many possible clause combinations, but they are typically used for content rather than software.

License CategoryExamplesKey Characteristic
PermissiveMIT, Apache 2.0Minimal conditions; usable in closed-source/commercial projects
Strong CopyleftGNU GPL v2, GNU GPL v3Derivative works must use a compatible open license
Weak CopyleftMozilla Public License (MPL)Core library stays open; can link into proprietary systems
Public DomainFull ownership assigned to the user, minimal restrictions
Creative CommonsVarious clause combinationsTypically used for content, not software

The open-source movement, with Linux as its most visible achievement, has given countless people tools to earn a living and build valuable projects. Some projects (like the Linux kernel) are backed by powerful corporations, while others are quietly maintained by one or two volunteers — including projects that play critical roles in the infrastructure underpinning the internet and modern society. Historically, the people maintaining those projects have donated their time to make things better, though there have been cases where the influence of core projects has been misused for criminal or political ends. For that reason, it is worth doing some research into licensing and provenance whenever adding third-party components to your own projects.

Module 2: Getting Hands-on with Linux

Installing a Linux Environment

There is no single way to get Linux installed, and the number of possible target hosts and installation types is very large. A few common, representative approaches:

Windows Subsystem for Linux (WSL). For Windows users, WSL provides a CLI-based platform for running virtualized Linux environments directly inside the Windows Command Prompt — without a graphical Linux desktop, but with a full Ubuntu, Debian, or other distro experience.

wsl --install Debian

The first run can take a minute or more to complete. On first launch you are prompted to create a new account (any username you choose). The Windows prompt visibly changes to indicate you are now inside the Linux subsystem. You can confirm the kernel is genuinely Linux with:

uname -a

This typically reports a specialized Microsoft-built kernel that is nonetheless a real Linux kernel — WSL was built as a collaboration between Microsoft and Canonical engineers.

Creating a bootable USB stick. This is the most common approach for installing Linux onto physical hardware, whether a server or a personal laptop. General process (following the official Ubuntu installation guide, though the steps are broadly similar for any distro):

  1. Confirm the target machine meets the minimum hardware requirements for the distro (or simply try the live desktop without installing, to check for compatibility problems).
  2. Back up or confirm you have no important data on the target drive and on the USB stick being used to create the installer — both will be irreversibly overwritten.
  3. Download the appropriate installer image (typically the most recent AMD64 image) from the official distro website.
  4. Use a tool appropriate to your current operating system to write the image to the USB stick — for example, Rufus on Windows, or balenaEtcher on macOS/Linux.
  5. Shut down the target machine, plug in the USB stick, and power on. With most modern firmware the system boots directly into the installer; otherwise, boot-order/BIOS settings may need to be adjusted to force the machine to boot from USB.
  6. Proceed through the distro’s installation wizard.

Launching a Linux instance in AWS. With an active AWS account and the AWS CLI installed, a live Linux server instance can be created with a single command:

aws ec2 run-instances \
  --image-id ami-xxxxxxxxxxxxxxxxx \
  --count 1 \
  --instance-type t2.micro \
  --key-name MyKeyPair \
  --security-group-ids sg-xxxxxxxx \
  --subnet-id subnet-xxxxxxxx

This creates a headless AWS instance running Amazon Linux 2 (no desktop — just a server you would reach over SSH). Prerequisites for this command to work:

  • A valid, current AMI (--image-id) available in your default AWS region.
  • A previously created key pair (here, MyKeyPair) in the correct region, so you can SSH into the instance once it launches.
  • Valid, existing security group and subnet IDs.

This can equally be done through the AWS web console, but the CLI offers simplicity and fine-grained control once the required values are known.

Installing a Linux Virtual Machine Using VirtualBox

Running Linux inside a virtual machine is a practical option when dedicated hardware is not available. Oracle VirtualBox is a reliable, relatively simple, cross-platform choice for this. VMs allow different Linux versions (e.g., an older Ubuntu release alongside a newer Red Hat Enterprise Linux release) to run side-by-side on the same host.

Creating a new VM — step by step:

  1. Click the New icon in VirtualBox to define a new VM, and give it a name.
  2. Point VirtualBox to an Ubuntu ISO image; if VirtualBox already knows about a downloaded ISO, it will be offered automatically, and the OS type/version fields populate accordingly.
  3. On the Unattended Install tab, credentials for a new system user and a custom hostname can be preset — though for a manual Ubuntu install, the actual installation process will override these preset values (the initial password shown here should still be strengthened later).
  4. Adjust memory and CPU allocation using the sliders if the workload needs more than the defaults — but avoid over-allocating, since excessive VM resource usage can degrade the host machine’s own performance.
  5. Adjust storage size similarly — roughly 25 GB is sufficient for a functional Ubuntu desktop install, more if heavy local data writes are expected. Storage and other limits can be edited later and take effect on the VM’s next boot.
  6. Click Finish, then start the VM.

Running the Ubuntu installer inside the VM:

  • If the installer display is too large for the VirtualBox window, switch the VM display to Scale mode (the right Ctrl key + C combination reverses a broken auto-scale change, if needed).
  • Select the desired language, any needed accessibility accommodations, and keyboard layout (all changeable later).
  • Select an internet connection — a VM will typically share the host workstation’s own network connection.
  • Optionally update the installer itself if prompted (recommended, though it can be skipped for a quick pass).
  • Choose Try Ubuntu to only test the OS, or Install Ubuntu to proceed directly to installation.
  • Choose the interactive install process (unless you have a prepared auto-install template).
  • Enable both updates during install and third-party software options for full system functionality (recommended unless you specifically want to avoid non-free components).
  • Choose a disk option:
    • Erase disk — the simplest option; wipes the (virtual) disk clean for a fresh install. On a VM, this only affects the VM’s virtual disk, not the host machine’s physical drive. On real hardware, this would wipe the physical drive.
    • Manual installation — allows dual-boot alongside an existing OS (e.g., Windows) or custom partition/mount-point assignment.
  • Set a computer name, username, and password (a common convention for VMs/containers is a simple username like ubuntu).
  • Confirm the detected time zone.
  • Review all settings, then click Install. Installation can take up to around 30 minutes.

Booting into the new VM: select the VM in VirtualBox and click the green Start icon; the boot process may take a little longer than usual because of the added virtualization layers. Log in with the password created during installation.

flowchart TD
    A["Create New VM in VirtualBox"] --> B["Attach Ubuntu ISO Image"]
    B --> C["Configure CPU / RAM / Storage Allocation"]
    C --> D["Start VM -> Boot Installer"]
    D --> E["Choose Language, Accessibility, Keyboard"]
    E --> F["Connect to Network"]
    F --> G{"Try Ubuntu or Install Ubuntu?"}
    G -->|Try| H["Live Desktop (no install)"]
    G -->|Install| I["Choose Interactive or Automated Install"]
    I --> J["Enable Updates + Third-Party Software"]
    J --> K{"Erase Disk or Manual Partitioning?"}
    K --> L["Set Computer Name / Username / Password"]
    L --> M["Confirm Time Zone"]
    M --> N["Run Installation (up to ~30 min)"]
    N --> O["Boot into Installed Ubuntu VM"]

Getting Familiar with the Linux File System

Files on Linux are organized according to a stable, logical, hierarchical system that is consistent across virtually all Linux distributions, and largely holds true on macOS, OpenBSD, and Unix as well — even when resources are spread across multiple physical storage devices. This structure traces back many decades to the original Unix operating system.

This layout is formalized by the Filesystem Hierarchy Standard (FHS), documented by the Linux Foundation. Compliance requires that a distro provide each of the standard top-level directories under root — they don’t all need to be populated, but they must exist, so applications and users can rely on predictable locations across any compliant distro.

The very top of the file system is the root directory, represented by a single forward slash (/):

cd /

Listing its contents shows the standard top-level directories, plus possibly a few extras created by regular system use:

ls

Note: a directory literally named root (the home directory of the root user) is not the same thing as “the root directory” — it is just one subdirectory located directly under root.

flowchart TD
    ROOT["/ (root directory)"]
    ROOT --> BIN["/bin -> symlink to /usr/bin"]
    ROOT --> SBIN["/sbin -> symlink to /usr/sbin"]
    ROOT --> BOOT["/boot"]
    ROOT --> DEV["/dev"]
    ROOT --> ETC["/etc"]
    ROOT --> HOME["/home"]
    ROOT --> LIB["/lib"]
    ROOT --> MEDIA["/media"]
    ROOT --> MNT["/mnt"]
    ROOT --> OPT["/opt"]
    ROOT --> PROC["/proc"]
    ROOT --> ROOTUSR["/root (root user's home dir)"]
    ROOT --> RUN["/run"]
    ROOT --> USR["/usr"]
    ROOT --> VAR["/var"]
    USR --> USRBIN["/usr/bin"]
    USR --> USRLIB["/usr/lib"]
    USR --> USRSHARE["/usr/share"]

Most of these directories form their own tree-like substructures. The tree command visualizes that structure directly:

tree -L 1

tree may not be installed by default. On Debian/Ubuntu systems, install it with:

sudo apt update
sudo apt install tree

Running tree with no depth limit against a full system illustrates just how large Linux file systems can get — commonly more than 64,000 directories containing more than half a million files (this count can be inflated by large development environments, e.g. a Python/JupyterLab installation):

tree

Moving into /etc:

cd /etc

Because the current location is already root, the leading slash could be omitted here — but in general, including the leading slash ensures Linux resolves the path relative to root rather than the current directory.

A shell alias may let a shortened command work — for example, a Bash configuration might map a single letter l to ls. This is a per-system/per-user convenience and should not be assumed to work everywhere.

/etc is a very active directory holding most system and application configuration files, so it tends to accumulate many subdirectories and files quickly.

Confirming your location and command locations:

pwd

To find where a command’s actual binary file lives:

which pwd
# /usr/bin/pwd

To understand why a command can be run without specifying its full path, inspect the PATH environment variable:

echo $PATH

PATH is a colon-separated list of directories that are searched, in order, whenever a bare command name is typed — as though invoking the command from inside one of those directories. If /usr/bin (where pwd lives) is not in PATH, or if a binary is moved out of a directory listed in PATH, invoking it by name alone will fail. New directories can be manually appended to PATH as needed — a common task for Linux administrators.

flowchart LR
    CMD["User types: pwd"] --> SHELL["Shell checks $PATH directories in order"]
    SHELL --> D1["/usr/local/sbin"]
    SHELL --> D2["/usr/local/bin"]
    SHELL --> D3["/usr/bin"]
    D3 --> FOUND["Binary found: /usr/bin/pwd"]
    FOUND --> EXEC["Command executes"]

Moving Around the Linux File System

Linux command interpretation depends heavily on whether a path is absolute (starts from root) or relative (interpreted based on the current directory).

Example: from inside /etc/perl, running:

cd home

fails, because Linux looks for a directory literally named home beneath the current directory (/etc/perl/home), which does not exist. Prefixing the path with a slash resolves it from the true root instead:

cd /home
pwd

/home is where user accounts get their own personal directories — for example, a default ubuntu user account would have its personal working space at /home/ubuntu. It is common practice to create a private directory hierarchy under /home for every new user added to a system.

Relative navigation also works with .. (parent directory):

cd ..
pwd

Key root-level directories:

DirectoryPurpose
/binBinaries for essential user commands (cat, chmod, mkdir, etc.) — actually a symbolic link into /usr/bin on modern systems
/sbinBinaries for system-oriented tools used more by Linux itself (process, network, firewall, encryption tasks) — a symbolic link into /usr/sbin
/usrContains system resources, including /usr/share (static docs and locale data needed by all processes/users) and the real locations backing /bin//sbin
/etcSystem and application configuration files
/libShared libraries and kernel module files — libraries hold reusable code functions for any process; modules extend kernel device support without rebooting
/media, /mntMount points for removable media (USB drives) and temporary file systems; normally empty unless a device has been manually mounted
/varVariable data generated by the system and running applications, including log files; also conventionally used by tools like web servers for their application files
/devDynamic files representing physical devices recognized by the system; generated in response to detected hardware and not guaranteed to persist across reboots

Verifying that /bin and /sbin are really symlinks:

ls -l /bin
ls -l /sbin

This design reflects the historical transition from systems with very limited storage to today’s resource-rich environments, where /usr now holds the canonical binary locations and /bin//sbin remain only for compatibility.

Module 3: Working with Files and Directories

Reading Files from the Command Line

Since Linux is fundamentally driven by plaintext configuration and data files, a solid toolkit for reading and working with text from the command line is essential.

cat prints file contents to the screen:

cat /etc/shells

/etc/shells lists the file-system locations of each shell interpreter currently available on the system. A leading line beginning with # is a comment meant only for human readers — programs ignore it. Different shell interpreters can interpret certain commands slightly differently, which is why the available options are tracked in this file (even though most users colloquially just call their shell “Bash,” regardless of the actual interpreter in use).

Print with line numbers (useful when, say, an error message references a specific line number):

cat -n /etc/shells

Clear the screen (same role as cls on Windows):

clear

cat is short for concatenate — its core purpose is to link/chain the contents of multiple sources together, not just print a single file:

cat /etc/shells /etc/passwd

/etc/passwd (spelled without the “o” and “r” you might expect) holds login information for each system user. Encrypted password data used to live here too, but was moved to a separate /etc/shadow file years ago for security reasons. Running the combined cat command above prints the contents of /etc/shells first, immediately followed by the (much longer) contents of /etc/passwd. cat is also efficient for combining large data files — for example, concatenating multiple large CSV files (millions of rows) into a single file, a task at which cat is hard to beat for speed and reliability.

cat is convenient for short files, but not for files that extend beyond a single screen — like /etc/passwd, and more so, system logs.

less is suited for browsing longer files interactively. Listing the log directory first:

ls /var/log
  • auth.log — records of account authentication attempts.
  • Files under an apache2 subdirectory — events related to the Apache web server.
  • syslog — on Debian/Ubuntu systems, this captures events from most system log producers, and is typically a very long file.

Open a long file with less:

less /var/log/syslog

Each log entry typically begins with a datetime stamp, followed by the process name and event message.

less KeyAction
SpaceMove down one screen
bMove back up one screen
/searchtermSearch forward for a string (case-sensitive)
nJump to the next match
G (uppercase)Jump to the end of the file
qQuit less

Example search inside less: typing /Error (capital E, since the search is case-sensitive) and pressing Enter jumps to the first match; n cycles through subsequent matches, with matches highlighted.

head and tail extract just the lines you need from large files, rather than displaying everything.

head /var/log/syslog        # first 10 lines (default)
head -n 5 /var/log/syslog   # first 5 lines
tail /var/log/syslog        # last 10 lines (default)
CommandPurposeCommon Flags
catPrint (and concatenate) whole file contents-n (number lines)
lessInteractively page through long files, with search/pattern, n, G, q
headPrint the first lines of a file-n N (first N lines)
tailPrint the last lines of a file-n N (last N lines), -f (follow)

Creating and Editing Files Using Nano

Creating and editing files is just as important as reading them. Full-featured word processors — Microsoft Word, Google Docs, or even the open-source LibreOffice Writer — should generally be avoided for Linux administration tasks, because they add invisible formatting markup by default that can cause a Bash script or configuration file to behave erratically or fail outright. Linux administration requires truly plain text.

Options include a graphical plaintext editor (e.g., gedit) or a terminal-based editor. Historically that meant vi (or its modern successor, vim) — originally designed for terminals with very limited keyboards (no mouse, no arrow keys or function keys in the earliest environments). This led to navigation via regular character keys and multiple editing modes; even exiting vi requires a specific key sequence (:q). While vi/vim is extremely powerful once mastered, it has a steep learning curve.

Many administrators prefer nano instead, a simpler terminal-based text editor:

nano newfile.txt

If the named file already exists, its contents load into the editor; otherwise, nano opens an empty buffer. A mouse cannot be used, but arrow keys work normally, and a menu of key combinations is shown at the bottom of the screen.

Nano ShortcutAction
Ctrl+XExit (prompts to save unsaved changes)
Ctrl+OSave (write out) without exiting
Ctrl+Shift+VPaste (regular Ctrl+V/Ctrl+C often do not work in Bash shells; right-click copy/paste generally does work)

Typing content and pressing Ctrl+X, then Y to confirm saving, writes the new file to the current directory; cat newfile.txt then shows the saved content.

Editing a system file that requires elevated privileges: attempting to edit /var/log/syslog directly with nano may show a warning that the file is unwritable, because syslog is readable by any user but writable only by users with root privileges:

nano /var/log/syslog

Opening it with elevated privileges (assuming your user is a member of the sudo group) would allow saving changes:

sudo nano /var/log/syslog

Without sudo, attempting to save (Ctrl+X, then confirming with Enter) fails; choosing N at the save prompt discards the attempted changes instead.

Editing a file you own (for example, an old script file owned by your own user account) works normally — arrow keys move between lines, Delete removes characters. A practical example from the narration: editing a script to uncomment previously commented-out lines (removing a leading # and following space) so that a pip install command and other previously disabled commands will actually execute when the script runs, and adding an exit command at the end to terminate the script explicitly. Saving with Ctrl+X (confirming Y) writes the changes to disk without any permission warnings, since the file belongs to the current user.

Monitoring Ongoing File Changes

Piping commands together. The pipe character (|, typically Shift + backslash) sends the output of one command directly into another command as input, rather than printing it to the screen:

cat file.txt | head -n 20

This is functionally equivalent to head -n 20 file.txt. Chaining a second pipe extracts a very specific slice of a file — for example, lines 16 through 20:

cat file.txt | head -n 20 | tail -n 5
flowchart LR
    A["cat file.txt"] -->|pipe| B["head -n 20"]
    B -->|pipe| C["tail -n 5"]
    C --> D["Lines 16-20 printed"]

Building and running a shell script. Using nano to create a new script:

nano myscript.sh

While Linux does not require a specific file extension to determine how to execute a file, .sh is a common convention to signal “this is a shell script” for human readability. An illustrative log-generating script discussed in the narration behaves like this:

#!/bin/bash
# Generates fake log entries to simulate a running application

while true; do
    echo "$(date '+%Y-%m-%d %H:%M:%S') INFO: sample log entry 1" >> webapp.log
    sleep 2
    echo "$(date '+%Y-%m-%d %H:%M:%S') INFO: sample log entry 2" >> webapp.log
    sleep 1
    echo "$(date '+%Y-%m-%d %H:%M:%S') INFO: sample log entry 3" >> webapp.log
    sleep 2
done

The script’s while loop repeatedly executes a small set of commands (in this example, three echo statements interleaved with sleep pauses) until something breaks the loop, appending each generated entry to a log file (webapp.log) in the current directory.

Before the script can run, it needs the executable permission bit set:

chmod +x myscript.sh
ls -l myscript.sh

Many shells will color an executable file differently (e.g., green) once the executable bit is set, as a visual convenience (not guaranteed across all shell configurations).

Running the script, using a leading ./ to tell Bash the file lives in the current directory, and & to run it as a background process (so the terminal remains available):

./myscript.sh &

Because the script’s output is redirected into webapp.log rather than the terminal, nothing prints to the screen immediately. Confirming the file exists and inspecting its growing contents:

ls
cat webapp.log

Re-running the last command without retyping it is possible using the Up arrow key to recall command history.

Following a growing file with tail -f. Rather than repeatedly re-running cat, the -f (“follow”) flag on tail continuously prints new lines as they are appended:

tail -f webapp.log

This immediately shows the most recent lines of the existing file, then streams new lines as they are written — useful, for example, to watch a service’s error log in near-real time without manually scrolling through potentially thousands of boring log entries. Press Ctrl+C to stop following.

Managing a backgrounded process. To bring a background job back to the foreground (so it can be interrupted), use fg with the job number:

fg %1

Once back in the foreground, Ctrl+C stops the process.

stateDiagram-v2
    [*] --> Foreground: script started normally
    Foreground --> Background: append & to command, or Ctrl+Z then bg
    Background --> Foreground: fg %<job_number>
    Foreground --> Terminated: Ctrl+C
    Background --> Terminated: kill <pid>

Accessing System Documentation

Linux administration leaves little room for error — a single wrong character can cause a command to fail outright, or (worse) to succeed in an unintended way, up to and including permanently and irreversibly erasing data from a drive. Getting commands right matters, and Linux provides substantial built-in documentation to help.

Bare command guidance. Running a command with no arguments sometimes prints basic usage guidance:

tar

Many tools also support explicit help flags:

tar --help
tar --usage

Piping long help output into less keeps it manageable:

tar --help | less

(tar itself is used to bundle multiple files into a single archive file, or unpack an existing archive, optionally applying compression/decompression.)

The man system. The primary source of documentation for most commands is their manual page:

man tar

A typical man page:

  • Notes that tar supports both the traditional Linux/GNU syntax (no dash required before flags) and the older Unix-style syntax (dash required) — reflecting the tool’s age (tar dates back to the 1970s).
  • Provides a detailed description of the tool and its usage.
  • Explains each flag/option in detail.
  • Is divided into consistent sections, often including practical examples, external references, copyright information, and sometimes historical/biographical notes about the original authors.

Man page section numbers. Man pages are organized into numbered sections; the same command name can have entries in multiple sections covering different topics:

man kill        # defaults to section 1 (User Commands)
man 1 kill      # explicitly: User Commands Manual
man 2 kill      # System Calls Manual (a completely different guide, still about "kill")
man 3 kill      # (may report no section 3 exists for kill)
Man Section NumberContent Type
1User Commands
2System Calls
3Library Calls
4Special Files (e.g., device files)
5File Formats and Conventions
6Games
7Miscellaneous (macros, conventions, protocols)
8System Administration Commands

A command can have up to 8 separate man pages (one per section), though most commands only have one.

Searching man pages by keyword. When the exact command name isn’t known, -k searches man page name descriptions for a keyword:

man -k "delete a directory"

This might surface rmdir (deletes a directory, but only if it is already empty) even when the actual goal was rm (deletes files or directories, including non-empty ones) — because the rm man page’s name section happens to use the word “remove” rather than “delete.” This illustrates why it can be necessary to experiment with different search terms when searching man pages by keyword.

flowchart TD
    Q["Need help with a command"] --> A{"Do you know the command name?"}
    A -->|Yes| B["man <command>"]
    A -->|No| C["man -k \"keyword phrase\""]
    B --> D{"Multiple man sections for this name?"}
    D -->|Yes| E["man <section_number> <command>"]
    D -->|No| F["Single man page shown"]
    C --> G["Review matching commands by description"]

Summary

Linux is built as a layered system: the kernel mediates between hardware and applications; the bootloader (GRUB) and init manager (systemd) bring the system to a running state; a distribution wraps the kernel together with an application layer, package manager, and configuration; and nearly everything on the system — configuration, logs, and application data — is represented as plaintext files organized under a standardized, predictable file system hierarchy.

Key principles to carry forward:

  • The kernel is modular and portable across enormously different hardware, from smartphones to supercomputers, and is maintained as a large-scale collaborative open-source project.
  • A distribution is more than a kernel — it is the kernel plus a curated application layer, package manager, and support model, and different distros exist to serve different needs (general-purpose desktop/server use, security testing, cloud-native deployment, enterprise support contracts, or minimal customizability).
  • Open-source licensing comes with real (if usually minor) obligations; know whether software you depend on is permissive, copyleft, or public domain.
  • The file system is organized predictably under a single root (/), with well-known top-level directories (/etc, /home, /usr, /var, /bin, /sbin, /dev, /media, /mnt) serving consistent roles across distros.
  • Absolute paths (starting with /) are unambiguous; relative paths depend on the current working directory — know the difference to avoid cd and file-access mistakes.
  • A small set of command-line tools (cat, less, head, tail, nano, pipes, chmod, man) cover the overwhelming majority of everyday file-reading, file-editing, and troubleshooting needs.
  • Built-in documentation (--help, man, man -k) should be the first stop before guessing at command syntax, given how unforgiving Linux administration can be of small mistakes.

Quick-Reference Command Table

CommandPurpose
pwdPrint current working directory
lsList directory contents
cd <path>Change directory (absolute path with /, relative without)
tree -L 1Show directory structure one level deep
which <cmd>Show the file-system path of a command’s binary
echo $PATHShow directories searched for executable commands
cat <file>Print (or concatenate) file contents
cat -n <file>Print file contents with line numbers
less <file>Page through a long file interactively
head -n N <file>Print the first N lines of a file
tail -n N <file>Print the last N lines of a file
tail -f <file>Continuously follow a growing file
nano <file>Open a file in the nano text editor
chmod +x <file>Make a file executable
./<script>.sh &Run a script in the background
fg %1Bring a background job back to the foreground
man <command>Open a command’s manual page
man -k "<keyword>"Search man page descriptions by keyword
sudo <command>Run a command with root privileges
ssh user@hostOpen a remote shell session over SSH

Checklist for Getting Started with Linux

  • Choose an installation method appropriate to your context (WSL, bootable USB, VM, or cloud instance).
  • Learn to distinguish absolute vs. relative paths before navigating unfamiliar systems.
  • Get comfortable with cat, less, head, and tail for reading files of any size.
  • Adopt a plaintext-safe editor (nano or vim) — never a word processor — for scripts and configuration files.
  • Understand file permissions well enough to use chmod and sudo correctly and safely.
  • Practice using man (including -k search) before resorting to guesswork on unfamiliar commands.

Search Terms

linux · systems · administration · networking · security · system · command · installing · kernel

Interested in this course?

Contact us to book it or get a custom training plan for your team.