About This Course

This course is designed for university students who are new to Linux but have some familiarity with programming concepts. Over 10 sessions, you'll learn to use Linux as your daily driver operating system, master the command line, and gain essential system administration skills.

What You'll Learn

  • Navigate and control Linux entirely from the command line
  • Install and manage software independently
  • Perform system administration tasks
  • Write shell scripts for automation
  • Use Git for version control
  • Run Docker containers

How This Course Is Organized

The course is divided into four parts:

  1. Foundations — Introduction, installation, and desktop environment
  2. CLI Mastery — File system, commands, text processing, permissions
  3. System Administration — Packages, processes, scripting, networking
  4. DevOps Introduction — Git and Docker basics

The course concludes with a capstone project where you'll apply all your skills to set up a personal Linux server.

Prerequisites

  • A Windows laptop (or any computer you can install Linux on)
  • An 8GB+ USB drive (for dual-boot installation)
  • Basic familiarity with programming concepts
  • No prior Linux or command-line experience required!

Let's Get Started

Ready to discover the power of Linux? Let's begin with Chapter 1.

Chapter 1: Introduction & Philosophy

Learning Objectives

By the end of this chapter, you will be able to:

  • Understand what Linux is and its history
  • Explain the open-source philosophy and why it matters
  • Identify different Linux distributions and their use cases
  • Recognize why Linux is essential for developers
  • Navigate the Linux ecosystem confidently

Prerequisites

None! This is your starting point. Welcome to Linux!


What Is Linux?

The Kernel, Not the Operating System

Technically speaking, Linux is a kernel — the core component that manages hardware resources and enables software to communicate with the CPU, memory, and devices. The complete operating system that you use is better described as GNU/Linux, combining:

  • The Linux kernel (created by Linus Torvalds in 1991)
  • GNU tools (shell, file utilities, compilers — started by Richard Stallman in 1983)
  • Desktop environments (GNOME, KDE, XFCE)
  • Package managers (dnf, apt, pacman)

Analogy: If an OS were a car, Linux would be the engine, and GNU would be the steering wheel, transmission, and other systems that make it drivable.

A Brief History

timeline
    title Linux History Timeline
    1983 : Richard Stallman announces GNU project
         : Free Software Foundation founded
    1991 : Linus Torvalds creates Linux kernel
         : First version released (0.01)
    1992 : GNU + Linux = Complete OS
    1993 : Debian founded
    1994 : Red Hat founded
    1996 : KDE launched (first desktop environment)
    1999 : GNOME project starts
    2003 : Fedora project launches
    2004 : Ubuntu first release
    2015 : Fedora becomes flagship of Red Hat

1991: A young Finnish student named Linus Torvalds posted a message to a newsgroup:

"I'm doing a (free) operating system (just a hobby, won't be big and professional like GNU)..."

— Linus Torvalds, August 1991

That "hobby" now powers:

  • 100% of the world's top 500 supercomputers
  • 96% of the world's web servers
  • All Android devices (over 3 billion active users)
  • Most cloud infrastructure (AWS, Google Cloud, Azure)
  • The International Space Station computers

Linux vs. Windows vs. macOS

FeatureLinuxWindowsmacOS
Source CodeOpen (anyone can view/modify)Closed (proprietary)Closed (proprietary)
CostFree$100-$200+Included with Apple hardware
CustomizationUnlimitedLimitedLimited
Package ManagementCentral repositoriesManual downloadsApp Store + manual
PrivacyFull controlData collection concernsData collection concerns
DevelopmentNative environmentWSL/secondaryUnix-based but closed
GamingImproving rapidly (Proton/Steam)ExcellentModerate

The Open-Source Philosophy

"Free Software" Doesn't Mean "Zero Cost"

In the open-source world, "free" refers to freedom, not price. The Free Software Movement defines four essential freedoms:

  1. Freedom 0: The freedom to run the program as you wish, for any purpose
  2. Freedom 1: The freedom to study how the program works, and change it
  3. Freedom 2: The freedom to redistribute copies so you can help others
  4. Freedom 3: The freedom to distribute copies of your modified versions

Think of it like a recipe: When you buy a recipe book, you can cook the food (Freedom 0), modify the recipe (Freedom 1), share the original with friends (Freedom 2), and share your improved version (Freedom 3).

Open Source vs. Free Software

PhilosophyFocusKey Organization
Free SoftwareEthics, user rightsFree Software Foundation (FSF)
Open SourcePractical benefits, methodologyOpen Source Initiative (OSI)

Both movements support the same software, but with different emphasis:

  • Free Software: "It's morally wrong to deny users these freedoms"
  • Open Source: "This development method produces better software"

Why Open Source Matters for You

1. Learning and Transparency

You can read the source code of any tool you use. Want to know how ls works? Just read it!

# View the source code of core utilities
# These are the actual programs you'll use daily
$ cat /usr/bin/ls

2. Security Through Transparency

With millions of eyes on the code, vulnerabilities are found and fixed quickly. No security through obscurity.

3. No Vendor Lock-in

If a project dies or goes in a direction you don't like, you can fork it and continue development.

4. Career Opportunities

Open source is your public portfolio. Contributing to projects demonstrates real skills to employers.


Why Linux for Developers?

1. Your Production Environment

Linux runs the internet. When you deploy code, it's almost certainly going to Linux. Developing on Linux eliminates environment mismatches.

2. Native Developer Tools

Linux has everything you need built-in:

# Package managers give you instant access to tools
$ sudo dnf install python3 nodejs git docker
# One command. No downloads, no installers, no restarts.

3. The Terminal Is Power

The command line is:

  • Faster than GUI for most operations
  • Scriptable — automate repetitive tasks
  • Remote-friendly — work on servers anywhere
  • Documentable — copy commands to share knowledge

4. Better Resource Management

Linux respects your RAM and CPU. No forced updates, no background processes you can't disable.

5. Containerization and Cloud

Docker, Kubernetes, and cloud-native technologies were built on Linux. You'll use them every day as a developer.


Choosing a Distribution

Linux comes in different "flavors" called distributions (or "distros"). Each includes the Linux kernel plus different tools, desktop environments, and philosophies.

Distribution Categories

graph TD
    A[Linux Distributions] --> B[Beginner-Friendly]
    A --> C[Intermediate]
    A --> D[Advanced]

    B --> B1[Fedora Workstation]
    B --> B2[Ubuntu]
    B --> B3[Linux Mint]

    C --> C1[Debian]
    C --> C2[openSUSE]
    C --> C3[Pop!_OS]

    D --> D1[Arch Linux]
    D --> D2[Gentoo]
    D --> D3[Void Linux]

Our Course Distributions: Fedora & Debian

AspectFedoraDebian
PhilosophyCutting-edge, latest softwareStable, rock-solid
Release CycleEvery ~6 monthsWhen ready (2-3 years)
Package Managerdnf (RPM-based)apt (DEB-based)
Best ForNew hardware, developers, enthusiastsServers, production, stability
Parent/ChildUpstream for RHELUpstream for Ubuntu, Mint
CommunityRed Hat sponsoredCommunity-driven

Fedora Workstation is recommended for this course because:

  • Latest software versions
  • Excellent GNOME integration
  • Developer-focused
  • Sponsored by Red Hat (major employer)

Debian is ideal for:

  • Learning server administration
  • Production deployments
  • Understanding the foundation of Ubuntu-based systems

Other Notable Distributions

DistributionUse Case
UbuntuMost popular beginner distro, based on Debian
Linux MintWindows-like experience, very beginner-friendly
Pop!_OSUbuntu-based, optimized for developers
Arch LinuxRolling release, DIY, advanced users
Kali LinuxPenetration testing and security
Raspberry Pi OSSingle-board computers, education

The Linux Ecosystem

Desktop Environments

Unlike Windows or macOS, Linux lets you choose your complete desktop experience:

Desktop EnvironmentCharacteristicsResource UsageBest For
GNOMEModern, gesture-based, default on FedoraMediumMost users, modern workflows
KDE PlasmaHighly customizable, Windows-likeLow-MediumPower users, Windows refugees
XFCELightweight, traditionalLowOlder hardware, minimalists
CinnamonTraditional, similar to Windows 7LowWindows users

This course uses GNOME — the default on Fedora and Debian, modern, and well-documented.

Package Managers

Package ManagerDistributions
dnf (Fedora)Fedora, RHEL, CentOS
apt (Debian)Debian, Ubuntu, Linux Mint
pacman (Arch)Arch Linux, Manjaro
zypperopenSUSE

Summary

Key Takeaways:

  • Linux is a kernel, part of the GNU/Linux operating system
  • Open source means freedom to use, study, modify, and share software
  • Linux dominates servers, cloud, supercomputers, and mobile (Android)
  • Fedora (cutting-edge) and Debian (stable) are our course distributions
  • GNOME is the desktop environment we'll use
  • Linux is essential for developers — it's your production environment

Next Up: You'll install Linux on your machine in Chapter 2!


Chapter Quiz

Test your understanding of Linux philosophy and fundamentals:


Exercises

Exercise 1: Explore the Linux Timeline

Visit the following resources and identify three facts about Linux history that surprised you:

  1. Watch Linus Torvalds' 2016 TED Talk: "The mind behind Linux"
  2. Browse the Linux Foundation's history page
  3. Check out the Unix timeline

Deliverable: Write a brief paragraph about the most surprising fact and why it matters.

Exercise 2: Compare Fedora and Debian

Research the latest versions of both distributions and answer:

  1. What are the kernel versions in each?
  2. What desktop environment do they default to?
  3. Name one advantage of each distribution
  4. Which one would you choose for your personal laptop and why?

Deliverable: A comparison table or bulleted list.

Exercise 3: Find Open Source Around You

List 5 technologies or services you use that are open source. For each, identify:

  1. The project name
  2. What programming language it's written in
  3. One way you could contribute (even as a beginner)

Examples to get you started: Firefox, VLC, Blender, VS Code, Python...

Exercise 4: Philosophy Reflection

Answer this question in 100-200 words:

"Why does the freedom to study and modify software matter for a developer? How would your career be different if all software were proprietary?"


Expected Output

After completing these exercises, you should have:

  1. Timeline Notes: A list of 3+ interesting facts from Linux history
  2. Distribution Comparison: A documented choice between Fedora and Debian with reasoning
  3. Open Source Inventory: A list of 5+ open source projects you use
  4. Philosophy Reflection: A written reflection on software freedom

Further Reading


Discussion Questions

  1. Why do you think all supercomputers run Linux?
  2. What are the trade-offs between "bleeding edge" (Fedora) and "stable" (Debian) distributions?
  3. How does open source change the relationship between software creators and users?
  4. What would happen if the Linux kernel suddenly became proprietary?

Chapter 2: Installation

Learning Objectives

By the end of this chapter, you will be able to:

  • Create a bootable Linux USB drive
  • Understand disk partitioning basics
  • Install Linux in a dual-boot configuration
  • Set up Linux in a Virtual Machine
  • Configure your system after first boot

Prerequisites

  • Completed Chapter 1
  • 8GB+ USB drive (for bootable media)
  • Backed up important data (always backup before disk operations!)
  • Internet connection

Pre-Installation Checklist

Hardware Requirements

ComponentMinimumRecommended
CPU64-bit processorModern multi-core
RAM4 GB8 GB+
Storage20 GB free space50 GB+ SSD
USB4 GB8 GB+ (for bootable media)

Know Your System

Before installing, identify your current setup:

# On Windows: Open System Information
# Press Win+R, type "msinfo32", press Enter

# Note down:
# - System Type (64-bit or 32-bit) - You need 64-bit
# - Total RAM
# - Disk partitions and free space

Backup Your Data

WARNING: Disk operations can result in data loss. Always backup before installing.

  1. External Drive: Copy important files to external storage
  2. Cloud Backup: Use Google Drive, Dropbox, OneDrive
  3. Create a System Image: Windows has built-in backup tools

Choose Your Installation Method

flowchart TD
    A[Installation Method] --> B{Primary OS?}
    B -->|Yes, want Windows+Linux| C[Dual-Boot]
    B -->|No, dedicated to Linux| D[Replace Windows]
    B -->|Unsure/Safe option| E[Virtual Machine]

    C --> F[Recommended: Best performance]
    D --> G[Advanced: Complete commitment]
    E --> H[Safest: No risk to Windows]

Recommendation for this course: Start with Dual-Boot (preferred) or Virtual Machine (safer).


Creating a Bootable USB

Step 1: Download the ISO

Fedora Workstation:

https://fedoraproject.org/workstation/

Debian:

https://www.debian.org/distrib/

Choose the 64-bit ISO image (usually ~2-3 GB).

This ensures your download wasn't corrupted.

On Fedora/Linux:

# Download checksum file
$ wget https://fedoraproject.org/static/checksums/Fedora-Workstation-40-CHECKSUM

# Verify
$ sha256sum -c Fedora-Workstation-40-CHECKSUM

On Windows:

# Open PowerShell in Downloads folder
certutil -hash Fedora-Workstation-Live-x86_64-40.iso SHA256

Compare the output with the checksum on the download page.

Step 3: Write to USB

Option A: Using BalenaEtcher (Cross-Platform, Easiest)

  1. Download from balena.io/etcher
  2. Open Etcher
  3. Flash from file: Select your downloaded ISO
  4. Select target: Choose your USB drive
  5. Flash! (this will erase all data on the USB)

Option B: Using Fedora Media Writer (Fedora Only)

  1. Install Fedora Media Writer from the website
  2. Select "Fedora Workstation 40"
  3. Choose your USB drive
  4. Write

Option C: Using dd (Linux/Mac, Advanced)

# WARNING: This can destroy data if you get the device wrong!

# Find your USB device
$ lsblk

# Unmount the drive
$ sudo umount /dev/sdX

# Write the ISO (replace X with your device letter)
$ sudo dd if=Downloads/fedora.iso of=/dev/sdX bs=4M status=progress && sync

⚠️ CRITICAL: Be absolutely certain you're writing to the USB drive, not your hard drive!


Understanding Partitions

What Are Partitions?

A partition is a logical division of a hard drive. Think of it like dividing a large room into smaller rooms — each room can have different furniture (operating systems) and purposes.

graph LR
    A[Physical Disk<br>/dev/sda] --> B[Partition 1<br>/dev/sda1<br>Windows EFI]
    A --> C[Partition 2<br>/dev/sda2<br>Windows C: Drive]
    A --> D[Partition 3<br>/dev/sda3<br>Linux Root /]
    A --> E[Partition 4<br>/dev/sda4<br>Linux Swap]

Partition Types

TypePurposeSize Recommendation
EFI System PartitionBoot files (UEFI)512 MB
Root (/)System files, applications30-50 GB minimum
/homeUser data, documentsRemainder of disk
SwapVirtual memory (hibernation)Equal to RAM size

File Systems

File SystemDescriptionUse Case
ext4Standard Linux filesystemMost installations
btrfsAdvanced features, snapshotsFedora default, data safety
xfsHigh performance, large filesServers, large datasets
NTFSWindows filesystemWindows compatibility

Partition Layout Example

Physical Disk (250 GB SSD)
├── /dev/sda1 (512 MB)  - EFI System Partition (Windows boot)
├── /dev/sda2 (100 GB)  - Windows C: Drive
├── /dev/sda3 (100 GB)  - Linux Root (/) with btrfs
└── /dev/sda4 (8 GB)    - Linux Swap (for hibernation)

Dual-Boot Installation (Fedora/Debian)

What is Dual-Boot?

Dual-booting allows you to have both Windows and Linux on the same computer. At startup, you choose which OS to boot.

Pros:

  • Best of both worlds
  • Full hardware performance
  • Learn Linux while keeping Windows safety net

Cons:

  • Requires disk space
  • More complex installation
  • Boot configuration can be tricky

Step 1: Prepare Windows

Shrink Windows Partition

  1. Open Disk Management in Windows:

    Right-click Start → Disk Management
    
  2. Right-click your C: drive → Shrink

  3. Enter size to shrink (at least 50 GB, recommended 100 GB+)

  4. Click Shrink — This creates "Unallocated Space"

Note: If "Shrink" is grayed out or shows very little space:

  • Disable Windows fast startup: Power Options → Choose what power buttons do
  • Disable hibernation: powercfg /hibernate off (Run as Administrator)
  • Defragment your drive

Disable Fast Startup (Important!)

Windows "Fast Startup" can cause problems with dual-boot:

  1. Open Control PanelPower Options
  2. Click "Choose what the power buttons do"
  3. Click "Change settings that are currently unavailable"
  4. Uncheck "Turn on fast startup"
  5. Save changes

Step 2: Boot from USB

  1. Insert your bootable USB

  2. Restart your computer

  3. Enter boot menu (usually one of these keys):

    • F12 — Dell, Lenovo, many others
    • F10 — HP
    • F2 or Del — Some systems
    • Esc — Some systems
    • Hold Option ⌥ — Mac
  4. Select your USB drive from the boot menu

Step 3: Install Fedora

Boot Menu

  1. Select "Start Fedora Workstation 40" (or your version)
  2. Press Enter to boot
  3. Select "Install to Hard Drive" from the desktop

Installation Steps

1. Language Selection

  • Select your language and keyboard
  • Click Continue

2. Installation Summary

You'll see several sections:

SectionAction
LOCALIZATIONSet your time zone
SOFTWAREAccept defaults (or add development tools)
SYSTEMConfigure installation destination
USERCreate your user account

3. Installation Destination (CRITICAL!)

Click Installation Destination → You'll see your disks:

Disk: 250 GB
├── sda1: 512 MB   (EFI)
├── sda2: 150 GB   (Windows C:)
└── Free Space: 99.5 GB (Unallocated)

Select your disk and choose:

  • Automatically configure partitioning
  • OR select "Free Space" and choose Custom for control

4. User Creation

  • Full Name: Your actual name
  • Username: lowercase, no spaces (e.g., jdoe)
  • Password: Use a strong password
  • ☑️ Make this user administrator

5. Begin Installation

Click Begin Installation and wait 10-30 minutes.

Step 4: First Boot

  1. Remove USB when prompted

  2. Reboot

  3. You should see GRUB boot menu:

    Fedora Workstation (default)
    Advanced options for Fedora
    Windows Boot Manager (on /dev/sda1)
    
  4. If you don't see Windows option, don't panic — see Troubleshooting below

Step 5: Post-Install Configuration

On first boot, you'll go through initial setup:

  1. Privacy Settings: Enable or disable location services
  2. Online Accounts: Connect Google, Nextcloud, etc. (optional)
  3. Software: Wait for updates to install

Virtual Machine Installation

What is a Virtual Machine?

A VM runs Linux inside your current OS as a regular application. It's like having a computer within your computer.

Pros:

  • Safest option — No risk to Windows
  • Easy to delete and start over
  • Great for testing and learning

Cons:

  • Slower performance
  • Limited graphics/Gaming
  • Shared resources with host
SoftwareCostLicenseBest For
VirtualBoxFreeOpen SourceBeginners, cross-platform
VMware Workstation PlayerFreeProprietaryWindows host, better performance
GNOME BoxesFreeOpen SourceLinux host, simple
QEMU/KVMFreeOpen SourceAdvanced users, best performance

Step 1: Install VirtualBox

Download from virtualbox.org

Step 2: Create a New VM

  1. Click New
  2. Name: Fedora Linux → Type: Linux → Version: Fedora 64-bit
  3. Memory: At least 4096 MB (4 GB)
  4. Create Virtual Hard Disk:
    • VDI format
    • Dynamically allocated
    • At least 50 GB

Step 3: Configure VM Settings

System → Motherboard:

  • Enable EFI (special features)
  • Base Memory: 4096 MB+
  • Processor: 2+ CPUs

Display:

  • Video Memory: 128 MB
  • Enable 3D Acceleration

Storage:

  • Click "Adds optical drive"
  • Select your Fedora ISO file

Network:

  • Attached to: NAT

Step 4: Install Linux

  1. Start the VM
  2. Follow the same installation steps as dual-boot
  3. The VM will automatically use the entire virtual disk

Step 5: Install Guest Additions (Optional)

After installation, this improves performance:

  1. In VM menu: DevicesInsert Guest Additions CD image
  2. In Linux terminal:
    $ sudo dnf install virtualbox-guest-additions
    $ reboot
    

First Boot Configuration

Initial Setup Wizard

After installation boots, complete these steps:

1. Welcome to GNOME

Follow the on-screen prompts to:

  • Select language
  • Connect to WiFi
  • Set privacy settings

2. System Updates

# Update your system immediately after first boot
$ sudo dnf upgrade

Or via GNOME Software: Updates → Download & Install

3. Install Essential Software

# Fedora - Essential development tools
$ sudo dnf install @development-tools
$ sudo dnf install vim neovim git code
$ sudo dnf install ffmpeg vlc gimp
# Debian - Equivalent packages
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install build-essential git vim
$ sudo apt install vlc gimp

4. Enable Flathub (Additional Software)

GNOME Software can access Flathub, a large software repository:

  1. Open GNOME Software
  2. Click the menu → Software Repositories
  3. Enable Flathub

Troubleshooting

Windows Not Showing in Boot Menu

If GRUB doesn't show Windows:

# Boot into Linux and update GRUB
$ sudo os-prober
$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
# For UEFI:
$ sudo grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg

Computer Boots Directly to Windows

If you can't access Linux at all:

  1. Boot into BIOS/UEFI (F2, Del, F10)
  2. Find Boot Order settings
  3. Change boot order to prioritize Linux boot manager
  4. Save and exit

Graphics/Display Issues

If the display is wrong:

# For NVIDIA cards
$ sudo dnf install rpmfusion-free-release-tainted
$ sudo dnf install akmod-nvidia xorg-x11-drv-nvidia-cuda

WiFi Not Working

Some proprietary WiFi drivers need manual installation:

# Identify your WiFi card
$ lspci | grep -i network

# Install extra drivers
$ sudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm
$ sudo dnf update

Summary

Key Takeaways:

  • Backup first — Always backup before disk operations
  • Dual-boot for performance, VM for safety
  • Shrink Windows to create space for Linux
  • UEFI + GPT is the modern standard (not BIOS/MBR)
  • First boot: Update system, install essential tools
  • GRUB manages boot selection between OSes

Installation Methods Compared:

MethodPerformanceSafetyComplexity
Dual-Boot⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Virtual Machine⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

Chapter Quiz

Test your understanding of Linux installation methods and concepts:


Exercises

Exercise 1: Pre-Installation Assessment

Create a document answering:

  1. What is your current system specification?

    • CPU model and cores
    • RAM amount
    • Disk size and free space
    • Graphics card
  2. Which installation method will you use and why?

    • Dual-boot, VM, or replace Windows?
    • Justify your choice
  3. How much space will you allocate to Linux?

Deliverable: A brief document with your system specs and installation plan.

Exercise 2: Create a Bootable USB

  1. Download Fedora Workstation ISO
  2. Verify the checksum (SHA256)
  3. Create a bootable USB using BalenaEtcher
  4. Boot from the USB (don't install yet, just verify it works)

Deliverable: A photo/screenshot of the Fedora boot menu.

Exercise 3: Partition Planning

Draw a diagram showing how you would partition a 500 GB disk for dual-boot:

  • Windows: 200 GB
  • Linux: Remaining space

Show the partition layout with:

  • Device names (/dev/sda1, /dev/sda2, etc.)
  • Partition types (EFI, NTFS, ext4/btrfs, swap)
  • Mount points (/, /home, swap)

Deliverable: A diagram (ASCII art or hand-drawn photo).

Exercise 4: Complete Installation Lab

Perform a full installation:

If Dual-Boot:

  1. Shrink Windows partition
  2. Install Linux alongside Windows
  3. Verify both OSes boot correctly

If VM:

  1. Create a virtual machine
  2. Install Linux inside it
  3. Install guest additions

Deliverable:

  • Screenshot of both Windows and Linux boot menus
  • Screenshot of Linux desktop after first boot
  • List any issues encountered and how you solved them

Expected Output

After completing these exercises, you should have:

  1. System Assessment: Documented specs and installation plan
  2. Bootable USB: Working Fedora or Debian USB drive
  3. Partition Diagram: Clear understanding of disk layout
  4. Working Linux Installation: System you can boot and use

Further Reading


Discussion Questions

  1. Why might someone choose a VM over dual-boot, or vice versa?
  2. What are the risks of dual-booting? How can they be mitigated?
  3. Why does Linux use different file systems (ext4, btrfs) than Windows (NTFS)?
  4. How would you recover if the installation failed and Windows wouldn't boot?

Chapter 3: GNOME Desktop

Learning Objectives

By the end of this chapter, you will be able to:

  • Navigate the GNOME desktop environment confidently
  • Use the Activities overview and application launcher
  • Customize your desktop with themes and extensions
  • Manage windows, workspaces, and virtual desktops
  • Install applications via GNOME Software

Prerequisites

  • Completed Chapter 2
  • Linux installed and running
  • Working internet connection

GNOME Overview

What is GNOME?

GNOME (GNU Network Object Model Environment) is a complete desktop environment for Linux. It provides:

  • Graphical User Interface (GUI) — Point-and-click interaction
  • Core Applications — File manager, web browser, terminal, settings
  • System Integration — Manages displays, audio, notifications

GNOME Philosophy

GNOME follows a modern, minimal design philosophy:

graph LR
    A[GNOME Design Principles] --> B[Simplicity]
    A --> C[Consistency]
    A --> D[Accessibility]
    A --> E[Internationalization]

    B --> B1[Clean, uncluttered interface]
    C --> C1[Same patterns everywhere]
    D --> D1[Usable by everyone]
    E --> E1[Available in 40+ languages]

Key Design Elements:

  • Top Bar: System status, clock, notifications
  • Activities Overview: Application launcher and window manager
  • Dash: Favorite applications dock
  • Dynamic Workspaces: Automatic virtual desktop management

GNOME vs Other Desktop Environments

FeatureGNOMEKDE PlasmaXFCE
PhilosophyModern, minimalHighly customizableTraditional, lightweight
Resource UsageMediumLow-MediumLow
Default onFedora, Debian, UbuntuKubuntu, KDE neonXubuntu, Mint XFCE
Touch/GesturesExcellentGoodBasic
Learning CurveMediumLow-MediumLow

Desktop Navigation

The GNOME Layout

┌─────────────────────────────────────────────────────────┐
│  [Activities] [App Name]       □      🌙 📶 🔋 2:45 PM  │ ← Top Bar
├─────────────────────────────────────────────────────────┤
│                                                         │
│                                                         │
│                    Desktop Area                          │
│                    (or Windows)                          │
│                                                         │
│                                                         │
├─────────────────────────────────────────────────────────┤
│              [🔍]  [📁]  [🖥️]  [⚙️]  [📧]                │ ← Dash
└─────────────────────────────────────────────────────────┘

The Top Bar

The top bar is your command center:

┌─────────────────────────────────────────────────────────────────┐
│ [Activities] [Application Menu]      [Status] [Calendar] [Sys] │
└─────────────────────────────────────────────────────────────────┘
      ↓              ↓                      ↓          ↓
   Click to see   Current app's         Volume,     Notifications,
   Activities     menu (if open)        network,    calendar, power
                  (or "Activities")     battery

Components:

  • Activities Button (top-left): Opens overview
  • Application Menu (center): Current app's menu
  • Status Indicators (right): System tray icons
  • Clock (right): Click for calendar and notifications
  • System Menu (far-right): Settings, power, logout

Try this: Click the clock to see the calendar and notifications!

Keyboard Shortcuts (Essential!)

Master these to become efficient:

ActionShortcut
Open Activities OverviewSuper (Windows key) or Alt+F1
Application SearchSuper, then type
Switch WindowsAlt+Tab
Switch WorkspacesSuper+PageUp/PageDown
Show All ApplicationsSuper+A
Open TerminalSuper+Enter (if configured)
Close WindowAlt+F4 or Super+Q
Hide WindowSuper+H
Lock ScreenSuper+L
ScreenshotPrintScreen

💡 Pro Tip: The Super key is the Windows key on most keyboards. macOS users can use Command in most cases.


Activities Overview

What is Activities Overview?

The Activities Overview is GNOME's central hub. Press the Super key to activate it.

flowchart TD
    A[Activities Overview] --> B[Application Grid]
    A --> C[Window Selector]
    A --> D[Workspace Switcher]
    A --> E[Search Bar]

    B --> B1[Click to launch apps]
    C --> C1[Click to focus windows]
    D --> D1[Switch between desktops]
    E --> E1[Type to search anything]

Opening Applications

  1. Press Super to open Activities
  2. Click the grid icon (bottom-left) to show All Applications
  3. Scroll or search to find your app
  4. Click to launch

Switching Between Windows

  1. Press Super for Activities
  2. Click on any window thumbnail to focus it
  3. Or press Alt+Tab for quick switching

Managing Workspaces

  1. Press Super for Activities
  2. Look at the right side — you'll see workspaces
  3. Drag windows between workspaces
  4. Click a workspace to switch to it

Search from Activities

The search bar in Activities is powerful:

# Type in the search bar to find:
> firefox          # Launch applications
> "document"       # Find files by name
> "wifi"           # Search settings
> calc             # Calculator
>                 # Web search (if enabled)

Search Categories:

  • Applications
  • Settings
  • Files (indexed in your home directory)
  • Calculator (type equations)
  • Web search (optional)

Pinned Favorites (Dash)

The Dash is the dock at the bottom of the screen with your favorite apps.

To add a favorite:

  1. Open Activities → All Applications
  2. Right-click an app
  3. Select "Add to Favorites"

To remove a favorite:

  1. Right-click the app in the Dash
  2. Select "Remove from Favorites"

Window Management

Window Actions

ActionMouseKeyboard
Move windowDrag title barAlt+F7 then arrows
Resize windowDrag edges/cornersAlt+F8 then arrows
MaximizeClick maximize buttonSuper+↑ or Alt+F10
UnmaximizeClick unmaximizeSuper+↓
Minimize/HideClick minimizeSuper+H
CloseClick × or Alt+F4Alt+F4
Always on TopRight-click title barNot available by default

Tiling Windows (Snap to Edge)

Drag a window to the edge of the screen to tile it:

┌──────────────────────────────────────────────┐
│         Drag to left edge:                   │
│ ┌──────────┬─────────────────────────────────┐│
│ │          │                                 ││
│ │ Window 1 │        Empty / Window 2         ││
│ │  (50%)   │            (50%)                ││
│ └──────────┴─────────────────────────────────┘│
└──────────────────────────────────────────────┘

         Drag to corner: Quarter screen

Keyboard Tiling:

  • Super+← → Left half
  • Super+→ → Right half
  • Super+↑ → Maximize
  • Super+↓ → Restore/Minimize

Virtual Workspaces

GNOME uses dynamic workspaces — they're created and destroyed as needed.

Understanding Workspaces:

Workspace 1: Browser, Terminal
Workspace 2: Code Editor, File Manager
Workspace 3: Music, Chat

Workspace Shortcuts:

ActionShortcut
Switch to next workspaceSuper+PageDown
Switch to previous workspaceSuper+PageUp
Move window to next workspaceSuper+Shift+PageDown
Open new workspaceJust drag a window to empty space

Customization (Themes, Extensions)

GNOME Settings Overview

Open Settings via:

  • System MenuSettings (gear icon)
  • Activities → Search "Settings"
  • Terminal: gnome-control-center

Appearance Settings

Settings → Appearance:

┌─────────────────────────────────────────┐
│  Appearance                             │
├─────────────────────────────────────────┤
│  Style:                                 │
│  ○ Light   ● Dark   ○ Dark with Accent  │
│                                         │
│  Accent Color:                          │
│  ● Blue   ○ Green   ○ Orange, etc.      │
│                                         │
│  Background: [Change...]                │
│  Lock Screen: [Change...]               │
│  Application Icons: [Adwaita]           │
└─────────────────────────────────────────┘

Dark Mode:

# Terminal command to toggle dark mode
$ gsettings set org.gnome.desktop.interface gtk-theme 'Adwaita-dark'

Desktop Background

To change wallpaper:

  1. Open Settings → Appearance
  2. Click Background or Lock Screen
  3. Choose from defaults or click Add Picture...

Supported formats: JPG, PNG, WebP, SVG

GNOME Extensions

Extensions add functionality to GNOME. Think of them like browser extensions for your desktop.

ExtensionPurpose
Dash to DockTransform the Dash into a configurable dock
AppIndicator/KStatusNotifierItemTray icons (Discord, Spotify, etc.)
ArcMenuWindows-style start menu
Blur my ShellBlur effects on overview, dash
GSConnectPair Android phone with desktop
CaffeinePrevent screen from automatically locking

Installing Extensions

Method 1: GNOME Software (Easiest)

  1. Open GNOME Software
  2. Search for "Extensions" app
  3. Install "Extensions" (the manager app)
  4. Browse and install extensions directly

Method 2: Web Browser

  1. Visit extensions.gnome.org
  2. Browse extensions
  3. Toggle switch to install (requires browser extension)
  4. Open Extensions app to manage

Method 3: Terminal (Advanced)

# Install GNOME Shell integration
$ sudo dnf install gnome-shell-extensions

# Install specific extensions
$ sudo dnf install gnome-shell-extension-dash-to-dock
$ sudo dnf install gnome-shell-extension-appindicator

Managing Extensions

Open the Extensions app to:

  • Enable/disable extensions
  • Configure extension settings
  • Remove unwanted extensions

⚠️ Warning: Some extensions can cause system instability. Install only what you need.

Font Customization

Settings → Fonts:

SettingDescriptionDefault
Interface TextUI fontCantarell 11
Document TextDocument readingSans 11
Monospace TextCode, terminalMonospace 11
Legacy Window TitlesOlder appsSans 11
AntialiasingSmooth edgesSubpixel
Scaling FactorText size1.0

Terminal:

# Change interface font size
$ gsettings set org.gnome.desktop.interface document-font-name 'Sans 12'

# Change monospace font
$ gsettings set org.gnome.desktop.interface monospace-font-name 'Monospace 12'

System Settings

Essential Settings to Configure

1. Network (WiFi & Ethernet)

Settings → Network

# Quick status check in terminal
$ nmcli connection show
$ nmcli device wifi list

Connect to WiFi:

  1. Click the network icon in top bar
  2. Select your network
  3. Enter password

Forgetting a network:

  1. Settings → Network
  2. Click the gear icon next to the network
  3. Click Forget

2. Display & Monitors

Settings → Display

  • Resolution: Usually auto-detected
  • Scale: For high-DPI (4K/Retina) displays
  • Refresh Rate: Higher = smoother motion

Multiple Monitors:

┌────────────────┐  ┌────────────────┐
│   Display 1    │  │   Display 2    │
│   (Primary)    │  │   (Secondary)  │
└────────────────┘  └────────────────┘
       [Set as Primary] [Arrange]

Arrangement: Drag displays to match physical layout.

3. Sound & Volume

Settings → Sound

SettingPurpose
OutputSpeakers/headphones
InputMicrophone
System SoundsAlert sounds
VolumeMaster volume level

Quick Mute: Click volume icon → select Mute

4. Power & Battery

Settings → Power

ProfileUse Case
Balanced PowerDefault for most users
Power SaverExtend battery life
PerformanceMaximum performance (plugged in)

Battery Saver:

# Check battery status
$ upower -i /org/freedesktop/UPower/devices/battery_BAT0

5. Privacy

Settings → Privacy

Important settings:

  • Location Services: Disable for privacy
  • Camera & Microphone: Control app access
  • Usage & History: Clear usage data
  • Screen Lock: Set timeout and password requirement

6. Users

Settings → Users

  • Add User: Create additional accounts
  • Automatic Login: Skip login screen (convenient but less secure)
  • Parental Controls: Limit app usage (for families)

⚠️ Security Tip: Disable automatic login for laptops and shared computers.


Installing GUI Applications

GNOME Software

GNOME Software is your GUI app store:

┌─────────────────────────────────────────┐
│  GNOME Software                         │
├─────────────────────────────────────────┤
│  [Explore] [Installed] [Updates]        │
│                                         │
│  Featured Applications:                 │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐ │
│  │ Firefox │  │  VLC    │  │  GIMP   │ │
│  │  Browser│  │ Player  │  │  Image  │ │
│  │ [Install]│ [Install]│ [Install]│ │
│  └─────────┘  └─────────┘  └─────────┘ │
└─────────────────────────────────────────┘

To install:

  1. Open GNOME Software
  2. Browse or search for an app
  3. Click Install

To remove:

  1. Click Installed tab
  2. Find the app
  3. Click Remove

Flatpak (Flathub)

Many apps are available as Flatpaks — containerized packages that work on any distro.

# Install Flatpak support (Fedora has it by default)
$ sudo dnf install flatpak

# Add Flathub repository
$ sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo

# Install an app
$ flatpak install flathub com.spotify.Client

# Run the app
$ flatpak run com.spotify.Client

Popular Flathub Apps:

  • Spotify
  • Discord
  • VS Code
  • LibreOffice
  • OBS Studio
  • Steam

Finding Applications

CategoryRecommended Apps
Web BrowsersFirefox, Chromium, Brave
OfficeLibreOffice, OnlyOffice
GraphicsGIMP, Inkscape, Krita
MediaVLC, Audacity, OBS
CommunicationDiscord, Thunderbird
DevelopmentVS Code, Sublime Text

Summary

Key Takeaways:

  • GNOME is the default desktop on Fedora and Debian
  • Activities Overview (Super key) is the central hub
  • Workspaces provide virtual desktops for organization
  • Extensions add functionality (use sparingly)
  • GNOME Software is the GUI app store
  • Keyboard shortcuts dramatically improve efficiency

Essential Shortcuts to Memorize:

ShortcutAction
SuperOpen Activities
Alt+TabSwitch windows
Super+EnterOpen terminal
Super+LLock screen
PrintScreenScreenshot

Chapter Quiz

Test your understanding of the GNOME desktop environment:


Exercises

Exercise 1: GNOME Navigation Scavenger Hunt

Complete these tasks as fast as possible:

  1. Open the Activities Overview
  2. Find and launch GNOME Terminal
  3. Open a second workspace
  4. Move Terminal to workspace 2
  5. Switch back to workspace 1
  6. Open GNOME Files (Nautilus)
  7. Maximize the Files window
  8. Close the Files window
  9. Lock the screen
  10. Unlock and return

Deliverable: Record your time and list which shortcuts you used.

Exercise 2: Desktop Customization

Personalize your desktop:

  1. Change your desktop background
  2. Enable dark mode
  3. Add 5 applications to your favorites/dock
  4. Install 1 GNOME extension (from Extensions app)
  5. Change your interface font size
  6. Configure your power settings

Deliverable: Screenshots of your customized desktop.

Exercise 3: Application Installation

Install these applications:

  1. Via GNOME Software: Install VLC media player
  2. Via Flatpak: Install Flatpak, add Flathub, install 1 app
  3. Via Terminal (preview): Use dnf to install tree
$ sudo dnf install tree

Deliverable: List the commands/steps you used for each method.

Exercise 4: Workspace Workflow

Create a productive workspace setup:

  1. Workspace 1: Browser + Terminal
  2. Workspace 2: Files + Text Editor
  3. Workspace 3: Settings + Software (optional)

Practice switching between workspaces and moving windows.

Deliverable: Describe your workspace workflow and how it helps you stay organized.


Expected Output

After completing these exercises, you should have:

  1. Navigation Skills: Can use GNOME efficiently without mouse
  2. Customized Desktop: Personalized appearance and setup
  3. Installed Apps: VLC, Flatpak app, and tree command
  4. Workspace Workflow: Organized multi-desktop setup

Further Reading


Discussion Questions

  1. Why does GNOME hide options compared to Windows/macOS? Is this good or bad?
  2. How does GNOME's dynamic workspace model compare to fixed virtual desktops?
  3. What are the security implications of installing extensions from the web?
  4. Why might someone prefer KDE Plasma or XFCE over GNOME?

Chapter 4: File System & Navigation

Learning Objectives

By the end of this chapter, you will be able to:

  • Understand the Linux file system hierarchy
  • Navigate directories using cd, pwd, and ls
  • Create and remove directories and files
  • Differentiate between absolute and relative paths
  • Use tab completion to work more efficiently
  • Understand home directories and the ~ shortcut

Prerequisites

  • Completed Part I: Foundations
  • Have a working Linux installation with terminal access

The Linux File System Hierarchy

Unlike Windows, which uses drive letters (C:, D:, etc.), Linux uses a single unified directory tree starting at the root directory, represented by / (forward slash).

/ (root)
├── bin/        # Essential user binaries (ls, cp, cat, etc.)
├── boot/       # Boot loader files
├── dev/        # Device files
├── etc/        # Configuration files
├── home/       # User home directories
│   ├── student/
│   └── user/
├── lib/        # System libraries
├── media/      # Removable media mount points
├── mnt/        # Mount point for temporary filesystems
├── opt/        # Optional software packages
├── proc/       # Process and kernel information
├── root/       # Home directory for root user
├── run/        # Runtime data
├── sbin/       # System binaries
├── srv/        # Service data
├── sys/        # Kernel and hardware information
├── tmp/        # Temporary files
└── var/        # Variable data (logs, spool, etc.)

Key Directories to Remember

DirectoryPurposeWhat You'll Find There
/home/usernameYour home directoryYour personal files, documents, downloads
/binBinariesEssential commands like ls, cp, cat
/etcEtcetera (config)System-wide configuration files
/varVariable dataLogs, web server files, mail queues
/tmpTemporaryFiles that don't need to persist

Essential Navigation Commands

pwd - Print Working Directory

Shows your current location in the file system.

$ pwd
/home/student

ls - List Directory Contents

Shows files and directories in your current location.

$ ls
Documents  Downloads  Music  Pictures  Videos

Common ls options:

OptionPurposeExample
-lLong format (details)ls -l
-aShow hidden files (dotfiles)ls -a
-hHuman-readable sizesls -lh
-laCombined: long + allls -la
-tSort by time modifiedls -lt
$ ls -la
drwxr-xr-x 5 student student 4096 Jan 15 10:30 Documents
drwxr-xr-x 2 student student 4096 Jan 14 09:15 Downloads
-rw-r--r-- 1 student student  123 Jan 15 10:00 notes.txt

cd - Change Directory

Navigate to different directories.

cd           # Go to home directory (same as cd ~)
cd ..        # Go up one level (parent directory)
cd /         # Go to root directory
cd -         # Go to previous directory
cd ~/Music   # Go to Music subdirectory in home

Examples:

$ pwd
/home/student

$ cd /etc
$ pwd
/etc

$ cd ..
$ pwd
/

$ cd -
$ pwd
/etc

Paths: Absolute vs. Relative

Understanding paths is fundamental to Linux navigation.

Absolute Paths

Start from / (root) and specify the complete path.

cd /home/student/Documents
cd /etc/nginx
cd /var/log

When to use: When you want to be precise about the location, regardless of where you currently are.

Relative Paths

Start from your current directory (also called "working directory").

cd Documents           # Go into Documents in current directory
cd ../Pictures         # Go up one level, then into Pictures
cd ./Music/songs       # Explicit reference to current directory

Special path symbols:

SymbolMeaning
.Current directory
..Parent directory (one level up)
~Home directory
/Root directory

Visual Example

/
└── home/
    └── student/
        ├── Documents/
        │   └── project.txt
        ├── Downloads/
        └── Pictures/

If you're in /home/student/Documents:

CommandDestinationPath Type
cd /home/student/home/studentAbsolute
cd ../home/studentRelative
cd ../Pictures/home/student/PicturesRelative
cd ~/Pictures/home/student/PicturesAbsolute (with ~)

Creating and Removing Directories

mkdir - Make Directory

Create new directories.

mkdir project                    # Create single directory
mkdir -p a/b/c                  # Create nested directories (parents)
mkdir -p ~/linux-course/session{01..10}  # Create multiple directories

The -p flag is particularly useful:

  • Creates parent directories if they don't exist
  • Doesn't error if directory already exists

rmdir - Remove Directory

Remove empty directories only.

rmdir empty-folder

rm - Remove Files and Directories

Remove files and directories (use with caution!).

rm file.txt                     # Remove file (asks for confirmation)
rm -f file.txt                  # Force remove (no confirmation)
rm -r directory/                # Remove directory and contents
rm -rf directory/               # Force remove directory recursively

Warning: rm -rf is permanent. There's no recycle bin in the terminal!


Creating Files

touch - Create Empty File

Create an empty file or update timestamps.

touch notes.txt                 # Create new empty file
touch report.md todo.txt        # Create multiple files

Creating Files with Content

You'll learn more about text editors and redirection in Chapter 5, but here's a quick preview:

echo "Hello, Linux!" > hello.txt    # Create file with content
cat > newfile.txt << EOF
Line 1
Line 2
Line 3
EOF

Tab Completion: Your Best Friend

Tab completion saves time and prevents typos. Start typing a command or filename, then press Tab.

How It Works

$ cd Doc[TAB]          # Expands to: cd Documents
$ ls /hom[TAB]         # Expands to: ls /home/
$ cat note[TAB]        # Expands to: cat notes.txt

Multiple Matches

If multiple files match your prefix, press Tab twice to see all options:

$ cd Do[TAB][TAB]
Documents/  Downloads/

Tips for Tab Completion

  1. Always use it - It prevents typos and saves keystrokes
  2. Press Tab twice - If nothing happens, press again to see options
  3. Works with commands too - Type cha[TAB] to get chattr, chacl, etc.
  4. Handles paths - ~/Doc[TAB]~/Documents/

Hidden Files and Directories

In Linux, files starting with a dot (.) are hidden by default. They're not shown in regular ls output.

$ ls
Documents  Downloads  Music

$ ls -a
.  ..  .bashrc  .config  .gitconfig  Documents  Downloads  Music

Common hidden files:

FilePurpose
.bashrcBash shell configuration
.bash_historyCommand history
.gitconfigGit configuration
.ssh/SSH keys and config
.config/Application settings

Practical Examples

Example 1: Setting Up a Course Directory

# Start from home
cd ~

# Create course structure
mkdir -p linux-course/{session{01..10},exercises,notes}

# Navigate into session 01
cd linux-course/session01

# Create a notes file
touch notes.txt

# Go back to course root
cd ~/linux-course

# Verify structure
ls -R

Example 2: Exploring System Directories

# Look at what's in /etc
cd /etc
ls

# Find SSH configuration
cd ssh
ls -la

# Return home quickly
cd ~

Example 3: Cleaning Up Downloads

# Go to Downloads
cd ~/Downloads

# List files sorted by size (you'll learn this in Chapter 5)
ls -lhS

# Remove old files (be careful!)
rm old-file.zip

# Clean up empty directories
cd ..
rmdir Downloads/old-empty-folder

Summary

In this chapter, you learned:

  • File System Structure: Linux uses a single tree starting at /
  • Key Directories: /home (user files), /bin (programs), /etc (config)
  • Navigation Commands:
    • pwd - Where am I?
    • ls - What's here?
    • cd - Go somewhere
  • Paths: Absolute (from /) vs relative (from current directory)
  • Special Symbols: . (current), .. (parent), ~ (home)
  • Directory Management: mkdir, rmdir, rm -r
  • Tab Completion: Always press Tab to save time and avoid typos

Chapter Quiz

Test your understanding of the Linux file system and navigation:


Exercises

Exercise 1: Directory Navigation

  1. Open your terminal
  2. Navigate to /etc
  3. List the contents
  4. Go to /var/log
  5. Return to your home directory using a single command
  6. Verify you're home with pwd

Exercise 2: Create Course Structure

Create this directory structure in your home folder:

~/linux-course/
├── session01/
├── session02/
├── session03/
└── exercises/
    ├── basic/
    └── advanced/

Exercise 3: File Creation Practice

  1. Navigate to ~/linux-course/session01
  2. Create an empty file called notes.txt
  3. Go back to ~/linux-course
  4. Use tab completion to navigate to session01/notes.txt

Exercise 4: Path Practice

Starting from /home/student, use relative paths to:

  1. Go to /home/student/Documents
  2. From there, go to /home/student/Pictures using only relative paths
  3. Return to /home/student using the shortest command

Exercise 5: Exploration Challenge

  1. Navigate to /usr/bin
  2. Count how many executables are there (hint: ls | wc -l)
  3. Find if python3 exists there (hint: ls python*)
  4. Explore what's in /tmp

Expected Output

Exercise 1 Solution

$ cd /etc
$ ls
aiccu          cups           ld.so.cache   nsswitch.conf  udev
alias          dbus           libao.conf    opt            udisks2
...

$ cd /var/log
$ pwd
/var/log

$ cd ~
$ pwd
/home/student

Exercise 2 Solution

$ mkdir -p ~/linux-course/session{01..03}
$ mkdir -p ~/linux-course/exercises/{basic,advanced}
$ cd ~/linux-course
$ tree -L 2    # or use: find . -type d -maxdepth 2
.
├── exercises
│   ├── advanced
│   └── basic
├── session01
├── session02
└── session03

Exercise 3 Solution

$ cd ~/linux-course/session01
$ touch notes.txt
$ cd ~/linux-course
$ cd ses[TAB]    # Expands to session01
$ ls
notes.txt

Exercise 4 Solution

$ cd ~/linux-course/session01
$ cd ../../Pictures      # or: cd ../session02
$ cd ~                   # or: cd /home/student

Next Chapter

In Chapter 5, you'll learn CLI Fundamentals - viewing files, copying and moving, pipes, redirection, and wildcards. This will build on your navigation skills to make you truly productive in the terminal.

Chapter 5: CLI Fundamentals

Learning Objectives

By the end of this chapter, you will be able to:

  • View file contents using cat, less, head, and tail
  • Copy and move files with cp and mv
  • Use pipes (|) to chain commands together
  • Redirect input and output with >, >>, and <
  • Use wildcards (*, ?, []) to work with multiple files
  • Combine commands with ;, &&, and ||

Prerequisites

  • Completed Chapter 4: File System & Navigation
  • Comfortable with basic directory navigation

Command Syntax Basics

Every Linux command follows this basic structure:

command [options] [arguments]
ComponentDescriptionExample
commandThe program to runls
optionsModify behavior (usually start with -)-l, -a, -la
argumentsWhat to operate on (files, directories)/etc, *.txt
ls -l /home          # ls=command, -l=option, /home=argument
grep -r "TODO" .     # grep=command, -r=option, "TODO"=arg1, .=arg2

Getting Help

command --help       # Show help for most commands
man command          # Show manual page (press q to quit)
man ls               # Manual for ls command

Viewing File Contents

cat - Concatenate and Display

cat displays the entire contents of a file to the terminal.

cat file.txt                    # Display file
cat file1.txt file2.txt         # Display multiple files
cat -n file.txt                 # Show with line numbers
cat -b file.txt                 # Number non-blank lines

When to use: Small files, quickly viewing contents, combining files.

$ cat notes.txt
Welcome to Linux!
This is your second day.
Learn the terminal well.

less - View with Pagination

less lets you scroll through large files.

less large-file.log             # View file with scrolling
less +F /var/log/syslog         # Follow file (like tail -f)

Navigation in less:

KeyAction
Space or fPage forward
bPage backward
Arrow keysLine by line
/patternSearch forward
nNext search result
qQuit

When to use: Large files, when you need to search, or want to scroll.

head - Show First Lines

Display the beginning of a file.

head file.txt                   # First 10 lines (default)
head -n 20 file.txt             # First 20 lines
head -n 5 /var/log/syslog       # First 5 lines of syslog

tail - Show Last Lines

Display the end of a file.

tail file.txt                   # Last 10 lines (default)
tail -n 20 file.txt             # Last 20 lines
tail -f /var/log/syslog         # Follow file in real-time

The -f flag is incredibly useful for watching logs as they're written!

GUI vs CLI Comparison

TaskGUI ActionCLI Command
Open fileDouble-clickcat file.txt
View large fileScroll with mouseless large.txt
Check beginningScroll to tophead file.txt
Check endScroll to bottomtail file.txt
Watch logReopen filetail -f log.txt

Copying and Moving Files

cp - Copy Files and Directories

cp file.txt backup.txt          # Copy file
cp file.txt ~/Documents/        # Copy to directory
cp file1.txt file2.txt docs/    # Copy multiple files
cp -r directory/ new-dir/       # Copy directory recursively
cp -p file.txt preserve.txt     # Preserve permissions/timestamps

Common options:

OptionPurpose
-iInteractive (prompt before overwriting)
-rRecursive (for directories)
-pPreserve mode, ownership, timestamps
-vVerbose (show what's being copied)
$ cp -v notes.txt backup.txt
'notes.txt' -> 'backup.txt'

mv - Move or Rename Files

mv old.txt new.txt              # Rename file
mv file.txt ~/Documents/        # Move file
mv directory/ ~/new-location/   # Move directory
mv *.txt docs/                  # Move all .txt files

Important: mv is both "move" and "rename" - they're the same operation in Linux!


Pipes: Chaining Commands

The pipe (|) takes the output of one command and uses it as input to another.

Basic Syntax

command1 | command2 | command3

Practical Examples

# Long directory listing, piped to less for pagination
ls -l /etc | less

# Find large files
ls -lS | head -n 5              # Sort by size, show top 5

# Count files
ls | wc -l                      # Count number of files

# Search for process
ps aux | grep firefox           # Find firefox process

# View system info
neofetch                        # (if installed)

Building Complex Pipelines

# Find all .txt files, count lines, show largest
find . -name "*.txt" -exec wc -l {} \; | sort -n | tail -n 5

# View Apache errors
cat /var/log/apache2/error.log | grep "ERROR" | less

# Count unique IP addresses in access log
cat access.log | awk '{print $1}' | sort | uniq

Redirection: Controlling Input/Output

Redirection sends command output to files or reads input from files.

Output Redirection

# Overwrite file (> or 1>)
echo "Hello" > file.txt         # Write to file (overwrites)
ls -l > directory-list.txt

# Append to file (>> or 1>>)
echo "World" >> file.txt        # Add to end of file
date >> log.txt                 # Append timestamp

# Redirect errors (2> or 2>>)
command 2> errors.txt           # Redirect error messages
command &> output.txt           # Redirect both output and errors

Input Redirection

# Read from file (< or 0<)
wc -l < file.txt                # Count lines in file

# Here document (<<)
cat << EOF > config.txt
Host: localhost
Port: 8080
Debug: true
EOF

Redirection vs Pipes

| Feature | Pipe | | Redirection > | |---------|----------|----------------| | Sends to | Another command | A file | | Chaining | Yes (multiple) | No (single file) | | Real-time | Yes | No | | Example | ls \| grep txt | ls > files.txt |


Wildcards: Pattern Matching

Wildcards let you work with multiple files matching a pattern.

The Asterisk (*)

Matches any number of any characters.

*.txt                   # All .txt files
file*                   # All files starting with "file"
*backup*                # All files containing "backup"
*.tar.gz                # All .tar.gz files

The Question Mark (?)

Matches exactly one character.

file?.txt               # file1.txt, fileA.txt (not file10.txt)
image?.jpg              # image1.jpg, image2.jpg

Character Classes ([])

Matches one character from the set.

file[123].txt           # file1.txt, file2.txt, file3.txt
`file[abc].txt`         # filea.txt, fileb.txt, filec.txt
[0-9]                   # Any single digit
[a-z]                   # Any lowercase letter
[A-Z]                   # Any uppercase letter
[a-zA-Z]                # Any letter

Negation ([!] or [^])

Matches anything except the specified characters.

file[!0-9].txt          # file.txt but not file1.txt, file2.txt, etc.

Practical Wildcard Examples

# Copy all .jpg files to backup
cp *.jpg backup/

# Remove all temporary files
rm *.tmp

# List all hidden files
ls .*

# Find all log files
ls /var/log/*.log

# Work with numbered files
rm chapter-[0-5].md     # Remove chapters 0-5

Combining Commands

Sequential Execution (;)

Run commands regardless of previous success.

mkdir newdir; cd newdir; touch file.txt

AND Operator (&&)

Run next command only if previous succeeded.

mkdir newdir && cd newdir && ls    # cd only if mkdir succeeded
./configure && make && sudo make install

OR Operator (||)

Run next command only if previous failed.

mkdir newdir || echo "Directory already exists"
grep "pattern" file.txt || echo "Pattern not found"

Combining AND and OR

# Try to start service, report success or failure
sudo systemctl start nginx && echo "Started!" || echo "Failed!"

# Create backup or report error
cp important.txt backup.txt || echo "Backup failed!"

Practical Examples

Example 1: Organize Downloads

cd ~/Downloads

# Create organized directories
mkdir -p images documents archives

# Move files by type
mv *.jpg *.png *.gif images/
mv *.pdf *.docx *.txt documents/
mv *.zip *.tar.gz archives/

Example 2: Log Analysis

# Find all 404 errors in web log
grep " 404 " /var/log/nginx/access.log | less

# Count unique IPs
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -n

# Find errors from last 50 lines
tail -n 50 /var/log/syslog | grep -i error

Example 3: Backup Strategy

# Create timestamped backup
DATE=$(date +%Y%m%d)
cp important.txt backup-$DATE.txt

# Archive and compress
tar -czf backup-$(date +%Y%m%d).tar.gz ~/Documents

# Verify backup was created
ls -lh backup-*.tar.gz

Example 4: Process Management

# Find CPU-intensive processes
ps aux | sort -rk 3 | head -n 10

# Kill specific process
pkill firefox

# Or be more specific
kill $(pidof firefox)

Summary

In this chapter, you learned:

  • Viewing Files:
    • cat - Display entire file
    • less - Scroll through large files
    • head / tail - View start/end of files
  • File Operations:
    • cp - Copy files/directories
    • mv - Move/rename files
  • Pipes (|): Chain commands, pass output to input
  • Redirection (>, >>, <): Control where input/output goes
  • Wildcards (*, ?, []): Match multiple files
  • Command Combos (;, &&, ||): Control command flow

Chapter Quiz

Test your understanding of CLI fundamentals:


Exercises

Exercise 1: View Different Files

  1. Create a test file: echo -e "Line 1\nLine 2\nLine 3" > test.txt
  2. View it with cat
  3. View the first line only
  4. View the last line only
  5. View it with less, then search for "Line 2"

Exercise 2: Copy and Organize

  1. Create these files: touch file1.txt file2.txt file3.txt doc1.pdf doc2.pdf
  2. Create directories: mkdir text docs
  3. Move all .txt files to text/
  4. Copy all .pdf files to docs/
  5. Verify with ls

Exercise 3: Pipeline Practice

  1. List all files in /bin
  2. Pipe to wc -l to count them
  3. Pipe to grep zip to find compression tools
  4. Find the 5 largest files in /usr/bin (hint: ls -lS | head)

Exercise 4: Redirection

  1. Create a file with content: echo "First line" > output.txt
  2. Add another line: echo "Second line" >> output.txt
  3. View the result
  4. Count lines: wc -l < output.txt

Exercise 5: Wildcards

  1. Create files: touch file1.txt file2.txt fileA.txt file10.txt data.csv data.txt
  2. List all files starting with "file"
  3. List all .txt files
  4. List file followed by exactly one character
  5. List file followed by a digit

Expected Output

Exercise 1 Solution

$ echo -e "Line 1\nLine 2\nLine 3" > test.txt
$ cat test.txt
Line 1
Line 2
Line 3

$ head -n 1 test.txt
Line 1

$ tail -n 1 test.txt
Line 3

$ less test.txt
# /Line 2 (press Enter, then 'q' to quit)

Exercise 2 Solution

$ touch file1.txt file2.txt file3.txt doc1.pdf doc2.pdf
$ mkdir text docs
$ mv *.txt text/
$ cp *.pdf docs/
$ ls
text/  docs/

$ ls text/
file1.txt  file2.txt  file3.txt

$ ls docs/
doc1.pdf  doc2.pdf

Exercise 3 Solution

$ ls /bin | wc -l
152

$ ls /bin | grep zip
gzip
gunzip
unzip
zip
zipcloak
zipdetails
zipgrep
zipinfo
zipsplit

$ ls -lS /usr/bin | head -n 5

Exercise 4 Solution

$ echo "First line" > output.txt
$ echo "Second line" >> output.txt
$ cat output.txt
First line
Second line

$ wc -l < output.txt
2

Exercise 5 Solution

$ touch file1.txt file2.txt fileA.txt file10.txt data.csv data.txt

$ ls file*
file1.txt  file10.txt  file2.txt  fileA.txt

$ ls *.txt
data.txt  file1.txt  file10.txt  file2.txt  fileA.txt

$ ls file?.txt
file1.txt  file2.txt  fileA.txt

$ ls file[0-9].txt
file1.txt  file2.txt

Next Chapter

In Chapter 6, you'll learn Text Processing - searching with grep, finding files with find, and manipulating text with sed, awk, sort, and more.

Chapter 6: Text Processing

Learning Objectives

By the end of this chapter, you will be able to:

  • Search text patterns using grep
  • Find files by name, size, or type with find
  • Process text with sed for search and replace
  • Use awk for text extraction and formatting
  • Sort, count, and deduplicate with sort, uniq, and wc
  • Build powerful text processing pipelines

Prerequisites

  • Completed Chapter 5: CLI Fundamentals
  • Comfortable with pipes and redirection
  • Understanding of wildcards and basic regex

Searching with Grep

grep is one of the most powerful and frequently used commands in Linux. It searches for patterns in files.

Basic Usage

grep pattern file.txt            # Search for pattern in file
grep "hello world" file.txt      # Search for phrase
grep -i pattern file.txt         # Case-insensitive search
grep -r "TODO" .                 # Recursive search in current directory
grep -v pattern file.txt         # Invert match (show non-matching lines)

Common Options

OptionPurposeExample
-iIgnore casegrep -i error log.txt
-rRecursivegrep -r "function" src/
-nShow line numbersgrep -n TODO *.py
-cCount matchesgrep -c "error" log.txt
-vInvert matchgrep -v "#" config.txt
-lList matching filesgrep -l "import" *.py
-wWhole word onlygrep -w "cat" file.txt

Practical Examples

# Find all TODO comments in code
grep -rn "TODO" src/

# Count errors in log file
grep -c "ERROR" /var/log/syslog

# Find IP addresses in logs
grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" access.log

# Show lines without comments
grep -v "^#" config.txt

# Find processes
ps aux | grep firefox

Extended Regular Expressions

grep -E "error|warning" log.txt          # Match error OR warning
grep -E "^Start|End$" file.txt           # Match lines starting with Start or ending with End
grep -E "[0-9]+" file.txt                # Match numbers
grep -E "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" emails.txt  # Email pattern

Finding Files with Find

find searches for files and directories based on various criteria.

Basic Syntax

find [path] [options] [expression]

Common Usage Patterns

# Find by name
find . -name "file.txt"
find . -name "*.jpg"
find / -name "config.yml" 2>/dev/null

# Find by type (f=file, d=directory, l=symlink)
find . -type f
find . -type d
find . -type l

# Find by size
find . -size +10M                  # Larger than 10MB
find . -size -1k                   # Smaller than 1KB
find . -size 100M                  # Exactly 100MB

# Find by modification time
find . -mtime -7                   # Modified in last 7 days
find . -mtime +30                  # Modified more than 30 days ago
find . -mmin -60                   # Modified in last 60 minutes

# Find by permissions
find . -perm 777                   # Exactly 777 permissions
find . -perm -u+x                  # Files with user execute

Combining Find with Actions

# Delete files matching pattern (be careful!)
find . -name "*.tmp" -delete

# Execute command on each file
find . -name "*.jpg" -cp {} backup/   # Copy all .jpg files

# Find and list details
find . -name "*.py" -ls

# Find empty files
find . -empty

# Find owned by specific user
find /home -user student

Powerful Find Pipelines

# Find large files and sort by size
find . -type f -size +10M -exec ls -lh {} \; | sort -k5 -h

# Find Python files modified in last 7 days
find . -name "*.py" -mtime -7

# Find and count file types
find . -type f -name "*.*" | sed 's/.*\.//' | sort | uniq -c | sort -rn

Text Manipulation with Sed

sed (stream editor) is used for filtering and transforming text.

Basic Substitution

sed 's/old/new/' file.txt          # Replace first occurrence per line
sed 's/old/new/g' file.txt         # Replace all occurrences (global)
sed -i 's/old/new/g' file.txt      # Edit file in-place

# Remove empty lines
sed '/^$/d' file.txt

# Remove comments
sed 's/#.*$//' file.txt

# Replace spaces with tabs
sed 's/ /\t/g' file.txt

Common Sed Operations

OperationCommandDescription
Delete linessed '5d' file.txtDelete line 5
Delete rangesed '5,10d' file.txtDelete lines 5-10
Print specificsed -n '5p' file.txtPrint only line 5
Delete patternsed '/pattern/d' file.txtDelete matching lines
Print patternsed -n '/pattern/p' file.txtPrint only matching lines

Practical Examples

# Replace "foo" with "bar" in all .txt files
sed -i 's/foo/bar/g' *.txt

# Remove trailing whitespace
sed -i 's/[[:space:]]*$//' file.txt

# Convert Windows line endings to Unix
sed -i 's/\r$//' file.txt

# Add line numbers
sed = file.txt | sed 'N;s/\n/\t/'

# Extract text between delimiters
sed -n 's/.*<title>\(.*\)<\/title>.*/\1/p' file.html

Text Processing with Awk

awk is a powerful text processing language. It's especially good at columnar data.

Basic Structure

awk 'pattern { action }' file.txt

Field Processing

# Print specific columns (space-separated by default)
awk '{print $1}' file.txt           # Print first column
awk '{print $1, $3}' file.txt       # Print first and third columns
awk '{print $NF}' file.txt          # Print last column

# Different delimiter
awk -F: '{print $1}' /etc/passwd    # : as delimiter (first field)
awk -F, '{print $2, $4}' file.csv   # CSV file

Built-in Variables

VariableMeaning
$0Entire line
$1, $2, ...Fields 1, 2, ...
$NFNumber of fields (last field)
NRCurrent record number (line number)
FSField separator (default: space)
OFSOutput field separator

Practical Examples

# Print lines longer than 80 characters
awk 'length($0) > 80' file.txt

# Sum values in column 3
awk '{sum += $3} END {print sum}' numbers.txt

# Calculate average
awk '{sum += $1; count++} END {print sum/count}' data.txt

# Filter and format
awk '$3 > 100 {print $1, "is high"}' data.txt

# Extract unique values from first column
awk '!seen[$1]++' file.txt

# Reorder columns (swap 1 and 2)
awk '{print $2, $1, $3}' file.txt

Pattern Matching

# Print lines matching pattern
awk '/error/ {print}' log.txt

# Print if field matches
awk '$3 == "success" {print $1, $2}' data.txt

# Range pattern (print between START and END)
awk '/START/,/END/' file.txt

# Multiple conditions
awk '$1 > 50 && $2 < 100' file.txt

Sorting and Counting

sort - Arrange Lines

sort file.txt                     # Sort alphabetically
sort -n file.txt                  # Sort numerically
sort -r file.txt                  # Reverse sort
sort -u file.txt                  # Sort and remove duplicates
sort -k2 file.txt                 # Sort by 2nd column
sort -t: -k3 -n /etc/passwd       # Sort passwd by 3rd field (UID)

# Sort by human-readable sizes
sort -h sizes.txt

# Random shuffle
sort -R file.txt

# Sort and save
sort -o sorted.txt file.txt       # Same as: sort file.txt > sorted.txt

uniq - Remove Duplicates

uniq file.txt                     # Remove adjacent duplicates
uniq -c file.txt                  # Count occurrences
uniq -d file.txt                  # Show only duplicates
uniq -u file.txt                  # Show only unique lines

# Common pattern: sort first, then uniq
sort file.txt | uniq              # Remove all duplicates
sort file.txt | uniq -c           # Count occurrences
sort file.txt | uniq -d           # Show only duplicated lines

wc - Word Count

wc file.txt                       # Lines, words, bytes
wc -l file.txt                    # Line count only
wc -w file.txt                    # Word count only
wc -c file.txt                    # Byte count only
wc -m file.txt                    # Character count

# Count multiple files
wc -l *.txt                       # Count lines in all .txt files
ls | wc -l                        # Count files in directory

Building Processing Pipelines

The real power comes from combining these tools.

Log Analysis Pipeline

# Find top 5 IP addresses by request count
cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -n 5

Breakdown:

  1. cat access.log - Read the log file
  2. awk '{print $1}' - Extract first column (IP address)
  3. sort - Sort IPs to group duplicates
  4. uniq -c - Count occurrences
  5. sort -rn - Sort by count, descending, numerically
  6. head -n 5 - Show top 5

Disk Usage Analysis

# Find largest directories
du -h | sort -rh | head -n 10

File Type Statistics

# Count file extensions
find . -type f | sed 's/.*\.//' | sort | uniq -c | sort -rn

Process Monitoring

# Find top CPU users
ps aux | sort -rk 3 | head -n 10

# Find specific process and kill it
ps aux | grep chrome | awk '{print $2}' | xargs kill

Code Analysis

# Count lines of code (excluding comments and blanks)
find src -name "*.py" -exec cat {} \; | grep -v "^#" | grep -v "^$" | wc -l

# Find all TODO comments
grep -rn "TODO" src/ | wc -l

# Find files containing specific functions
grep -rl "def my_function" src/

Practical Examples

Example 1: Clean Up Logs

# Extract only errors from today's logs
grep "ERROR" /var/log/syslog | grep "$(date +%Y-%m-%d)" > today-errors.txt

# Count errors by type
grep "ERROR" /var/log/syslog | awk '{print $5}' | sort | uniq -c

Example 2: Email Processing

# Extract email addresses from text
grep -E "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" contacts.txt

# Count unique domains
grep -E "@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" contacts.txt | \
  sed 's/.*@//' | sort | uniq -c

Example 3: CSV Processing

# Calculate sum of column 3 in CSV
awk -F, '{sum += $3} END {print "Total:", sum}' data.csv

# Filter rows where column 2 > 100
awk -F, '$2 > 100' data.csv

# Extract specific columns and create new CSV
awk -F, '{print $1, $3, $5}' OFS=, input.csv > output.csv

Example 4: File Management

# Find and delete old temporary files
find /tmp -name "*.tmp" -mtime +7 -delete

# Find large log files and compress them
find /var/log -name "*.log" -size +100M -exec gzip {} \;

# Rename files (replace spaces with underscores)
find . -name "* *" -type f | rename 's/ /_/g'

Summary

In this chapter, you learned:

  • grep: Search for patterns in files with powerful regex support
  • find: Locate files by name, size, type, or time
  • sed: Stream editor for search and replace operations
  • awk: Text processing language for columnar data
  • sort: Sort lines alphabetically or numerically
  • uniq: Remove or count duplicate lines
  • wc: Count lines, words, and characters
  • Pipelines: Combine tools for powerful text processing

Quick Reference

TaskCommand
Search patterngrep "pattern" file.txt
Find file by namefind . -name "file.txt"
Replace textsed 's/old/new/g' file.txt
Extract columnawk '{print $1}' file.txt
Count lineswc -l file.txt
Sort filesort file.txt
Remove duplicatessort file.txt | uniq

Chapter Quiz

Test your understanding of text processing commands:


Exercises

Exercise 1: Grep Practice

Create a sample file and search:

cat > sample.txt << EOF
Hello World
Linux is great
ERROR: Something went wrong
WARNING: Low disk space
ERROR: Connection failed
Success: All good
EOF
  1. Find all lines containing "ERROR"
  2. Count how many lines have "ERROR"
  3. Find lines with "ERROR" or "WARNING"
  4. Show line numbers with matches

Exercise 2: Find and Process

  1. Find all .txt files in your home directory
  2. Find all files larger than 1MB in /var/log
  3. Find all files modified in the last 24 hours
  4. Count how many .conf files exist in /etc

Exercise 3: Awk Processing

Create a data file:

cat > data.csv << EOF
name,age,score
Alice,25,95
Bob,30,87
Charlie,25,92
Diana,35,88
EOF
  1. Extract the name column (column 1)
  2. Calculate the average score
  3. Find rows where age is 25
  4. Format as: "Name: Alice, Score: 95"

Exercise 4: Pipeline Building

  1. Create a list of random numbers: for i in {1..20}; do echo $RANDOM; done > numbers.txt
  2. Find the 5 largest numbers
  3. Count how many are greater than 10000
  4. Sort them and remove duplicates

Exercise 5: Log Analysis Challenge

Simulate a web log:

cat > access.log << EOF
192.168.1.1 - - [01/Jan/2025] "GET /index.html" 200
192.168.1.2 - - [01/Jan/2025] "GET /about.html" 200
192.168.1.1 - - [01/Jan/2025] "GET /index.html" 200
192.168.1.3 - - [01/Jan/2025] "GET /contact.html" 404
192.168.1.2 - - [01/Jan/2025] "POST /submit" 500
EOF
  1. Count how many 404 errors occurred
  2. Find the IP address that made the most requests
  3. Extract all unique pages visited
  4. Show only failed requests (status code >= 400)

Expected Output

Exercise 1 Solution

$ grep "ERROR" sample.txt
ERROR: Something went wrong
ERROR: Connection failed

$ grep -c "ERROR" sample.txt
2

$ grep -E "ERROR|WARNING" sample.txt
ERROR: Something went wrong
WARNING: Low disk space
ERROR: Connection failed

$ grep -n "ERROR" sample.txt
3:ERROR: Something went wrong
5:ERROR: Connection failed

Exercise 2 Solution

$ find ~ -name "*.txt"
/home/student/notes.txt
/home/student/sample.txt

$ find /var/log -size +1M
/var/log/journal/... (large journal files)

$ find ~ -mtime -1
/home/student/.bash_history
/home/student/sample.txt

$ find /etc -name "*.conf" | wc -l
42

Exercise 3 Solution

$ awk -F, '{print $1}' data.csv
name
Alice
Bob
Charlie
Diana

$ awk -F, 'NR>1 {sum += $3; count++} END {print sum/count}' data.csv
90.5

$ awk -F, '$2 == 25' data.csv
Alice,25,95
Charlie,25,92

$ awk -F, 'NR>1 {print "Name:", $1, ", Score:", $3}' data.csv
Name: Alice , Score: 95
Name: Bob , Score: 87
Name: Charlie , Score: 92
Name: Diana , Score: 88

Exercise 4 Solution

$ for i in {1..20}; do echo $RANDOM; done > numbers.txt

$ sort -rn numbers.txt | head -n 5
32145
29834
28745
27653
26847

$ awk '$1 > 10000' numbers.txt | wc -l
8

$ sort numbers.txt | uniq
1024
5678
... (unique sorted numbers)

Exercise 5 Solution

$ grep " 404 " access.log | wc -l
1

$ awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -n 1
2 192.168.1.1

$ awk -F'"' '{print $2}' access.log | sort -u
GET /about.html
GET /contact.html
GET /index.html
POST /submit

$ awk '$9 >= 400' access.log
192.168.1.3 - - [01/Jan/2025] "GET /contact.html" 404
192.168.1.2 - - [01/Jan/2025] "POST /submit" 500

Next Chapter

In Chapter 7, you'll learn Permissions & Users - understanding Linux security, managing permissions with chmod and chown, and user administration with sudo and user management commands.

Chapter 7: Permissions & Users

Learning Objectives

By the end of this chapter, you will be able to:

  • Understand Linux's permission model (read, write, execute)
  • Interpret ls -l output and permission strings
  • Change permissions using symbolic and numeric modes with chmod
  • Change file ownership with chown and chgrp
  • Use sudo to execute commands with elevated privileges
  • Manage users and groups with useradd, usermod, and passwd

Prerequisites

  • Completed Chapter 6: Text Processing
  • Comfortable with basic file operations

Understanding Linux Permissions

Linux is a multi-user system with built-in security. Every file and directory has permissions that control who can read, write, or execute it.

The Three Permission Types

PermissionSymbolDescriptionFor FilesFor Directories
ReadrView contentsCan read fileCan list directory
WritewModify contentsCan change fileCan add/remove files
ExecutexRun as programCan execute fileCan enter directory

The Three User Classes

ClassSymbolDescription
User (Owner)uThe file's owner
GroupgUsers in the file's group
OthersoEveryone else
Permissions:  rwx  rwx  rwx
              ^    ^    ^
              |    |    |
           User  Group Others

Reading Permissions with ls -l

The ls -l command displays detailed file information including permissions.

Format Breakdown

$ ls -l file.txt
-rw-r--r-- 1 student student 1234 Jan 15 10:30 file.txt
^----------^ ^  ^       ^      ^    ^
 permissions   | owner   group size date name
              links

Permission String Structure

-  rw-  r--  r--
|  ^   ^   ^
|  |   |   |
|  |   |   +-- Others permissions
|  |   +------ Group permissions
|  +---------- User (owner) permissions
+-------------- File type

File Type Characters

CharacterType
-Regular file
dDirectory
lSymbolic link
bBlock device
cCharacter device
sSocket
pNamed pipe

Examples

drwxr-xr-x  # Directory: user=rwx, group=rx, others=rx
-rw-r--r--  # Regular file: user=rw, group=r, others=r
-rwxr-xr-x  # Executable: user=rwx, group=rx, others=rx
lrwxrwxrwx  # Symbolic link (all permissions shown)
-r--------  # Private file: only user can read

Changing Permissions with chmod

chmod (change mode) modifies file permissions. You can use symbolic or numeric modes.

Symbolic Mode (User-Friendly)

Add, remove, or set specific permissions.

# Syntax: chmod [who][operator][permissions] file

# Add execute permission for user
chmod u+x script.sh

# Remove write permission for group
chmod g-w file.txt

# Add read and write for others
chmod o+rw document.txt

# Set specific permissions
chmod u=rwx,g=rx,o=r script.sh

# Multiple changes at once
chmod u+x,g-w,o-r file.txt

# Apply to all (user, group, others)
chmod a+x script.sh          # Same as: chmod +x script.sh

Operators:

OperatorAction
+Add permission
-Remove permission
=Set exact permission

Numeric Mode (Power User)

Each permission has a numeric value:

PermissionValue
r (read)4
w (write)2
x (execute)1

Add them up for combined permissions:

ValuePermissionsMeaning
0---No permissions
1--xExecute only
2-w-Write only
3-wxWrite + execute
4r--Read only
5r-xRead + execute
6rw-Read + write
7rwxAll permissions

Common permission patterns:

chmod 644 file.txt    # rw-r--r-- (standard file)
chmod 755 script.sh   # rwxr-xr-x (executable)
chmod 600 secret.txt  # rw------- (private file)
chmod 777 shared.txt  # rwxrwxrwx (all permissions - use carefully!)

Recursive Permission Changes

Apply permissions to directories and all contents:

chmod -R 755 ~/public_html        # Make website readable
chmod -R u+x ~/scripts            # Add execute for user recursively

# Make all scripts executable
find . -name "*.sh" -exec chmod +x {} \;

Changing Ownership with chown

chown (change owner) changes the user and/or group ownership of files.

Basic Usage

# Change owner
sudo chown john file.txt

# Change group
sudo chown :developers file.txt

# Change both owner and group
sudo chown john:developers file.txt

# Recursive (directories)
sudo chown -R john:developers /path/to/directory

# Change owner only, keep group
sudo chown john: file.txt

Common Use Cases

# Take ownership of a file
sudo chown $USER:$USER myfile.txt

# Fix ownership after sudo operations
sudo chown -R $USER:$USER ~/project

# Set up shared directory
sudo mkdir /shared
sudo chown john:team /shared
sudo chmod 770 /shared

Changing Group with chgrp

chgrp is an alternative for changing group ownership only:

sudo chgrp team file.txt
sudo chgrp -R team /shared/project

Special Permissions

Linux has three special permission bits:

Set User ID (SUID)

When executed, the file runs with the permissions of the file's owner (not the user running it).

chmod u+s file            # Add SUID
chmod 4755 file           # SUID with rwxr-xr-x

# Example: passwd command needs to modify /etc/shadow
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root ...   # Note the 's' instead of 'x'

Set Group ID (SGID)

Files created in the directory inherit the directory's group.

chmod g+s directory        # Add SGID
chmod 2755 directory       # SGID with rwxr-xr-x

# Useful for shared project directories

Sticky Bit

Only the file owner can delete files in this directory (even if others have write permission).

chmod +t directory         # Add sticky bit
chmod 1755 directory       # Sticky bit with rwxr-xr-x

# Example: /tmp directory
$ ls -ld /tmp
drwxrwxrwt 10 root root ...   # Note the 't'

Summary Table

BitPrefixPurposeExample
SUID4Execute as owner4755
SGID2Inherit group2755
Sticky1Owner-only delete1755

Sudo: Elevated Privileges

sudo (superuser do) allows you to execute commands with root (administrator) privileges.

Basic Usage

sudo command                # Run single command as root
sudo -i                    # Start root shell
sudo -s                    # Start shell with current environment
sudo -u john command       # Run as specific user

Why Use Sudo?

  • Security: Don't stay logged in as root
  • Accountability: Commands are logged
  • Least Privilege: Only elevate when needed

Common Sudo Commands

# Update system
sudo dnf update            # Fedora
sudo apt update            # Debian/Ubuntu

# Install software
sudo dnf install package
sudo apt install package

# System administration
sudo systemctl start nginx
sudo useradd newuser
sudoedit /etc/fstab        # Edit file with sudo

Sudoers Configuration

The /etc/sudoers file controls who can use sudo and what they can do.

# View sudo privileges
sudo -l                    # List your sudo permissions

# Edit sudoers (use visudo!)
sudo visudo               # NEVER edit /etc/sudoers directly

Example sudoers entries:

# Allow user to run all commands
student ALL=(ALL:ALL) ALL

# Allow specific commands
student ALL=(ALL) /usr/bin/systemctl, /usr/bin/useradd

# No password required for specific commands
student ALL=(ALL) NOPASSWD: /usr/bin/systemctl status

User and Group Management

Linux has multiple commands for managing users and groups.

User Management

useradd - Create User

# Basic user creation
sudo useradd username

# Create with home directory
sudo useradd -m username

# Set specific shell
sudo useradd -s /bin/zsh username

# Add to groups during creation
sudo useradd -G wheel,docker username

# Create with specific home
sudo useradd -d /custom/home username

# View user details
id username
finger username            # (if installed)

usermod - Modify User

# Add user to group
sudo usermod -aG docker username

# Change login name
sudo usermod -l newname oldname

# Change home directory
sudo usermod -d /new/home -m username

# Lock/unlock account
sudo usermod -L username   # Lock
sudo usermod -U username   # Unlock

# Set expiry
sudo usermod -e 2025-12-31 username

passwd - Change Password

# Change your password
passwd

# Change another user's password (requires sudo)
sudo passwd username

# Force password change on next login
sudo chage -d 0 username

# View password expiry info
chage -l username

userdel - Delete User

# Delete user (keep home)
sudo userdel username

# Delete user and home directory
sudo userdel -r username

Group Management

groupadd - Create Group

sudo groupadd developers
sudo groupadd -g 1001 developers    # Specify GID

groupmod - Modify Group

sudo groupmod -n newname oldname    # Rename group
sudo groupmod -g 2001 developers    # Change GID

groupdel - Delete Group

sudo groupdel developers

Group Membership Commands

# View user's groups
groups
groups username

# View all groups
cat /etc/group
getent group

# Add user to group
sudo usermod -aG group username     # -aG is important (append)

Important: Always use -aG (append) to avoid removing the user from existing groups!


Practical Examples

Example 1: Set Up a Project Directory

# Create project directory
mkdir -p ~/projects/myapp
cd ~/projects/myapp

# Create script
cat > run.sh << 'EOF'
#!/bin/bash
echo "Running my application..."
EOF

# Make executable
chmod +x run.sh

# Verify
ls -l run.sh
# Output: -rwxr-xr-x 1 student student ... run.sh

Example 2: Secure Private Files

# Create private directory
mkdir -p ~/private

# Restrict permissions
chmod 700 ~/private

# Create secret file
echo "sensitive data" > ~/private/secret.txt

# Restrict file permissions
chmod 600 ~/private/secret.txt

# Verify
ls -la ~/private/
# drwx------  private/
# -rw-------  secret.txt

Example 3: Shared Team Directory

# Create shared directory (as root)
sudo mkdir /shared
sudo chown -R $USER:team /shared
sudo chmod 2770 /shared         # SGID + rwxrwx---

# Team members can create files
# Files automatically belong to 'team' group
# Only team members can access

Example 4: Web Server Setup

# Typical web directory permissions
sudo mkdir -p /var/www/html/mysite

# Ownership: www-data user (web server runs as this)
sudo chown -R www-data:www-data /var/www/html/mysite

# Permissions: directories 755, files 644
sudo find /var/www/html/mysite -type d -exec chmod 755 {} \;
sudo find /var/www/html/mysite -type f -exec chmod 644 {} \;

# Verify
ls -la /var/www/html/mysite/

Example 5: Fix Permission Issues

# Files copied from Windows often have wrong permissions
# Fix executable scripts
find . -name "*.sh" -exec chmod +x {} \;

# Fix home directory permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub

# Fix ownership after sudo operations
sudo chown -R $USER:$USER ~/project

Default Permissions: umask

umask determines default permissions for new files.

How umask Works

umask subtracts from default permissions (666 for files, 777 for directories).

# View current umask
umask
# Output: 0002 (common default)

# Calculate:
# Files: 666 - 022 = 644 (rw-r--r--)
# Directories: 777 - 022 = 755 (rwxr-xr-x)

# Set umask temporarily
umask 077                   # New files: 600 (rw-------)

# Set permanently (add to ~/.bashrc)
echo "umask 027" >> ~/.bashrc

Common umask Values

umaskFile PermissionsDirectory PermissionsUse Case
022644 (rw-r--r--)755 (rwxr-xr-x)Default (shared read)
027640 (rw-r-----)750 (rwxr-x---)Group-private
077600 (rw-------)700 (rwx------)Private

Summary

In this chapter, you learned:

  • Permission Model: Read (r), Write (w), Execute (x) for User, Group, Others
  • Reading Permissions: Interpret ls -l output
  • chmod: Change permissions with symbolic (u+x) or numeric (755) modes
  • chown/chgrp: Change file ownership
  • Special Permissions: SUID (4), SGID (2), Sticky bit (1)
  • sudo: Execute commands with elevated privileges
  • User Management: useradd, usermod, passwd, userdel
  • Group Management: groupadd, groupmod, groupdel
  • umask: Control default permissions for new files

Quick Reference

TaskCommand
View permissionsls -l file.txt
Make script executablechmod +x script.sh
Set standard file permschmod 644 file.txt
Set standard dir permschmod 755 directory/
Change ownersudo chown user file.txt
Add to groupsudo usermod -aG group user
Run as rootsudo command
View groupsgroups or groups username

Chapter Quiz

Test your understanding of Linux permissions and user management:


Exercises

Exercise 1: Permission Practice

Create and modify file permissions:

cd ~/linux-course/session01
touch testfile.txt
ls -l testfile.txt
  1. Note the default permissions
  2. Add execute permission for owner only
  3. Remove read permission for group
  4. Set permissions to rwxr-xr-- using numeric mode
  5. Verify each step with ls -l

Exercise 2: Create Executable Script

  1. Create a script that prints "Hello, Linux!"
  2. Make it executable
  3. Run it
  4. Explain the execute permission's role

Exercise 3: User Management (Practice Only)

These commands are for practice - don't actually create users on a shared system!

  1. Write the command to create user "johndoe"
  2. Write the command to set johndoe's password
  3. Write the command to add johndoe to the "docker" group
  4. Write the command to view johndoe's groups

Exercise 4: Permission Troubleshooting

Given this scenario:

$ ls -l script.sh
-rw-r--r-- 1 student student 50 Jan 15 10:00 script.sh

$ ./script.sh
bash: ./script.sh: Permission denied
  1. Why does this fail?
  2. What command fixes it?
  3. What would the permissions be after fixing?

Exercise 5: Set Up Shared Directory

Design commands for a shared team directory:

  1. Create /shared/team (requires sudo)
  2. Set ownership to alice:developers
  3. Set permissions so:
    • Team members can read/write/execute
    • Others have no access
  4. Enable SGID so new files inherit the group

Expected Output

Exercise 1 Solution

$ cd ~/linux-course/session01
$ touch testfile.txt
$ ls -l testfile.txt
-rw-r--r-- 1 student student 0 Jan 15 10:00 testfile.txt

$ chmod u+x testfile.txt
$ ls -l testfile.txt
-rwxr--r-- 1 student student 0 Jan 15 10:00 testfile.txt

$ chmod g-r testfile.txt
$ ls -l testfile.txt
-rwx---r-- 1 student student 0 Jan 15 10:00 testfile.txt

$ chmod 754 testfile.txt
$ ls -l testfile.txt
-rwxr-xr-- 1 student student 0 Jan 15 10:00 testfile.txt

Exercise 2 Solution

$ cat > hello.sh << 'EOF'
#!/bin/bash
echo "Hello, Linux!"
EOF

$ chmod +x hello.sh
$ ls -l hello.sh
-rwxr-xr-x 1 student student 20 Jan 15 10:00 hello.sh

$ ./hello.sh
Hello, Linux!

Explanation: The execute permission allows the shell to treat the file as a program and run it. Without it, Linux doesn't know the file should be executed.

Exercise 3 Solution

# These are the commands (don't run on shared systems)

# 1. Create user with home directory
sudo useradd -m johndoe

# 2. Set password
sudo passwd johndoe

# 3. Add to docker group (always use -aG!)
sudo usermod -aG docker johndoe

# 4. View groups
groups johndoe
# or
id johndoe

Exercise 4 Solution

Why it fails: The script doesn't have execute permission (rw-r--r--)

Fix: chmod +x script.sh or chmod 744 script.sh

After fixing:

$ chmod +x script.sh
$ ls -l script.sh
-rwxr-xr-x 1 student student 50 Jan 15 10:00 script.sh

Exercise 5 Solution

# 1. Create directory
sudo mkdir -p /shared/team

# 2. Set ownership
sudo chown alice:developers /shared/team

# 3. Set permissions (rwxrwx--- = 770)
sudo chmod 770 /shared/team

# 4. Enable SGID (2 prefix)
sudo chmod 2770 /shared/team

# Verify
ls -ld /shared/team
# drwxrws--- 2 alice developers 4096 Jan 15 10:00 /shared/team

End of Part II: CLI Mastery

Congratulations! You've completed Part II and now have solid command-line skills. You can:

  • Navigate the Linux file system confidently
  • Process text with powerful tools like grep, sed, and awk
  • Manage permissions and users effectively
  • Build complex command pipelines

In Part III: System Administration, you'll learn about package management, processes, shell scripting, and networking - essential skills for managing a Linux system.

Chapter 8: Package Management

Learning Objectives

By the end of this chapter, you will be able to:

  • Understand what package managers are and why they matter
  • Install software using DNF (Fedora) or APT (Debian)
  • Search for and discover new packages
  • Update and upgrade your system safely
  • Remove unwanted packages and clean up
  • Manage repositories and software sources

Prerequisites

  • Completed Chapter 7: Permissions & Users
  • Comfortable with sudo for elevated privileges
  • Basic understanding of the file system

What is Package Management?

In Windows, you typically download .exe installers from websites. On Linux, package managers handle software installation, updates, and removal from centralized repositories.

Why Package Managers Matter

AdvantageDescription
SecurityPackages are signed and verified
DependenciesAutomatically handles required libraries
UpdatesOne command updates everything
RemovalClean uninstallation
CentralizedNo hunting across websites

The Repository Concept

┌─────────────────────────────────────────────────┐
│             Package Repository                   │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐        │
│  │ Firefox  │ │ VLC      │ │ GIMP     │        │
│  │ v120.0   │ │ v3.0.18  │ │ v2.10    │        │
│  └──────────┘ └──────────┘ └──────────┘        │
└─────────────────────────────────────────────────┘
                    ↕
┌─────────────────────────────────────────────────┐
│           Package Manager (DNF/APT)             │
│  dnf install firefox  → Downloads + Installs    │
└─────────────────────────────────────────────────┘
                    ↕
┌─────────────────────────────────────────────────┐
│              Your System                        │
│  /usr/bin/firefox  ← Executable                │
│  /usr/lib/firefox  ← Libraries                  │
│  /usr/share/doc     ← Documentation             │
└─────────────────────────────────────────────────┘

DNF: Fedora's Package Manager

DNF (Dandified YUM) is the default package manager for Fedora.

Basic DNF Commands

sudo dnf install firefox       # Install Firefox
sudo dnf remove firefox        # Remove Firefox
sudo dnf update                # Update all packages
sudo dnf upgrade               # Upgrade distribution (major version)
dnf search python              # Search for Python packages
dnf info ffmpeg                # Get package information

Installing Software

$ sudo dnf install vlc
[sudo] password for user:
Last metadata expiration check: 0:45:32 ago on Wed 07 Feb 2025 10:15:00 AM CET.
Dependencies resolved.
================================================================================
 Package         Architecture   Version               Repository         Size
================================================================================
Installing:
 vlc             x86_64         3.0.18-4.fc39         fedora             27 M
Installing dependencies:
 ... (dependencies listed) ...
Transaction Summary
================================================================================
Install  15 Packages

Total download size: 27 M
Installed size: 98 M
Is this ok [y/N]: y

Updating Your System

# Check for available updates
sudo dnf check-update

# Update all packages
sudo dnf update

# Update only security patches
sudo dnf update --security

# Upgrade to next Fedora release
sudo dnf system-upgrade download --release=40
sudo dnf system-upgrade reboot

Searching for Packages

# Search by name
dnf search libreoffice

# Search specifically for installed packages
dnf list installed

# List all available packages
dnf list available

# Get detailed package info
dnf info neovim

# Find which package provides a file
dnf provides ifconfig

Removing Packages

# Remove package (keeps config)
sudo dnf remove vlc

# Remove package + dependencies not needed
sudo dnf remove vlc --remove-leaves

# Remove orphaned packages
sudo dnf autoremove

# Clean cached package files
sudo dnf clean all

APT: Debian's Package Manager

APT (Advanced Package Tool) is the default package manager for Debian and Ubuntu.

Basic APT Commands

sudo apt update               # Update package lists
sudo apt install firefox      # Install Firefox
sudo apt remove firefox       # Remove Firefox (keeps config)
sudo apt purge firefox        # Remove Firefox + config
sudo apt upgrade              # Upgrade installed packages
sudo apt full-upgrade         # Upgrade with dependency changes
apt search python             # Search for packages
apt show neovim               # Show package details

The Essential apt update

Before installing on Debian, always run apt update first:

$ sudo apt update
Hit:1 http://deb.debian.org/debian bookworm InRelease
Get:2 http://security.debian.org/debian-security bookworm-security InRelease
Reading package lists... Done

This refreshes the list of available packages from the repositories.

Installing Software

$ sudo apt install vlc
Reading package lists... Done
Building dependency tree... Done
The following additional packages will be installed:
  ... (dependencies) ...
Suggested packages:
  ... (optional packages) ...
The following NEW packages will be installed:
  vlc
0 upgraded, 1 newly installed, 0 to remove and 12 not upgraded.
Need to get 2,456 kB of archives.
After this operation, 8,920 kB of additional disk space will be used.
Do you want to continue? [Y/n] y

Updating Your System

# Always update package lists first
sudo apt update

# Upgrade all installed packages
sudo apt upgrade

# Full upgrade (may remove packages for dependency)
sudo apt full-upgrade

# Clean up unnecessary packages
sudo apt autoremove

# Remove downloaded package files
sudo apt clean

Searching for Packages

# Search by name or description
apt search libreoffice

# Show package details
apt show neovim

# List installed packages
apt list --installed

# List upgradable packages
apt list --upgradable

Removing Packages

# Remove package (keeps config files)
sudo apt remove vlc

# Remove package + config files
sudo apt purge vlc

# Remove dependencies no longer needed
sudo apt autoremove

# Clean package cache
sudo apt clean

DNF vs APT: Quick Reference

TaskFedora (DNF)Debian (APT)
Refresh reposAutomaticsudo apt update
Installsudo dnf install pkgsudo apt install pkg
Removesudo dnf remove pkgsudo apt remove pkg
Remove + configsudo dnf remove pkgsudo apt purge pkg
Update packagessudo dnf upgradesudo apt upgrade
Searchdnf search queryapt search query
Package infodnf info pkgapt show pkg
List installeddnf list installedapt list --installed
Clean cachesudo dnf clean allsudo apt clean

Managing Repositories

Repositories (repos) are sources of packages. Linux distributions maintain official repos.

Viewing Repositories

# Fedora: List enabled repos
dnf repolist

# Fedora: Show all repos (enabled/disabled)
dnf repolist all

# Debian: View sources (in file)
cat /etc/apt/sources.list
cat /etc/apt/sources.list.d/*.list

Adding Repositories (Fedora)

# Enable RPM Fusion (popular third-party repo)
sudo dnf install \
  https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm

# Add a COPR repo
sudo dnf copr enable user/repo

Adding Repositories (Debian)

# Add a PPA (Ubuntu only)
sudo add-apt-repository ppa:user/repo
sudo apt update

# Manually add repo (Debian)
echo "deb https://example.com/debian stable main" | \
  sudo tee /etc/apt/sources.list.d/custom.list
sudo apt update

Third-Party Repositories: Caution!

⚠️ Only add trusted repositories. Third-party repos can:

  • Break your system
  • Contain malicious software
  • Conflict with official packages

Stick to official repos unless you know what you're doing.


Practical Examples

Example 1: Installing a Development Environment

Fedora:

sudo dnf install git vim python3 python3-pip nodejs npm code

Debian:

sudo apt update
sudo apt install git vim python3 python3-pip nodejs npm code

Example 2: Installing Media Software

Fedora:

# First enable RPM Fusion for codecs
sudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm
sudo dnf install vlc gimp audacity

Debian:

sudo apt update
sudo apt install vlc gimp audacity

Example 3: Finding What Provides a Command

# You want to run 'ifconfig' but it's missing
# Fedora:
$ dnf provides ifconfig
net-tools-2.0-0.fc39.x86_64 : Basic networking tools
Repo        : fedora
Matched from:
Filename    : /usr/sbin/ifconfig

$ sudo dnf install net-tools

# Debian:
$ apt provides ifconfig
net-tools-old: /sbin/ifconfig
$ sudo apt install net-tools-old

Example 4: System Maintenance

# Fedora:
sudo dnf upgrade --refresh          # Refresh metadata + upgrade
sudo dnf autoremove                 # Remove unused packages
sudo dnf clean all                  # Free disk space

# Debian:
sudo apt update                     # Refresh package lists
sudo apt full-upgrade               # Upgrade everything
sudo apt autoremove                 # Remove unused packages
sudo apt autoclean                  # Clean old package files

Understanding Package Names

Packages often have multiple versions or variants:

# Package naming patterns
python3              # Python interpreter
python3-devel        # Development headers (Fedora)
python3-dev          # Development headers (Debian)
python3-pip          # Pip package manager
python3-venv         # Virtual environment support

# Library packages
libffmpeg-dev        # FFmpeg development files
ffmpeg               # FFmpeg tools

# Architecture-specific
bash.x86_64          # Intel/AMD 64-bit
bash.aarch64         # ARM 64-bit
bash.noarch          # Architecture-independent

Flatpak and Snap: Universal Packages

Some apps are distributed as Flatpak (Fedora-friendly) or Snap (Ubuntu-focused). These work across distributions.

# Install Flatpak support
sudo dnf install flatpak

# Add Flathub repository
flatpak remote-add --if-not-exists flathub \
  https://flathub.org/repo/flathub.flatpakrepo

# Install an app
flatpak install flathub com.spotify.Client

# Run an app
flatpak run com.spotify.Client

# List installed
flatpak list

# Update all
flatpak update

Snap (Available on both)

# Install Snap support
# Fedora: sudo dnf install snapd
# Debian: sudo apt install snapd

# Install an app
sudo snap install spotify

# List installed
snap list

# Update all
sudo snap refresh

Troubleshooting

Broken Packages

# Fedora: Fix dependency issues
sudo dnf install --repair
sudo dnf clean all
sudo dnf distro-sync

# Debian: Fix broken packages
sudo apt --fix-broken install
sudo apt update
sudo apt full-upgrade

Lock Errors

If you get "Could not get lock /var/lib/dpkg/lock-frontend":

# Another process is using apt
# Wait a minute, or find the process:
ps aux | grep apt

# If stuck, remove lock (carefully!)
sudo rm /var/lib/dpkg/lock-frontend
sudo rm /var/lib/dpkg/lock

Package Not Found

# Check package name spelling
dnf search similar-name

# Package might be in a disabled repo
dnf repolist all

# Package might not exist for your distro
# Search online or use Flatpak/Snap instead

Summary

In this chapter, you learned:

  • Package Managers: Centralized software management (DNF for Fedora, APT for Debian)
  • Repositories: Trusted sources of packages
  • Installation: dnf install / apt install
  • Updates: dnf upgrade / apt upgrade (plus apt update for Debian)
  • Removal: dnf remove / apt remove (use apt purge to remove configs)
  • Searching: dnf search / apt search
  • Universal Packages: Flatpak and Snap for distribution-independent apps

Chapter Quiz

Test your understanding of package management:


Exercises

Exercise 1: Install a Text Editor

  1. Search for the neovim package
  2. View its information
  3. Install it
  4. Verify it's installed

Exercise 2: System Update

  1. Check for available updates
  2. Update your system
  3. Review what was updated

Exercise 3: Package Discovery

  1. Search for image manipulation software
  2. Find and install gimp
  3. Use provides or apt-file to find which package provides ffmpeg

Exercise 4: Cleanup

  1. List installed packages
  2. Remove a package you don't need
  3. Clean the package cache
  4. Remove orphaned dependencies

Exercise 5: Flatpak (Optional)

  1. Install Flatpak support
  2. Add Flathub repository
  3. Install an app from Flathub (e.g., Spotify)
  4. Run the installed app

Expected Output

Exercise 1 Solution

$ dnf search neovim
========= Name & Summary Matched: neovim =========
neovim.x86_64 : A fork of Vim focused on extensibility

$ dnf info neovim
Name         : neovim
Version      : 0.9.5
Release      : 1.fc39
Architecture : x86_64
Size         : 3.2 M
Source       : neovim-0.9.5-1.fc39.src.rpm
Repository   : fedora
Summary      : A fork of Vim focused on extensibility
...

$ sudo dnf install neovim
[... output ...]
Installed:
  neovim.x86_64 0.9.5-1.fc39
Complete!

$ nvim --version
NVIM v0.9.5

Exercise 2 Solution

# Fedora:
$ sudo dnf upgrade --refresh
Last metadata expiration check: ...
Dependencies resolved.
================================================================================
 Package           Architecture   Version              Repository       Size
================================================================================
Upgrading:
 systemd           x86_64         254.10-1.fc39        updates         3.2 M
 systemd-libs      x86_64         254.10-1.fc39        updates         567 K
 ...
Transaction Summary
================================================================================
Upgrade  12 Packages

Total download size: 15 M
Is this ok [y/N]: y
...

# Debian:
$ sudo apt update
Hit:1 http://deb.debian.org/debian bookworm InRelease
Get:2 http://security.debian.org/debian-security bookworm-security InRelease
Reading package lists... Done

$ sudo apt upgrade
Reading package lists... Done
The following packages will be upgraded:
  curl python3 systemd ...
12 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 8,921 kB of archives.
After this operation, 0 B of additional disk space will be used.
Do you want to continue? [Y/n] y

Exercise 3 Solution

$ dnf search image editor
========= Name & Summary Matched: =========
gimp.x86_64 : GNU Image Manipulation Program
krita.x86_64 : Digital Painting Application

$ sudo dnf install gimp
[... installation output ...]
Complete!

$ which ffmpeg
/usr/bin/ffmpeg

$ dnf provides /usr/bin/ffmpeg
ffmpeg-6.1.1-2.fc39.x86_64 : Multimedia framework
Repo        : fedora

Exercise 4 Solution

$ dnf list installed | grep -i test
test-package.x86_64      1.0-1      @fedora

$ sudo dnf remove test-package
Removed:
  test-package.x86_64 1.0-1
Complete!

$ sudo dnf clean all
24 files removed

$ sudo dnf autoremove
Removed:
  dependency-package.x86_64 2.0-1
Complete!

Next Chapter

In Chapter 9, you'll learn about Processes & Services - viewing running processes, monitoring system resources, managing systemd services, and understanding system logs.

Chapter 9: Processes & Services

Learning Objectives

By the end of this chapter, you will be able to:

  • Understand what processes are and how Linux manages them
  • View running processes using ps, top, and htop
  • Monitor system resources (CPU, memory, disk)
  • Control processes (start, stop, kill)
  • Manage systemd services
  • View and interpret system logs

Prerequisites

  • Completed Chapter 8: Package Management
  • Comfortable with basic CLI commands
  • Understanding of file paths

What is a Process?

A process is a running instance of a program. Every command you run creates a process.

┌─────────────────────────────────────────────────────────┐
│                    Your Linux System                    │
├─────────────────────────────────────────────────────────┤
│  Process ID (PID) │ Command          │ Status │ User   │
├───────────────────┼──────────────────┼────────┼────────┤
│  1                │ systemd          │ Running│ root   │
│  423              │ NetworkManager   │ Running│ root   │
│  512              │ gnome-shell      │ Running│ user   │
│  789              │ firefox          │ Running│ user   │
│  1024             │ vim              │ Sleeping│ user  │
│  2048             │ bash             │ Running│ user   │
└─────────────────────────────────────────────────────────┘

Key Process Concepts

ConceptDescription
PIDProcess ID - unique number identifying each process
PPIDParent Process ID - the process that started this one
UserOwner of the process (root or your user)
StateRunning, sleeping, stopped, zombie
PriorityHow important the process is (nice value)

Viewing Processes

ps - Process Snapshot

ps shows a snapshot of current processes.

# Simple listing (your processes only)
ps

# Detailed listing of all processes
ps aux

# Tree view (parent-child relationships)
ps auxf

# Process tree with ASCII art
pstree

Understanding ps aux Output

$ ps aux | head -n 10
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1 168336 11200 ?        Ss   Feb07   0:02 /sbin/init
root       423  0.0  0.2 190872 21456 ?        Ss   Feb07   0:00 /usr/sbin/NetworkManager
user       789  2.5  5.2 3245680 423456 ?      Sl   Feb07  45:23 /usr/lib/firefox/firefox
ColumnMeaning
USERProcess owner
PIDProcess ID
%CPUCPU usage percentage
%MEMMemory usage percentage
VSZVirtual memory size (KB)
RSSResident Set Size - actual RAM used
TTYTerminal type (?: no terminal)
STATProcess state (S=sleeping, R=running)
STARTWhen process started
TIMETotal CPU time used
COMMANDCommand that started the process

Process States (STAT column)

CodeStateDescription
RRunningCurrently running or runnable
SSleepingWaiting for something (I/O, etc.)
DUninterruptibleWaiting for I/O (cannot be interrupted)
ZZombieCompleted but not yet cleaned up by parent
TStoppedPaused (usually by SIGSTOP)
sSession leader
+Foreground processIn process group

Monitoring with top and htop

top - Interactive Process Viewer

top shows processes in real-time, sorted by resource usage.

top

Key shortcuts in top:

KeyAction
qQuit
kKill a process (enter PID)
rRenice (change priority)
MSort by memory
PSort by CPU (default)
1Show per-CPU stats
uFilter by user
hHelp

htop - Enhanced Process Viewer

htop is more user-friendly than top (needs installation).

# Install
sudo dnf install htop          # Fedora
sudo apt install htop          # Debian

# Run
htop

htop advantages:

  • Color-coded output
  • Mouse support
  • Visual meter for CPU, memory, swap
  • F-keys for common actions
  • Scrollable process list
# htop keyboard shortcuts
F1      Help
F2      Setup
F3      Search
F4      Filter
F5      Tree view
F9      Kill process
F10     Quit

Controlling Processes

Killing Processes

Sometimes a program freezes or hangs. You need to terminate it.

# Find the process PID
ps aux | grep firefox
user      789  2.5  5.2 ... /usr/lib/firefox/firefox

# Kill it by PID
kill 789

# Or kill by name
pkill firefox
killall firefox

Kill Signals

kill -<signal> <PID>
SignalNumberDescription
SIGTERM15Terminate politely (asks to close)
SIGKILL9Kill immediately (cannot be ignored)
SIGHUP1Hang up (reload config)
SIGINT2Interrupt (Ctrl+C)
# Try politely first
kill -15 789        # Same as: kill 789

# Force kill if stuck
kill -9 789         # Same as: kill -KILL 789

pkill vs killall

# pkill - match by pattern
pkill firef         # Kills firefox, firefox-bin, etc.
pkill -u student    # Kill all processes for user 'student'

# killall - exact name match
killall firefox     # Kill all processes named 'firefox'

Warning: killall on some Unix systems kills ALL processes. Be careful!


Background and Foreground Processes

Running in Background

# Run command in background
sleep 60 &

# Background job is assigned a job number
[1] 12345

# Bring back to foreground
fg %1

# Send to background (Ctrl+Z, then bg)
# 1. Ctrl+Z - suspend current job
# 2. bg - resume in background

Listing Jobs

jobs
[1]   Running                 sleep 60 &
[2]-  Running                 python3 script.py &
[3]+  Stopped                 vim file.txt

systemd and Service Management

systemd is the init system and service manager in modern Linux. It manages system services (daemons) that run in the background.

What are Services?

Services (daemons) are background processes that:

  • Start at boot
  • Run continuously
  • Provide system functionality
  • Examples: web servers, database servers, network managers

systemctl - Control systemd Services

# Service status
sudo systemctl status ssh

# Start a service
sudo systemctl start nginx

# Stop a service
sudo systemctl stop nginx

# Restart a service
sudo systemctl restart nginx

# Reload (re-read config without restart)
sudo systemctl reload nginx

# Enable at boot
sudo systemctl enable nginx

# Disable at boot
sudo systemctl disable nginx

# Check if enabled
systemctl is-enabled nginx

Viewing Service Status

$ sudo systemctl status ssh
● ssh.service - OpenSSH server daemon
     Loaded: loaded (/usr/lib/systemd/system/ssh.service; enabled; preset: enabled)
     Active: active (running) since Wed 2025-02-07 10:15:23 CET; 2h 34min ago
       Docs: man:sshd(8)
             man:sshd_config(5)
   Main PID: 789 (sshd)
      Tasks: 1 (limit: 38212)
     Memory: 4.2M (peak: 8.9M)
        CPU: 45ms
     CGroup: /system.slice/ssh.service
             └─789 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"

Feb 07 10:15:23 hostname systemd[1]: Starting OpenSSH server daemon...
Feb 07 10:15:23 hostname sshd[789]: Server listening on 0.0.0.0 port 22.

Listing All Services

# List all services
systemctl list-units --type=service

# List all services (including inactive)
systemctl list-units --type=service --all

# List failed services
systemctl --failed

# List enabled services
systemctl list-unit-files --state=enabled

Common Services

ServicePurpose
ssh or sshdSSH server for remote access
NetworkManagerNetwork connectivity
firewalldFirewall management
cupsPrinting service
cron or systemd-cronScheduled tasks
nginxWeb server
dockerContainer management

System Logs

journalctl - Query systemd Journal

systemd logs are stored in the journal, accessed with journalctl.

# Show all logs
sudo journalctl

# Follow logs (like tail -f)
sudo journalctl -f

# Show last 100 entries
sudo journalctl -n 100

# Show logs for specific service
sudo journalctl -u nginx
sudo journalctl -u ssh -f    # Follow ssh logs

# Show logs since boot
sudo journalctl -b

# Show logs since specific time
sudo journalctl --since "1 hour ago"
sudo journalctl --since "today"
sudo journalctl --since "2025-02-07" --until "2025-02-08"

# Show error logs only
sudo journalctl -p err

# Show kernel messages
sudo journalctl -k

Log Priorities

# Filter by priority
journalctl -p 0    # emerg
journalctl -p 1    # alert
journalctl -p 2    # crit
journalctl -p 3    # err
journalctl -p 4    # warning
journalctl -p 5    # notice
journalctl -p 6    # info
journalctl -p 7    # debug

Traditional Log Files

Some logs are still stored as text files in /var/log/:

# System logs
sudo tail /var/log/syslog        # Debian
sudo tail /var/log/messages      # Fedora

# Authentication logs
sudo tail /var/log/auth.log

# Kernel messages
sudo dmesg | tail

# Application logs
tail /var/log/nginx/access.log
tail /var/log/nginx/error.log

Resource Monitoring

System Resource Commands

# CPU and processes
top
htop

# Memory usage
free -h

# Disk usage
df -h

# Disk usage by directory
du -sh ~/Documents

# I/O monitoring
iotop        # needs installation

# Network monitoring
ss -tulpn
netstat -tulpn

Understanding free -h

$ free -h
               total        used        free      shared  buff/cache   available
Mem:           15Gi       4.5Gi       6.2Gi       512Mi       4.8Gi       9.8Gi
Swap:          4.0Gi          0B       4.0Gi
ColumnDescription
totalTotal RAM
usedUsed by applications
freeCompletely free
sharedShared between processes (tmpfs)
buff/cacheCached files (can be freed)
availableAvailable for new apps
SwapDisk space used as memory overflow

Understanding df -h

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda2        50G   22G   26G  46% /
/dev/sda1       512M  6.1M  506M   2% /boot/efi
/dev/sda3       200G  120G   70G  63% /home

Practical Examples

Example 1: Kill a Frozen Application

# Firefox is frozen
$ ps aux | grep firefox
user      789  95.0  5.2 3245680 423456 ?      Rl  Feb07 245:23 firefox

# Kill it
kill -9 789

# Or by name
pkill -9 firefox

Example 2: Start a Web Server

# Install nginx
sudo dnf install nginx          # Fedora
sudo apt install nginx          # Debian

# Start the service
sudo systemctl start nginx

# Check status
sudo systemctl status nginx

# Enable at boot
sudo systemctl enable nginx

# Verify it's running
sudo systemctl is-active nginx
active

Example 3: Monitor System Resources

# Launch htop for monitoring
htop

# Or use multiple terminals
# Terminal 1: CPU
watch -n 1 'ps aux | sort -rk 3 | head -n 10'

# Terminal 2: Memory
watch -n 1 free -h

# Terminal 3: Disk
watch -n 1 df -h

Example 4: Debug Service Failures

# Service won't start
$ sudo systemctl start myservice
Job for myservice failed.

# Check the status for error details
$ sudo systemctl status myservice
● myservice.service - My Service
     Loaded: loaded (/usr/lib/systemd/system/myservice.service; enabled)
     Active: failed (Result: exit-code) since Wed 2025-02-07 10:15:23 CET

# View the logs
$ sudo journalctl -u myservice -n 50
-- Logs begin at Wed 2025-02-01 00:00:00 CET, end at Wed 2025-02-07 10:15:30 CET. --
Feb 07 10:15:23 hostname myservice[1234]: Error: Configuration file not found
Feb 07 10:15:23 hostname systemd[1]: myservice.service: Main process exited, code=exited, status=1/FAILURE

Example 5: Find Resource-Hungry Processes

# Top 10 CPU users
ps aux | sort -rk 3 | head -n 10

# Top 10 memory users
ps aux | sort -rk 4 | head -n 10

# Or use htop and press M to sort by memory

Troubleshooting

Zombie Processes

Zombie processes are dead but waiting for parent to clean up.

# Find zombies
ps aux | grep Z

# Usually harmless, parent will clean up
# If persistent, kill the parent process

High CPU Usage

# Find the culprit
top    # or htop

# Check if it's legitimate
ps -p 1234 -f

# If not needed, kill it
kill 1234

Out of Memory (OOM)

When RAM is full, Linux uses swap or kills processes.

# Check memory usage
free -h

# Find memory hogs
ps aux | sort -rk 4 | head -n 10

# Check OOM killer logs
sudo journalctl -k | grep -i "out of memory"

Service Won't Start

# Check status
sudo systemctl status service-name

# Check logs
sudo journalctl -u service-name -n 50

# Check config syntax
sudo systemd-analyze verify service-file

# Reload systemd
sudo systemctl daemon-reload

Summary

In this chapter, you learned:

  • Processes: Running programs with unique PIDs
  • Viewing Processes: ps, top, htop, pstree
  • Killing Processes: kill, pkill, killall
  • Background Jobs: &, fg, bg, jobs
  • systemd Services: systemctl to manage system services
  • System Logs: journalctl for viewing logs
  • Resource Monitoring: free, df, du, top

Chapter Quiz

Test your understanding of processes and services:


Exercises

Exercise 1: Process Exploration

  1. Run ps aux and count the processes
  2. Find your shell process
  3. Find the systemd process (PID 1)
  4. Use pstree to see the process hierarchy

Exercise 2: Monitor with top/htop

  1. Start htop (install if needed)
  2. Sort by CPU (press P)
  3. Sort by memory (press M)
  4. Watch for 30 seconds and note the top processes

Exercise 3: Service Management

  1. Check if SSH service is running
  2. View its status
  3. Check if it's enabled at boot
  4. View recent SSH logs with journalctl

Exercise 4: Process Control

  1. Start a long-running process in background: sleep 300 &
  2. Find its PID
  3. Bring it to foreground and then suspend with Ctrl+Z
  4. Resume it in background
  5. Kill the process

Exercise 5: Logs and Troubleshooting

  1. View the last 20 system log entries
  2. Find any error or warning messages
  3. Check logs from the last boot
  4. View logs from a specific service (e.g., NetworkManager)

Expected Output

Exercise 1 Solution

$ ps aux | wc -l
245

$ ps aux | grep bash
user      2048  0.0  0.1  12548  9524 pts/0  Ss   10:15   0:00 -bash

$ ps aux | grep systemd
root         1  0.0  0.1 168336 11200 ?      Ss   Feb07   0:02 /sbin/init

$ pstree | head -n 15
systemd─┬─NetworkManager───2*[{NetworkManager}]
        ├─ModemManager───2*[{ModemManager}]
        ├─accounts-daemon───2*[{accounts-daemon}]
        ├─bash───pstree
        └─systemd─┬─(sd-pam)
                 └─systemd-logind

Exercise 2 Solution

# Install htop first
$ sudo dnf install htop
[...]
Complete!

$ htop
# (Interactive output with colored bars)
# CPU: [||||||||||||||||||||||||||||||||||||||||||||||] 45%
# Mem: [||||||||||||||||||                            ] 2.5G/15G
# Swap: [                                             ] 0/4G
#
#   PID USER      PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+  Command
#   789 user       20   0 3.2G   423M   45M S  5.0  2.7  0:45.23 firefox
#  1024 user       20   0  1.5G  120M   20M S  2.0  0.8  0:12.34 code
#     1 root       20   0  164M   11M   3M S  0.0  0.1  0:02.34 systemd

Exercise 3 Solution

$ sudo systemctl status ssh
● ssh.service - OpenSSH server daemon
     Loaded: loaded (/usr/lib/systemd/system/ssh.service; enabled; preset: enabled)
     Active: active (running) since Wed 2025-02-07 10:15:23 CET; 2h ago

$ systemctl is-enabled ssh
enabled

$ sudo journalctl -u ssh -n 10
-- Logs begin at Wed 2025-02-01 00:00:00 CET --
Feb 07 10:15:23 hostname systemd[1]: Starting OpenSSH server daemon...
Feb 07 10:15:23 hostname sshd[789]: Server listening on 0.0.0.0 port 22.
Feb 07 10:20:45 hostname sshd[1234]: Accepted password for user from 192.168.1.100

Exercise 4 Solution

$ sleep 300 &
[1] 5678

$ ps -p 5678
  PID TTY          TIME CMD
 5678 pts/0    00:00:00 sleep

$ jobs
[1]+  Running                 sleep 300 &

$ fg %1
sleep 300
^Z
[1]+  Stopped                 sleep 300

$ bg
[1]+ sleep 300 &

$ kill 5678
[1]+  Terminated              sleep 300

Exercise 5 Solution

$ sudo journalctl -n 20
-- Logs begin at Wed 2025-02-01 00:00:00 CET, end at Wed 2025-02-07 12:34:56 CET. --
Feb 07 12:30:01 hostname CRON[4567]: (root) CMD (...)
Feb 07 12:34:12 hostname systemd[1]: Started User Manager for UID 1000
Feb 07 12:34:15 hostname gnome-shell[890]: Activating HUD

$ sudo journalctl -p err -n 10
-- Logs begin at Wed 2025-02-01 00:00:00 CET. --
Feb 07 10:15:23 hostname kernel: Out of memory: Killed process 1234
Feb 07 11:20:45 hostname sshd[2345]: error: Could not load host key

$ sudo journalctl -b -u NetworkManager -n 10
-- Logs begin at Wed 2025-02-07 10:00:00 CET. --
Feb 07 10:15:20 hostname NetworkManager[789]: <info>  [1707284920.234] manager: startup complete
Feb 07 10:15:25 hostname NetworkManager[789]: <info>  [1707284925.456] device (wlp3s0): state change: activated -> disconnected

Next Chapter

In Chapter 10, you'll learn Shell Scripting - writing bash scripts to automate tasks, using variables, loops, conditionals, and functions to make your life easier.

Chapter 10: Shell Scripting

Learning Objectives

By the end of this chapter, you will be able to:

  • Write and execute bash scripts
  • Use variables and user input
  • Implement conditionals and comparisons
  • Use loops for repetitive tasks
  • Create functions for reusable code
  • Automate real-world system administration tasks

Prerequisites

  • Completed Chapter 9: Processes & Services
  • Comfortable with basic commands and pipes
  • Understanding of file permissions

What is Shell Scripting?

A shell script is a text file containing a sequence of commands that the shell can execute. Think of it as:

  • Automation - Run multiple commands with one command
  • Programming - Use variables, loops, and conditionals
  • Productivity - Save time on repetitive tasks
#!/bin/bash
# This is a simple script
echo "Hello, World!"
date
whoami

Why Write Scripts?

TaskManual WayScript Way
Backup filesCopy each folder./backup.sh
Deploy appType 10 commands./deploy.sh
Clean logsDelete each file./cleanup.sh
Monitor systemRun top, ps, free./health.sh

Creating Your First Script

Script Structure

Every bash script starts with a shebang:

#!/bin/bash
# ^ This tells Linux to run this file with bash

# Comments start with #
echo "This is my first script!"

Step 1: Create the Script

# Create the file
nano myscript.sh

# Or use echo
cat > myscript.sh << 'EOF'
#!/bin/bash
echo "Hello, World!"
echo "Today is $(date)"
echo "Current user: $USER"
EOF

Step 2: Make It Executable

chmod +x myscript.sh

# Verify permissions
ls -l myscript.sh
-rwxr-xr-x 1 user user ... myscript.sh
# ^^^
# The 'x' means executable

Step 3: Run the Script

# Execute directly
./myscript.sh

# Or with bash explicitly
bash myscript.sh

# Or with sh
sh myscript.sh

Variables

Defining Variables

#!/bin/bash

# No spaces around '='
name="Alice"
age=25
greeting="Hello, $name!"

echo $name           # Alice
echo $greeting       # Hello, Alice!
echo "I am $age"     # I am 25

Variable Rules

# Correct
NAME="value"
my_var="value"
_var2="value"

# WRONG - spaces around =
name = "Alice"    # Error

# WRONG - using $ on left side
$name="Bob"       # Error

Using Variables

#!/bin/bash

file="report.txt"
count=5

echo "File: $file"           # File: report.txt
echo "Count: $count"         # Count: 5

# Braces for clarity
echo "${file}_backup"        # report.txt_backup

Environment Variables

These are predefined variables available in every script:

#!/bin/bash

echo "Current user: $USER"
echo "Home directory: $HOME"
echo "Current directory: $PWD"
echo "Shell: $SHELL"
echo "Hostname: $HOSTNAME"
echo "Path: $PATH"
VariableDescription
$USERCurrent username
$HOMEUser's home directory
$PWDPresent working directory
$SHELLDefault shell path
$HOSTNAMESystem hostname
$PATHCommand search paths

Command Substitution

Use the output of a command as a variable value.

Syntax: $(command) or `command`

#!/bin/bash

# Get today's date
today=$(date +%Y-%m-%d)
echo "Today is: $today"

# Count files
file_count=$(ls | wc -l)
echo "Files in current directory: $file_count"

# Get disk usage
disk_usage=$(df -h / | tail -1 | awk '{print $5}')
echo "Disk usage: $disk_usage"

Old Syntax (Backticks)

# Still works, but prefer $(...)
today=`date +%Y-%m-%d`

User Input

Reading Input with read

#!/bin/bash

echo "What is your name?"
read name
echo "Hello, $name!"

Prompt and Input on One Line

read -p "Enter your name: " name
echo "Hello, $name!"

Silent Input (for passwords)

read -s -p "Enter password: " password
echo  # newline
echo "Password received (not shown)"

Reading Multiple Values

read -p "Enter name age: " name age
echo "Name: $name, Age: $age"

Conditionals

if Statements

#!/bin/bash

count=10

if [ $count -eq 10 ]; then
    echo "Count is 10"
fi

if-else

#!/bin/bash

age=18

if [ $age -ge 18 ]; then
    echo "You are an adult"
else
    echo "You are a minor"
fi

if-elif-else

#!/bin/bash

score=75

if [ $score -ge 90 ]; then
    echo "Grade: A"
elif [ $score -ge 80 ]; then
    echo "Grade: B"
elif [ $score -ge 70 ]; then
    echo "Grade: C"
else
    echo "Grade: F"
fi

Comparison Operators

File TestMeaning
-f fileFile exists
-d dirDirectory exists
-e fileExists (file or dir)
-r fileFile is readable
-w fileFile is writable
-x fileFile is executable
String ComparisonMeaning
"$s1" = "$s2"Strings equal
"$s1" != "$s2"Strings not equal
-z "$s"String is empty
-n "$s"String is not empty
Number ComparisonMeaning
$n1 -eq $n2Equal
$n1 -ne $n2Not equal
$n1 -gt $n2Greater than
$n1 -ge $n2Greater or equal
$n1 -lt $n2Less than
$n1 -le $n2Less or equal

Examples

#!/bin/bash

# File check
if [ -f "/etc/passwd" ]; then
    echo "Password file exists"
fi

# String comparison
name="Alice"
if [ "$name" = "Alice" ]; then
    echo "Welcome, Alice!"
fi

# Number comparison
age=20
if [ $age -ge 18 ]; then
    echo "You can vote"
fi

# Combining conditions
if [ -f "data.txt" ] && [ -r "data.txt" ]; then
    echo "File exists and is readable"
fi

Logical Operators

-a    # AND (within single test)
-o    # OR (within single test)
!     # NOT
&&    # AND (between commands)
||    # OR (between commands)

# Example
if [ $age -ge 18 ] && [ $age -le 65 ]; then
    echo "Working age"
fi

Loops

for Loop

#!/bin/bash

# Loop through numbers
for i in 1 2 3 4 5; do
    echo "Number: $i"
done

# Loop through range
for i in {1..10}; do
    echo "Count: $i"
done

# Loop through files
for file in *.txt; do
    echo "Processing: $file"
done

while Loop

#!/bin/bash

count=1
while [ $count -le 5 ]; do
    echo "Count: $count"
    count=$((count + 1))
done

until Loop

#!/bin/bash

count=1
until [ $count -gt 5 ]; do
    echo "Count: $count"
    count=$((count + 1))
done

Breaking Out of Loops

#!/bin/bash

# break - exit loop entirely
for i in {1..10}; do
    if [ $i -eq 5 ]; then
        break
    fi
    echo $i
done
# Output: 1 2 3 4

# continue - skip to next iteration
for i in {1..5}; do
    if [ $i -eq 3 ]; then
        continue
    fi
    echo $i
done
# Output: 1 2 4 5

Functions

Defining Functions

#!/bin/bash

# Define a function
greet() {
    echo "Hello, $1!"
}

# Call the function
greet "Alice"
greet "Bob"

Functions with Multiple Arguments

#!/bin/bash

greet() {
    name=$1
    age=$2
    echo "Hello, $name! You are $age years old."
}

greet "Alice" 25
greet "Bob" 30

Returning Values

#!/bin/bash

add() {
    result=$(($1 + $2))
    echo $result
}

sum=$(add 5 3)
echo "Sum is: $sum"

Functions with Return Code

#!/bin/bash

check_file() {
    if [ -f "$1" ]; then
        return 0    # Success
    else
        return 1    # Failure
    fi
}

if check_file "data.txt"; then
    echo "File exists"
else
    echo "File not found"
fi

Arithmetic

Arithmetic Expansion

#!/bin/bash

a=10
b=5

# Addition
echo $(($a + $b))      # 15

# Subtraction
echo $(($a - $b))      # 5

# Multiplication
echo $(($a * $b))      # 50

# Division
echo $(($a / $b))      # 2

# Modulo
echo $(($a % $b))      # 0

# Exponentiation
echo $(($a ** 2))      # 100

Shorthand Arithmetic

#!/bin/bash

count=5

count=$((count + 1))   # Increment
echo $count            # 6

((count++))            # Post-increment
echo $count            # 7

((count+=5))           # Add 5
echo $count            # 12

Special Variables

Positional Parameters

#!/bin/bash

# $0    - Script name
# $1    - First argument
# $2    - Second argument
# $@    - All arguments
# $#    - Number of arguments

echo "Script name: $0"
echo "First arg: $1"
echo "Second arg: $2"
echo "All args: $@"
echo "Number of args: $#"

Exit Status

#!/bin/bash

# $? - Exit status of last command

ls /nonexistent
if [ $? -ne 0 ]; then
    echo "Command failed"
fi

Practical Scripts

Example 1: Backup Script

#!/bin/bash
# backup.sh - Backup important files

SOURCE="$HOME/Documents"
DESTINATION="$HOME/backup"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="$DESTINATION/backup_$DATE"

# Create backup directory
mkdir -p "$BACKUP_DIR"

# Copy files
echo "Backing up $SOURCE to $BACKUP_DIR"
cp -r "$SOURCE"/* "$BACKUP_DIR/"

# Compress
tar -czf "$BACKUP_DIR.tar.gz" "$BACKUP_DIR"
rm -rf "$BACKUP_DIR"

echo "Backup complete: $BACKUP_DIR.tar.gz"

Example 2: System Health Check

#!/bin/bash
# health.sh - Check system health

echo "=== System Health Check ==="
echo "Date: $(date)"
echo ""

# Disk usage
echo "--- Disk Usage ---"
df -h | grep -E "Filesystem|/$"

# Memory
echo ""
echo "--- Memory Usage ---"
free -h

# CPU
echo ""
echo "--- CPU Usage ---"
top -bn1 | grep "Cpu(s)"

# Top processes
echo ""
echo "--- Top 5 Processes by CPU ---"
ps aux | sort -rk 3 | head -n 6

echo ""
echo "=== Health Check Complete ==="

Example 3: Log Cleaner

#!/bin/bash
# clean_logs.sh - Remove old log files

LOG_DIR="/var/log"
DAYS=30

echo "Finding logs older than $DAYS days..."

# Find and remove old logs (dry run)
find "$LOG_DIR" -name "*.log" -type f -mtime +$DAYS

read -p "Delete these files? (y/n) " confirm

if [ "$confirm" = "y" ]; then
    find "$LOG_DIR" -name "*.log" -type f -mtime +$DAYS -delete
    echo "Old logs deleted."
else
    echo "Operation cancelled."
fi

Example 4: Batch File Renamer

#!/bin/bash
# rename.sh - Rename files in batch

# Add prefix to all files
PREFIX="backup_"

for file in *.txt; do
    if [ -f "$file" ]; then
        mv "$file" "${PREFIX}${file}"
        echo "Renamed: $file -> ${PREFIX}${file}"
    fi
done

Example 5: User Creation Script

#!/bin/bash
# create_user.sh - Create a new user

if [ $(id -u) -ne 0 ]; then
    echo "This script must be run as root"
    exit 1
fi

read -p "Enter username: " username

# Check if user exists
if id "$username" &>/dev/null; then
    echo "User $username already exists"
    exit 1
fi

# Create user
useradd -m "$username"

# Set password
passwd "$username"

echo "User $username created successfully"

Best Practices

1. Use Shebang

#!/bin/bash
# Always specify the interpreter

2. Use Comments

#!/bin/bash
# This script backs up important files
# Author: Your Name
# Date: 2025-02-07

# Create backup directory
mkdir -p backup

3. Quote Variables

# Good
echo "$name"
rm "$file"

# Bad (breaks with spaces)
echo $name
rm $file

4. Check for Errors

#!/bin/bash
set -e    # Exit on error

# Or check specific commands
if ! cp source.txt dest.txt; then
    echo "Copy failed"
    exit 1
fi

5. Use Meaningful Names

# Good
backup_source="$HOME/Documents"
backup_destination="$HOME/backup"

# Bad
a="$HOME/Documents"
b="$HOME/backup"

Debugging Scripts

Enable Debugging

#!/bin/bash
set -x    # Print each command before executing
# or run: bash -x script.sh

set -v    # Print script lines as they are read

Syntax Check

bash -n script.sh    # Check syntax without running

Common Errors

ErrorCauseFix
command not foundTypo or command not installedCheck spelling
permission deniedNot executableRun chmod +x script.sh
syntax errorMissing quote, bracket, etc.Check matching pairs
bad substitutionWrong variable syntaxUse ${var} not {var}

Summary

In this chapter, you learned:

  • Script Basics: Shebang, creating, and executing scripts
  • Variables: Defining and using variables, environment variables
  • Input/Output: echo, read, command substitution
  • Conditionals: if, else, elif, comparison operators
  • Loops: for, while, until, break, continue
  • Functions: Creating reusable code blocks
  • Arithmetic: Math operations and calculations
  • Best Practices: Comments, error checking, quoting

Chapter Quiz

Test your understanding of shell scripting:


Exercises

Exercise 1: Hello Script

  1. Create a script that asks for your name
  2. Greets you with the current date
  3. Tells you how many files are in the current directory

Exercise 2: Number Guessing Game

  1. Generate a random number: random=$((1 + RANDOM % 100))
  2. Ask the user to guess
  3. Tell them if it's too high or too low
  4. Continue until they guess correctly

Exercise 3: File Backup

  1. Create a script that backs up all .txt files
  2. Create a backup/ directory if it doesn't exist
  3. Copy all .txt files with a timestamp prefix
  4. Print a summary of files copied

Exercise 4: System Monitor

  1. Create a script that checks disk usage
  2. If disk usage is above 80%, print a warning
  3. Check if a specific service is running
  4. Print a summary report

Exercise 5: Calculator

  1. Create a script that takes two numbers
  2. Ask for the operation (+, -, *, /)
  3. Perform the calculation
  4. Display the result

Expected Output

Exercise 1 Solution

#!/bin/bash
# hello.sh

echo "What is your name?"
read name

echo ""
echo "Hello, $name!"
echo "Today is $(date)"
echo "Files in this directory: $(ls | wc -l)"
$ chmod +x hello.sh
$ ./hello.sh
What is your name?
Alice

Hello, Alice!
Today is Wed Feb  7 12:34:56 CET 2025
Files in this directory: 15

Exercise 2 Solution

#!/bin/bash
# guess.sh

random=$((1 + RANDOM % 100))
guess=0
attempts=0

echo "Guess the number (1-100)"

while [ $guess -ne $random ]; do
    read -p "Enter your guess: " guess
    ((attempts++))

    if [ $guess -lt $random ]; then
        echo "Too low!"
    elif [ $guess -gt $random ]; then
        echo "Too high!"
    fi
done

echo "Correct! You guessed it in $attempts attempts."

Exercise 3 Solution

#!/bin/bash
# backup.sh

BACKUP_DIR="backup"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
COUNT=0

# Create backup directory
mkdir -p "$BACKUP_DIR"

# Copy all .txt files
for file in *.txt; do
    if [ -f "$file" ]; then
        cp "$file" "$BACKUP_DIR/${TIMESTAMP}_$file"
        ((COUNT++))
        echo "Backed up: $file"
    fi
done

echo ""
echo "Backup complete! Copied $COUNT files to $BACKUP_DIR/"

Exercise 4 Solution

#!/bin/bash
# monitor.sh

# Check disk usage
DISK_USAGE=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
echo "Disk usage: $DISK_USAGE%"

if [ $DISK_USAGE -gt 80 ]; then
    echo "WARNING: Disk usage is above 80%!"
fi

# Check if SSH is running
echo ""
if systemctl is-active --quiet ssh; then
    echo "SSH service: Running"
else
    echo "SSH service: Not running"
fi

# Memory check
echo ""
echo "Memory usage:"
free -h | grep "Mem:"

Exercise 5 Solution

#!/bin/bash
# calculator.sh

read -p "Enter first number: " num1
read -p "Enter second number: " num2
read -p "Enter operation (+, -, *, /): " op

case $op in
    +)
        result=$(($num1 + $num2))
        ;;
    -)
        result=$(($num1 - $num2))
        ;;
    \*)
        result=$(($num1 * $num2))
        ;;
    /)
        if [ $num2 -eq 0 ]; then
            echo "Error: Division by zero"
            exit 1
        fi
        result=$(($num1 / $num2))
        ;;
    *)
        echo "Invalid operation"
        exit 1
        ;;
esac

echo ""
echo "$num1 $op $num2 = $result"

Next Chapter

In Chapter 11, you'll learn Networking Basics - understanding IP addresses, checking connectivity, using SSH for remote access, and troubleshooting network issues.

Chapter 11: Networking Basics

Learning Objectives

By the end of this chapter, you will be able to:

  • Understand IP addresses, ports, and network interfaces
  • Check network connectivity and diagnose issues
  • Use SSH for secure remote access
  • Transfer files securely over the network
  • Troubleshoot common network problems
  • Understand basic network security concepts

Prerequisites

  • Completed Chapter 10: Shell Scripting
  • Basic understanding of the file system
  • Comfortable with terminal commands

Understanding Networking

What is a Network?

A network connects computers together so they can share resources. Your Linux machine is likely connected to:

┌─────────────────────────────────────────────────────────┐
│                      The Internet                        │
│                        (Cloud)                           │
│                           ↑                              │
│                    ┌──────┴──────┐                       │
│                    │   Router    │                       │
│                    │  192.168.1.1│                       │
│                    └──────┬──────┘                       │
│                           │                              │
┌───────────────────────────┼──────────────────────────────┐
│ Local Network (LAN)        │   192.168.1.0/24            │
│                            │                             │
│  ┌─────────────────────┐   │   ┌─────────────────────┐   │
│  │ Your Linux Machine  │───┼───│    Other Device     │   │
│  │   192.168.1.100     │       │   192.168.1.101     │   │
│  └─────────────────────┘       └─────────────────────┘   │
└─────────────────────────────────────────────────────────┘

Key Networking Concepts

ConceptDescriptionExample
IP AddressUnique identifier for a device192.168.1.100
Subnet MaskDefines network range255.255.255.0
GatewayRoute to other networks192.168.1.1 (router)
DNSTranslates names to IPsgoogle.com → 142.250.x.x
PortSpecific service on a machine22 for SSH, 80 for web
MAC AddressHardware network ID00:1A:2B:3C:4D:5E

Viewing Network Configuration

ip Command (Modern)

The ip command is the modern replacement for ifconfig.

# Show all network interfaces
ip addr

# Show IPv4 addresses only
ip -4 addr

# Show specific interface
ip addr show eth0
ip a show wlan0    # short form

# Show routing table
ip route

# Show neighbors (ARP table)
ip neigh

Understanding ip addr Output

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536
    inet 127.0.0.1/8 scope host lo
           ^^^^^^^^^^^^  Local loopback (your own machine)

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel
    inet 192.168.1.100/24 brd 192.168.1.255 scope global dynamic eth0
           ^^^^^^^^^^^^^^^^  Your IP on local network
           ^^^^             Subnet mask (24 = 255.255.255.0)

Interface States

StateMeaning
UPInterface is active
DOWNInterface is disabled
UNKNOWNConnection state unknown

Network Interface Types

InterfaceDescription
loLoopback (localhost)
eth0Ethernet (wired)
wlan0Wireless (WiFi)
enp0s3Modern naming for ethernet
wlp3s0Modern naming for wireless

Checking Connectivity

ping - Test Reachability

ping sends ICMP packets to test if a host is reachable.

# Ping Google (Ctrl+C to stop)
ping google.com

# Ping specific number of times
ping -c 4 8.8.8.8

# Ping with interval
ping -i 2 192.168.1.1
$ ping -c 4 google.com
PING google.com (142.250.185.46) 56(84) bytes of data.
64 bytes from lga25s72-in-f14.1e100.net (142.250.185.46): icmp_seq=1 ttl=115 time=12.3 ms
64 bytes from lga25s72-in-f14.1e100.net (142.250.185.46): icmp_seq=2 ttl=115 time=11.8 ms
64 bytes from lga25s72-in-f14.1e100.net (142.250.185.46): icmp_seq=3 ttl=115 time=13.1 ms
64 bytes from lga25s72-in-f14.1e100.net (142.250.185.46): icmp_seq=4 ttl=115 time=12.9 ms

--- google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss
round-trip min/avg/max/stddev = 11.8/12.5/13.1/0.5 ms

traceroute - Trace Packet Path

Shows the route packets take to reach a destination.

# Trace route to Google
traceroute google.com

# Or use tracepath (simpler)
tracepath google.com
$ traceroute google.com
traceroute to google.com (142.250.185.46), 30 hops max
 1  _gateway (192.168.1.1)  0.123 ms
 2  10.0.0.1  5.432 ms
 3  72.14.215.85  12.123 ms
 ...

nslookup / dig - DNS Queries

Query DNS servers to resolve domain names.

# Look up IP for domain
nslookup google.com

# More detailed query
dig google.com

# Query specific DNS record
dig mx gmail.com    # Mail servers
$ nslookup google.com
Server:         127.0.0.53
Address:        127.0.0.53#53

Name:   google.com
Address: 142.250.185.46

Testing Web Connectivity

# Test HTTP request
curl -I https://google.com

# Test with details
curl -v https://example.com

# Test port connectivity
nc -zv google.com 80

SSH - Secure Remote Access

SSH (Secure Shell) lets you securely connect to remote machines.

Basic SSH Connection

ssh user@hostname

# Examples
ssh alice@192.168.1.100
ssh user@example.com
ssh root@server.example.com

First Connection - Host Key Verification

$ ssh alice@192.168.1.100
The authenticity of host '192.168.1.100' can't be established.
ED25519 key fingerprint is SHA256:abc123...
This key is not known by any other names.
Are you sure you want to continue (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.1.100' (ED25519) to the list of known hosts.
alice@192.168.1.100's password:

SSH Key-Based Authentication

Generate SSH keys to avoid typing passwords.

# Generate new key pair
ssh-keygen -t ed25519    # Modern, secure
# or
ssh-keygen -t rsa -b 4096

# Copy public key to remote server
ssh-copy-id alice@192.168.1.100

# Now login without password
ssh alice@192.168.1.100

SSH Keys Explained

┌─────────────────────────────────────────────────────────┐
│                  Your Machine                           │
│  ┌────────────────┐    ┌────────────────┐             │
│  │ Private Key    │    │ Public Key     │             │
│  │ (id_ed25519)   │    │ (id_ed25519.pub)│             │
│  │ KEEP SECRET!   │    │ Share freely   │             │
│  └────────────────┘    └────────────────┘             │
│                                │                        │
│                                │ Copy this to server    │
│                                ▼                        │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│                  Remote Server                          │
│           ┌────────────────┐                            │
│           │ Public Key     │                            │
│           │ In ~/.ssh/     │                            │
│           │ authorized_keys│                            │
│           └────────────────┘                            │
└─────────────────────────────────────────────────────────┘

Useful SSH Options

# Specify port (default is 22)
ssh -p 2222 user@host

# Connect with specific key
ssh -i ~/.ssh/mykey.pem user@host

# Verbose mode (debugging)
ssh -v user@host

# Execute command remotely
ssh user@host "ls -la /tmp"

# Local port forwarding
ssh -L 8080:localhost:80 user@host    # Access remote port 80 locally

SSH Config File

Simplify connections with ~/.ssh/config:

# Create config file
nano ~/.ssh/config
Host myserver
    HostName 192.168.1.100
    User alice
    Port 22
    IdentityFile ~/.ssh/id_ed25519

Host webserver
    HostName example.com
    User admin
    Port 2222
# Now just use:
ssh myserver
ssh webserver

File Transfer Over SSH

scp - Secure Copy

Copy files between machines over SSH.

# Copy file to remote
scp localfile.txt user@host:/remote/path/

# Copy file from remote
scp user@host:/remote/file.txt /local/path/

# Copy directory (recursive)
scp -r localdir/ user@host:/remote/path/

# Copy with preserved attributes
scp -p file.txt user@host:/path/

# Specify port
scp -P 2222 file.txt user@host:/path/

rsync - Sync Files

More efficient for large transfers and can sync directories.

# Sync local to remote
rsync -avz localdir/ user@host:remotedir/

# Sync remote to local
rsync -avz user@host:remotedir/ localdir/

# Dry run (preview)
rsync -avz --dry-run localdir/ user@host:remotedir/

# Delete files in destination that don't exist in source
rsync -avz --delete localdir/ user@host:remotedir/

# Show progress
rsync -avz --progress localdir/ user@host:remotedir/

rsync Options

OptionMeaning
-aArchive mode (preserves permissions, times)
-vVerbose (show what's happening)
-zCompress during transfer
--progressShow progress
--deleteDelete extra files in destination
--dry-runPreview without copying

Network Troubleshooting

Diagnostic Workflow

1. Check interface is up
   ip addr

2. Check local connectivity
   ping 127.0.0.1

3. Check gateway
   ping 192.168.1.1

4. Check DNS
   ping 8.8.8.8

5. Check name resolution
   ping google.com

6. Trace path
   traceroute google.com

Common Issues and Solutions

ProblemDiagnosisSolution
No connectionip addr shows DOWNBring interface up
Can't reach internetGateway unreachableCheck router connection
Can't browse sitesDNS failureUse 8.8.8.8 as DNS
Port blockednc -zv failsCheck firewall
Slow connectionHigh ping timesCheck bandwidth usage

Managing Network Interfaces

# Bring interface down
sudo ip link set eth0 down

# Bring interface up
sudo ip link set eth0 up

# Assign IP address
sudo ip addr add 192.168.1.100/24 dev eth0

# Remove IP address
sudo ip addr del 192.168.1.100/24 dev eth0

Checking Open Ports

# List listening ports
ss -tulpn

# Show specific port
ss -tulpn | grep :22

# Alternative with netstat
netstat -tulpn
$ ss -tulpn
Netid State  Recv-Q Send-Q Local Address:Port    Peer Address:Port
tcp   LISTEN 0      128          0.0.0.0:22          0.0.0.0:*
tcp   LISTEN 0      5            127.0.0.1:631       0.0.0.0:*

Firewall Basics

# Fedora (firewalld)
sudo firewall-cmd --list-all              # Show rules
sudo firewall-cmd --add-port=8080/tcp    # Open port
sudo firewall-cmd --reload                # Apply changes

# Debian (ufw)
sudo ufw status                           # Show status
sudo ufw allow 22                         # Allow SSH
sudo ufw enable                           # Enable firewall

Network Configuration Files

Understanding /etc/hosts

Local hostname to IP mapping (before DNS).

$ cat /etc/hosts
127.0.0.1   localhost
127.0.1.1   mycomputer
192.168.1.100  server.local

# You can add custom entries

resolv.conf - DNS Configuration

$ cat /etc/resolv.conf
nameserver 127.0.0.53
options edns0 trust-ad
search .

Practical Examples

Example 1: Remote Server Management

# Connect to server
ssh admin@server.example.com

# Once connected, run commands remotely
sudo systemctl status nginx
sudo tail -f /var/log/nginx/access.log

Example 2: Deploy Website

# Build locally
npm run build

# Copy to server
scp -r dist/* user@server:/var/www/html/

# Restart service on server
ssh user@server "sudo systemctl restart nginx"

Example 3: Backup Remote Files

# Sync remote files to local backup
rsync -avz --delete user@server:/var/www/ ~/backups/server/

Example 4: Network Diagnosis Script

#!/bin/bash
# network_check.sh

echo "=== Network Diagnosis ==="

# Check interfaces
echo "--- Network Interfaces ---"
ip addr | grep -E "^[0-9]|inet "

# Check gateway
echo ""
echo "--- Gateway Ping ---"
ping -c 2 $(ip route | grep default | awk '{print $3}')

# Check DNS
echo ""
echo "--- DNS Check ---"
nslookup google.com > /dev/null 2>&1
if [ $? -eq 0 ]; then
    echo "DNS: OK"
else
    echo "DNS: FAILED"
fi

# Check internet
echo ""
echo "--- Internet Connectivity ---"
ping -c 2 8.8.8.8 > /dev/null 2>&1
if [ $? -eq 0 ]; then
    echo "Internet: OK"
else
    echo "Internet: FAILED"
fi

Example 5: Port Forwarding for Remote Access

# Forward local port 8080 to remote server's localhost:80
ssh -L 8080:localhost:80 user@server

# Now access in browser: http://localhost:8080
# (Routes to server's port 80)

Security Best Practices

SSH Security

  1. Use key-based auth, not passwords

    ssh-keygen -t ed25519
    ssh-copy-id user@host
    
  2. Disable password authentication (server-side)

    # Edit /etc/ssh/sshd_config
    PasswordAuthentication no
    
  3. Change default SSH port

    # Edit /etc/ssh/sshd_config
    Port 2222
    
  4. Use firewall to limit access

    sudo ufw allow from 192.168.1.0/24 to any port 22
    

General Network Security

PracticeWhy
Use SSH, not TelnetEncrypted vs plain text
Keep system updatedSecurity patches
Use firewallBlock unwanted access
Monitor logsDetect intrusion
Use VPN for public WiFiEncrypt traffic

Summary

In this chapter, you learned:

  • Network Concepts: IP addresses, ports, gateways, DNS
  • Viewing Configuration: ip addr, ip route
  • Testing Connectivity: ping, traceroute, nslookup
  • SSH Remote Access: ssh, key-based authentication
  • File Transfer: scp, rsync
  • Troubleshooting: Diagnostic workflow, common issues
  • Security: SSH best practices, firewall basics

Chapter Quiz

Test your understanding of networking basics:


Exercises

Exercise 1: Network Information

  1. Check your IP address
  2. Check your default gateway
  3. Check your DNS servers
  4. List all network interfaces

Exercise 2: Connectivity Testing

  1. Ping your local gateway
  2. Ping 8.8.8.8 (Google DNS)
  3. Ping google.com
  4. Trace route to google.com

Exercise 3: SSH Connection

  1. Generate SSH key pair (if you don't have one)
  2. Copy your public key to a remote machine (or VM)
  3. Connect using SSH
  4. Run a remote command via SSH

Exercise 4: File Transfer

  1. Create a test file
  2. Copy it to remote machine using scp
  3. Sync a directory using rsync
  4. Verify the transfer

Exercise 5: Troubleshooting

  1. Create a network diagnostic script
  2. Check interface status
  3. Test gateway connectivity
  4. Test DNS resolution
  5. Test internet connectivity

Expected Output

Exercise 1 Solution

$ ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP>
    inet 192.168.1.100/24 brd 192.168.1.255 scope global dynamic eth0

$ ip route | grep default
default via 192.168.1.1 dev eth0

$ cat /etc/resolv.conf
nameserver 127.0.0.53

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP>
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP>
3: wlan0: <BROADCAST,MULTICAST>

Exercise 2 Solution

$ ping -c 2 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=0.123 ms

$ ping -c 2 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=115 time=12.3 ms

$ ping -c 2 google.com
PING google.com (142.250.185.46) 56(84) bytes of data.
64 bytes from lga25s72-in-f14.1e100.net: icmp_seq=1 ttl=115 time=12.5 ms

$ traceroute -n google.com
traceroute to google.com (142.250.185.46), 30 hops max
 1  192.168.1.1  0.123 ms
 2  10.0.0.1  5.432 ms

Exercise 3 Solution

$ ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Created directory '/home/user/.ssh'.

$ ssh-copy-id alice@192.168.1.100
alice@192.168.1.100's password:
Number of key(s) added: 1

$ ssh alice@192.168.1.100
Welcome to Ubuntu 22.04 LTS
alice@host:~$

$ ssh alice@192.168.1.100 "uname -a"
Linux host 5.15.0-76-generic #83-Ubuntu SMP x86_64 GNU/Linux

Exercise 4 Solution

$ echo "Test content" > testfile.txt

$ scp testfile.txt alice@192.168.1.100:/home/alice/
testfile.txt                     100%   13     0.1KB/s   00:00

$ mkdir files && cp testfile.txt files/
$ rsync -avz files/ alice@192.168.1.100:/home/alice/backups/
sending incremental file list
./
testfile.txt

$ ssh alice@192.168.1.100 "cat /home/alice/testfile.txt"
Test content

Exercise 5 Solution

#!/bin/bash
# diag.sh

echo "=== Network Diagnostic ==="

# Interfaces
echo -e "\n[1] Interface Status:"
ip addr show | grep -E "^[0-9]|inet " | head -20

# Gateway
echo -e "\n[2] Gateway Ping:"
GATEWAY=$(ip route | grep default | awk '{print $3}')
if ping -c 1 -W 2 $GATEWAY > /dev/null 2>&1; then
    echo "Gateway ($GATEWAY): OK"
else
    echo "Gateway ($GATEWAY): FAILED"
fi

# Internet
echo -e "\n[3] Internet Check:"
if ping -c 1 -W 2 8.8.8.8 > /dev/null 2>&1; then
    echo "Internet (8.8.8.8): OK"
else
    echo "Internet (8.8.8.8): FAILED"
fi

# DNS
echo -e "\n[4] DNS Resolution:"
if nslookup google.com > /dev/null 2>&1; then
    echo "DNS: OK"
else
    echo "DNS: FAILED"
fi

# Open ports
echo -e "\n[5] Listening Ports:"
ss -tulpn | grep LISTEN | head -5
$ chmod +x diag.sh
$ ./diag.sh
=== Network Diagnostic ===

[1] Interface Status:
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP>
    inet 192.168.1.100/24

[2] Gateway Ping:
Gateway (192.168.1.1): OK

[3] Internet Check:
Internet (8.8.8.8): OK

[4] DNS Resolution:
DNS: OK

[5] Listening Ports:
tcp   LISTEN 0  128  0.0.0.0:22
tcp   LISTEN 0  5    127.0.0.1:631

Next Chapter

In Chapter 12, you'll learn Git Version Control - tracking changes to your code, collaborating with others, and managing project history.

Chapter 12: Git Version Control

Learning Objectives

By the end of this chapter, you will be able to:

  • Understand what version control is and why it's essential
  • Initialize a Git repository
  • Track changes with staging and committing
  • View commit history and understand the log
  • Create and switch between branches
  • Merge changes from different branches
  • Work with remote repositories (push/pull)

Prerequisites

  • Completed Part III: System Administration
  • Basic familiarity with the command line
  • Internet connection (for remote repositories)

What Is Version Control?

The Problem Version Control Solves

Have you ever worked on a project and had files like these?

my-script.py
my-script-v2.py
my-script-v2-final.py
my-script-v2-final-REALLY-final.py
my-script-v2-final-working-backup.py

Version control solves this problem by tracking every change to your files in a structured, efficient way.

Why Version Control Matters

ScenarioWithout Version ControlWith Version Control
Made a mistakeRestore from backup (hope you have one)git revert - instant undo
Want to experimentCopy the entire foldergit branch - zero-cost experiments
CollaborateEmail files back and forthgit push/pull - seamless sharing
See historyRemember when you changed whatgit log - complete audit trail
Compare versionsOpen files side-by-side manuallygit diff - automatic highlighting

What Is Git?

Git is a distributed version control system created by Linus Torvalds in 2005 to manage Linux kernel development. It's now the industry standard for version control.

Key characteristics:

  • Distributed: Every developer has a complete copy of the project history
  • Fast: Operations are local, no server needed for most work
  • Branching: Creating parallel lines of development is cheap and easy
  • Open Source: Free to use and modify

Git Concepts

The Three States

Git has three main areas where files can exist:

graph LR
    A[Working Directory] -->|git add| B[Staging Area]
    B -->|git commit| C[Local Repository]
    C -->|git push| D[Remote Repository]

    style A fill:#e1f5ff
    style B fill:#fff4e1
    style C fill:#e8f5e9
    style D fill:#f3e5f5
  1. Working Directory: The actual files on your disk
  2. Staging Area (Index): Files prepared for the next commit
  3. Repository (Local): Where Git stores committed history

The Commit Graph

Git stores history as a directed acyclic graph:

graph TD
    A[Initial Commit] --> B[Feature A]
    A --> C[Feature B]
    B --> D[Merge A+B]
    C --> D

    style A fill:#c8e6c9
    style B fill:#bbdefb
    style C fill:#bbdefb
    style D fill:#ffecb3

Each commit points to its parent(s), creating a complete tree of changes.


Getting Started with Git

Installation

Git is likely already installed on your Linux system. Check with:

$ git --version
git version 2.43.0

If not installed:

Fedora:

sudo dnf install git

Debian:

sudo apt install git

Initial Configuration

Before using Git, set your identity (required for commits):

git config --global user.name "Your Name"
git config --global user.email "you@example.com"

Set a default branch name (modern standard):

git config --global init.defaultBranch main

Set your preferred editor:

git config --global core.editor nano

View your configuration:

git config --list

Basic Git Workflow

1. Initialize a Repository

Create a new project or navigate to an existing directory:

mkdir my-project
cd my-project
git init

Output:

Initialized empty Git repository in /home/user/my-project/.git/

This creates a .git directory (hidden) where Git stores all its data.

2. Create and Stage Files

Create a file:

echo "# My Project" > README.md
echo 'print("Hello, Git!")' > main.py

Check what Git sees:

git status

Output:

On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	README.md
	main.py

Stage the files (add to staging area):

git add README.md
git add main.py

Or stage all files:

git add .

3. Make Your First Commit

Create a commit with a descriptive message:

git commit -m "Initial commit: Add README and main script"

Output:

[main (root-commit)] Initial commit: Add README and main script
 2 files changed, 2 insertions(+)
 create mode 100644 README.md
 create mode 100644 main.py

Commit Message Best Practices:

  • Start with a verb: "Add", "Fix", "Remove", "Update"
  • Keep the first line under 50 characters
  • Use imperative mood ("Add feature" not "Added feature")
  • Add a blank line, then detailed explanation if needed

Viewing History

Commit Log

View commit history:

git log

Output:

commit a1b2c3d4e5f6... (HEAD -> main)
Author: Your Name <you@example.com>
Date:   Mon Feb 5 10:30:00 2026 +0000

    Initial commit: Add README and main script

More readable formats:

# One line per commit
git log --oneline

# Decorated graph
git log --graph --oneline --all

# With date stats
git log --stat

Viewing Changes

See what changed but not staged:

git diff

See staged changes:

git diff --staged

Compare two commits:

git diff HEAD~1 HEAD

View a specific file at a specific commit:

git show COMMIT_ID:path/to/file

Branching and Merging

Why Branch?

Branching lets you:

  • Work on features independently
  • Experiment without breaking the main code
  • Maintain multiple versions simultaneously
  • Review code before merging

Creating Branches

List existing branches:

git branch

Create a new branch:

git branch feature-login

Switch to a branch:

git checkout feature-login

Or create and switch in one command:

git checkout -b feature-login

Working on Branches

Make changes on your new branch:

echo "# Login Feature" >> README.md
git add README.md
git commit -m "Add login feature documentation"

Switch back to main:

git checkout main

Merging Branches

Merge a branch into the current one:

git merge feature-login

Output (fast-forward merge):

Updating a1b2c3d..d4e5f6g
Fast-forward
 README.md | 1 +
 1 file changed, 1 insertion(+)

Delete the merged branch:

git branch -d feature-login

Merge Conflicts

When two branches change the same lines differently, Git creates a conflict:

<<<<<<< HEAD
print("Version A")
=======
print("Version B")
>>>>>>> feature-login

To resolve:

  1. Edit the file to choose which version to keep (or combine both)
  2. git add <resolved-file>
  3. git commit

Working with Remotes

Remote Repositories

Remotes are versions of your project hosted elsewhere (GitHub, GitLab, Bitbucket).

Adding a Remote

After creating a repository on GitHub/GitLab:

git remote add origin https://github.com/username/repo.git

View remotes:

git remote -v

Pushing Changes

Send your local commits to the remote:

git push -u origin main

The -u flag sets the upstream relationship for future pushes.

Pulling Changes

Get changes from the remote:

git pull origin main

This is equivalent to:

git fetch origin main    # Download changes
git merge origin/main    # Merge into current branch

Cloning a Repository

Copy an existing repository:

git clone https://github.com/username/repo.git
cd repo

This automatically sets up the remote as origin.


Common Git Commands Reference

CommandDescription
git initInitialize a new repository
git clone <url>Clone an existing repository
git statusShow working tree status
git add <file>Stage changes
git commit -m "message"Commit staged changes
git logShow commit history
git diffShow unstaged changes
git diff --stagedShow staged changes
git branchList/create branches
git checkout <branch>Switch branches
git checkout -b <branch>Create and switch branch
git merge <branch>Merge branch into current
git remote -vList remotes
git pushPush to remote
git pullPull from remote
git stashTemporarily save changes
git stash popRestore stashed changes

Git Workflow Diagram

sequenceDiagram
    participant Dev as Developer
    participant WD as Working Dir
    participant SA as Staging Area
    participant LR as Local Repo
    participant RR as Remote Repo

    Dev->>WD: Edit files
    Dev->>SA: git add
    Dev->>LR: git commit
    Dev->>RR: git push

    Note over Dev,RR: New feature workflow

    Dev->>WD: git checkout -b feature
    Dev->>WD: Make changes
    Dev->>SA: git add
    Dev->>LR: git commit
    Dev->>LR: git checkout main
    Dev->>LR: git merge feature
    Dev->>RR: git push

Summary

Key Takeaways:

  • Git is distributed version control created by Linus Torvalds
  • Three states: Working directory → Staging area → Repository
  • Branching allows parallel development without conflicts
  • Commits are snapshots of your project at points in time
  • Remotes enable collaboration with other developers
  • Good commit messages make history understandable

Git Philosophy:

  • Commit often, commit small
  • Write meaningful commit messages
  • Use branches for features
  • Pull before you push
  • Review changes before committing

Next Up: You'll learn about Docker containers and how they complement version control for reproducible development environments!


Chapter Quiz

Test your understanding of Git version control:


Exercises

Exercise 1: Your First Repository

Create a new Git repository and make some commits:

  1. Create a directory called git-practice
  2. Initialize it as a Git repository
  3. Create a file called notes.md with some content
  4. Stage and commit the file with a descriptive message
  5. Add more content to notes.md and create a second commit
  6. View your commit history with git log

Expected Output:

$ git log --oneline
a1b2c3d Add more notes
7f6e5d4 Initial commit: Add notes.md

Exercise 2: Branching Practice

Practice creating and merging branches:

  1. Create a new branch called experiment
  2. On the experiment branch, create a file called test.txt
  3. Commit the file
  4. Switch back to main
  5. Merge the experiment branch into main
  6. Delete the experiment branch
  7. Verify the file exists on main

Expected Output:

$ git branch
* main
$ ls
notes.md  test.txt

Exercise 3: Undo Mistakes

Practice Git's undo capabilities:

  1. Create a file with content, commit it
  2. Modify the file and commit again
  3. Use git reset --soft HEAD~1 to undo the last commit (keeps changes staged)
  4. Use git reset HEAD~1 to unstage changes
  5. Use git checkout -- <file> to discard working directory changes

Challenge: When would you use git reset --hard? What's the danger?

Exercise 4: Merge Conflict Resolution

Practice resolving conflicts:

  1. Create a branch called conflict-test
  2. On main, create conflict.md with Version A and commit
  3. Switch to conflict-test, modify the same line to Version B and commit
  4. Switch back to main and change the same line to Version C and commit
  5. Merge conflict-test into main
  6. Resolve the conflict by choosing or combining versions
  7. Complete the merge

Exercise 5: Remote Collaboration (Optional)

If you have a GitHub/GitLab account:

  1. Create a new repository on the platform
  2. Add it as a remote to your local repository
  3. Push your local commits
  4. Make a change on the web interface
  5. Pull the changes to your local machine
  6. Verify the synchronization

Expected Output

After completing these exercises, you should have:

  1. A working Git repository with multiple commits
  2. Branching experience — you've created, merged, and deleted branches
  3. Undo skills — you know how to revert changes at different stages
  4. Conflict resolution — you've handled and resolved merge conflicts
  5. (Optional) Remote workflow — you've pushed and pulled from a remote

Further Reading


Common Pitfalls

Don't Commit Generated Files

Create a .gitignore file to exclude:

  • Binaries and executables
  • Dependencies (node_modules/, venv/)
  • Build artifacts (*.o, *.pyc)
  • IDE settings (.idea/, .vscode/)
  • System files (.DS_Store, Thumbs.db)

Example .gitignore:

# Python
__pycache__/
*.py[cod]
venv/

# Node
node_modules/
package-lock.json

# IDE
.vscode/
.idea/

Don't Commit Sensitive Data

Never commit:

  • API keys
  • Passwords
  • Private keys
  • Personal data

Use environment variables instead:

# Don't do this:
# api_key = "sk-1234567890abcdef"

# Do this:
import os
api_key = os.getenv("API_KEY")

Don't Ignore Merge Conflicts

Unresolved conflicts break builds. Always resolve before pushing.


Discussion Questions

  1. Why is Git's distributed model better than centralized version control systems like SVN?
  2. When would you use git rebase instead of git merge?
  3. What's the difference between git pull and git fetch?
  4. How does Git handle binary files (images, PDFs) differently from text files?
  5. Why do many projects have a CONTRIBUTING.md file with Git workflow guidelines?

Chapter 13: Docker Containers

Learning Objectives

By the end of this chapter, you will be able to:

  • Understand what containers are and why they're useful
  • Install and configure Docker on Linux
  • Run Docker containers from existing images
  • Manage container lifecycle (start, stop, remove)
  • Build custom Docker images with Dockerfiles
  • Use Docker Compose for multi-container applications
  • Understand container networking and volumes

Prerequisites

  • Completed Part III: System Administration
  • Basic understanding of Linux processes and permissions
  • Familiarity with the command line

What Are Containers?

The Problem Containers Solve

Have you ever heard: "It works on my machine!"

This classic developer complaint occurs because:

  • Different operating systems (Windows vs. Linux vs. macOS)
  • Different library versions
  • Different environment configurations
  • Missing dependencies

Containers solve this by packaging an application with everything it needs to run.

Containers vs. Virtual Machines

graph TB
    subgraph VM["Virtual Machine"]
        VM1[Hypervisor]
        VM2[Guest OS]
        VM3[Bin/Libs]
        VM4[App A]
    end

    subgraph Container["Container"]
        C1[Docker Engine]
        C2[Bin/Libs + App A]
        C3[Bin/Libs + App B]
        C4[Bin/Libs + App C]
    end

    OS[Host OS] --> VM1
    OS --> C1

    style VM2 fill:#ffcdd2
    style C1 fill:#c8e6c9
AspectVirtual MachinesContainers
Operating SystemFull guest OS per VMShare host OS kernel
Startup TimeMinutesSeconds/milliseconds
Resource UsageGBs of RAMMBs of RAM
Disk SpaceMultiple GBsTens to hundreds of MBs
IsolationCompleteProcess-level
PortabilityLimitedHighly portable

Why Use Containers?

  1. Consistency: "It works on my machine" becomes "It works everywhere"
  2. Isolation: Applications don't interfere with each other
  3. Portability: Run the same container on laptop, server, or cloud
  4. Scalability: Easily spawn multiple instances
  5. Efficiency: Lightweight compared to VMs
  6. DevOps: Bridge development and operations

Installing Docker

Fedora

Docker is available in Fedora's repositories:

# Install Docker
sudo dnf install docker

# Start and enable Docker service
sudo systemctl enable --now docker

# Verify installation
docker --version
# Docker version 26.0.0, build ...`

docker run hello-world

Debian

On Debian-based systems:

# Update package index
sudo apt update

# Install Docker
sudo apt install docker.io

# Start and enable Docker service
sudo systemctl enable --now docker

# Verify installation
docker --version

Managing Docker as a Non-Root User

By default, Docker requires sudo. To run Docker without sudo:

# Add your user to the docker group
sudo usermod -aG docker $USER

# Log out and back in for changes to take effect
# Or use:
newgrp docker

Security Note: Adding users to the docker group gives them root-equivalent privileges. Only do this for trusted users.

Starting the Docker Service

# Start Docker
sudo systemctl start docker

# Enable Docker to start on boot
sudo systemctl enable docker

# Check Docker status
sudo systemctl status docker

Docker Architecture

graph LR
    A[Client] -->|CLI| B[Docker Daemon]
    B --> C[Images]
    B --> D[Containers]
    B --> E[Registry]

    E -->|pull/push| B

    style A fill:#e1f5ff
    style B fill:#fff4e1
    style C fill:#c8e6c9
    style D fill:#f8bbd0
    style E fill:#e1bee7
  • Docker Client: Command-line interface (docker command)
  • Docker Daemon: Background service that manages containers
  • Images: Read-only templates for containers
  • Containers: Running instances of images
  • Registry: Repository of images (Docker Hub is the default)

Running Your First Container

Hello World

The classic first container:

docker run hello-world

Output:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
...
Hello from Docker!
This message shows that your installation appears to be working correctly.

What happened:

  1. Docker checked for the hello-world image locally
  2. Not found locally, so it pulled from Docker Hub
  3. Docker created a container from the image
  4. The container ran, printed the message, and exited

Running an Interactive Container

Run an Ubuntu container with an interactive shell:

docker run -it ubuntu bash

Flags:

  • -i — Keep STDIN open even if not attached
  • -t — Allocate a pseudo-TTY

You're now inside a container! Try:

# Inside the container
ls /
cat /etc/os-release
echo "Hello from container!" > /tmp/test.txt
cat /tmp/test.txt

# Exit the container
exit

Running in Detached Mode

Run containers in the background:

# Run nginx in the background
docker run -d --name my-webserver nginx

Flags:

  • -d — Detached mode (run in background)
  • --name — Give the container a name

View running containers:

docker ps

View all containers (including stopped):

docker ps -a

Essential Docker Commands

Image Management

CommandDescription
docker pull <image>Download an image from registry
docker imagesList locally stored images
docker rmi <image>Delete an image
docker image pruneRemove unused images

Container Management

CommandDescription
docker run <image>Create and start a container
docker psList running containers
docker ps -aList all containers
docker stop <container>Gracefully stop a container
docker kill <container>Forcefully stop a container
docker start <container>Start a stopped container
docker restart <container>Restart a container
docker rm <container>Delete a container
docker container pruneRemove stopped containers

Information and Debugging

CommandDescription
docker logs <container>Show container logs
docker inspect <container>View container details
docker exec -it <container> <cmd>Run command in container
docker statsLive resource usage

Working with Containers

Example: Web Server

Run an nginx web server:

# Run nginx in the background
docker run -d --name my-nginx -p 8080:80 nginx

Flags:

  • -p 8080:80 — Map host port 8080 to container port 80

Test it:

curl http://localhost:8080

Or open in your browser: http://localhost:8080

View logs:

docker logs my-nginx

Stop the container:

docker stop my-nginx

Remove the container:

docker rm my-nginx

Example: Database

Run a PostgreSQL database:

# Run PostgreSQL with environment variables
docker run -d \
  --name my-postgres \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 5432:5432 \
  postgres

Flags:

  • -e — Set environment variables

Connect to the database:

docker exec -it my-postgres psql -U postgres

Building Custom Images

What Is a Dockerfile?

A Dockerfile is a recipe for building a Docker image. It contains instructions for:

  • Base image to use
  • Files to copy
  • Commands to run
  • Ports to expose
  • Environment variables

Creating Your First Dockerfile

Create a simple web application:

mkdir my-docker-app
cd my-docker-app

Create app.py:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return """
    <html>
        <head><title>My Docker App</title></head>
        <body>
            <h1>Hello from Docker!</h1>
            <p>This app is running in a container.</p>
        </body>
    </html>
    """

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Create requirements.txt:

flask==3.0.0

Create Dockerfile:

# Use Python 3.11 as base image
FROM python:3.11-slim

# Set working directory
WORKDIR /app

# Copy requirements and install
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY app.py .

# Expose port
EXPOSE 5000

# Run the application
CMD ["python", "app.py"]

Building the Image

# Build the image
docker build -t my-python-app .

Flags:

  • -t my-python-app — Tag the image with a name
  • . — Build context (current directory)

Output:

[+] Building 45.2s (10/10) FINISHED
...
=> => naming to docker.io/library/my-python-app

Running Your Custom Image

# Run the container
docker run -d --name my-app -p 5000:5000 my-python-app

Test it:

curl http://localhost:5000

Dockerfile Instructions Reference

InstructionDescriptionExample
FROMBase imageFROM ubuntu:22.04
WORKDIRSet working directoryWORKDIR /app
COPYCopy files from hostCOPY . /app
ADDCopy files (supports URLs/tar)ADD app.tar.gz /app
RUNExecute command during buildRUN apt-get update
CMDDefault command to runCMD ["nginx"]
ENTRYPOINTContainer's main commandENTRYPOINT ["python"]
ENVSet environment variableENV APP_ENV=prod
EXPOSEDocument exposed portEXPOSE 80
VOLUMECreate mount pointVOLUME /data

Docker Compose

What Is Docker Compose?

Docker Compose is a tool for defining and running multi-container applications. Instead of running multiple docker run commands, you define services in a YAML file.

Installing Docker Compose

Docker Compose is typically included with Docker. Check:

docker compose version
# Docker Compose version v2.24.0

Creating a docker-compose.yml

Create a complete web application with a database:

mkdir my-compose-app
cd my-compose-app

Create docker-compose.yml:

version: '3.8'

services:
  web:
    build: .
    ports:
      - "5000:5000"
    depends_on:
      - db
    environment:
      - DATABASE_URL=postgresql://postgres:password@db:5432/mydb
    volumes:
      - ./app:/app

  db:
    image: postgres:15
    environment:
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=mydb
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:

Create a simple app/Dockerfile:

FROM python:3.11-slim
WORKDIR /app
RUN pip install flask psycopg2-binary
COPY app.py .
CMD ["python", "app.py"]

Create app/app.py:

from flask import Flask
import os

app = Flask(__name__)

@app.route('/')
def hello():
    db_url = os.getenv('DATABASE_URL', 'not set')
    return f"<h1>Web Server Running</h1><p>DB: {db_url}</p>"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Running Docker Compose

# Start all services
docker compose up -d

# View running services
docker compose ps

# View logs
docker compose logs

# View logs for a specific service
docker compose logs web

# Stop all services
docker compose down

# Stop and remove volumes
docker compose down -v

Container Networking

Understanding Container Networks

By default, containers are isolated from each other. Docker provides networking options:

Network TypeDescription
bridgeDefault, containers on same host communicate
hostContainer uses host's network (no isolation)
noneNo networking
overlayMulti-host networking (Swarm, Kubernetes)

Creating a Network

# Create a custom network
docker network create my-network

# Run containers on the network
docker run -d --name app1 --network my-network nginx
docker run -d --name app2 --network my-network nginx

# Containers can communicate by name
docker exec app1 curl app2

Listing Networks

docker network ls

Persistent Data with Volumes

What Are Volumes?

Volumes persist data after containers are removed. Containers are ephemeral—volumes are not.

Creating and Using Volumes

# Create a volume
docker volume create my-data

# Use a volume
docker run -d --name my-app -v my-data:/data nginx

# Inspect volume
docker volume inspect my-data

# List volumes
docker volume ls

# Remove volume (when no containers use it)
docker volume rm my-data

Bind Mounts

Mount a host directory into a container:

# Mount current directory to /app in container
docker run -v $(pwd):/app -w /app python:3.11 python script.py

Docker Workflow Diagram

graph LR
    A[Write Dockerfile] --> B[docker build]
    B --> C[Image Created]
    C --> D[docker push]
    D --> E[Registry]

    E --> F[docker pull]
    F --> G[Local Image]
    G --> H[docker run]
    H --> I[Container Running]

    style A fill:#e1f5ff
    style C fill:#c8e6c9
    style E fill:#e1bee7
    style I fill:#ffecb3

Summary

Key Takeaways:

  • Containers are lightweight, portable application environments
  • Docker is the leading container platform
  • Images are read-only templates, containers are running instances
  • Dockerfiles define how to build images
  • Docker Compose manages multi-container applications
  • Volumes provide persistent data storage
  • Networks enable container communication

Docker Philosophy:

  • One concern per container
  • Containers should be ephemeral
  • Use volumes for persistent data
  • Use compose for multi-container apps

Chapter Quiz

Test your understanding of Docker containers:


Exercises

Exercise 1: Run a Web Server

Run an nginx web server:

  1. Pull the nginx image
  2. Run nginx in detached mode on port 8080
  3. Verify it's running with curl
  4. View the container logs
  5. Stop and remove the container

Expected Output:

$ curl http://localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

Exercise 2: Build a Custom Image

Create a simple HTML server:

  1. Create a directory with an index.html file
  2. Write a Dockerfile that uses nginx and copies your HTML
  3. Build the image with tag my-web
  4. Run the container on port 8081
  5. Verify your custom page loads

Exercise 3: Multi-Container App

Use Docker Compose to run a web app with database:

  1. Create a docker-compose.yml with:
    • A Python/Flask web service
    • A PostgreSQL database
  2. Configure networking between services
  3. Start with docker compose up
  4. Verify the services communicate
  5. Clean up with docker compose down

Exercise 4: Persistent Data

Practice using volumes:

  1. Create a named volume
  2. Run a container that writes to the volume
  3. Remove the container
  4. Run a new container with the same volume
  5. Verify the data persists

Exercise 5: Image Inspection

Explore Docker internals:

  1. Pull an image (e.g., python:3.11)
  2. Use docker inspect to view image details
  3. Identify the layers, environment variables, and exposed ports
  4. Run the container and explore the filesystem
  5. Compare two different image tags

Expected Output

After completing these exercises, you should have:

  1. Running containers — you've started, stopped, and removed containers
  2. Custom images — you've built images from Dockerfiles
  3. Multi-container apps — you've used Docker Compose
  4. Persistent data — you've used volumes for data persistence
  5. Docker knowledge — you understand images, containers, and the Docker ecosystem

Further Reading


Common Pitfalls

Don't Run as Root Inside Containers

By default, containers run as root. Use the USER instruction:

RUN adduser -u 5678 --disabled-password --gecos "" appuser
USER appuser

Don't Put Secrets in Images

Use environment variables or secrets management:

# Don't do this:
# ENV API_KEY=sk-1234567890

# Do this:
ENV API_KEY_FILE=/run/secrets/api_key

Don't Create Large Images

Use multi-stage builds and minimal base images:

# Build stage
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o app

# Runtime stage (much smaller)
FROM alpine:latest
COPY --from=builder /app/app /app
CMD ["/app"]

Don't Forget Resource Limits

Prevent containers from consuming all resources:

docker run -m 512m --cpus=1.0 nginx

Discussion Questions

  1. How do containers differ from virtual machines at the kernel level?
  2. When would you use a bind mount instead of a volume?
  3. Why might you choose Alpine Linux as a base image?
  4. How does Docker handle security isolation between containers?
  5. What are the trade-offs between using Docker and bare metal deployment?

Capstone: Personal Linux Server

Overview

This capstone project brings together everything you've learned in this course. You will set up a personal Linux server that demonstrates your newfound skills in system administration, automation, and development tools.

Project Goals

By completing this capstone, you will:

  • Set up and configure a web server (nginx)
  • Create and serve a custom webpage
  • Write an automated backup script with cron
  • Track your configuration with Git
  • (Optional) Run services in Docker containers
  • Document your entire setup

Prerequisites

  • Completion of all 13 chapters
  • Linux system installed and configured
  • Root/sudo access
  • Basic text editor skills (nano or vim)

Part 1: Web Server Setup

Task 1.1: Install nginx

Install and configure nginx as your web server:

Fedora:

sudo dnf install nginx
sudo systemctl enable --now nginx
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

Debian:

sudo apt update
sudo apt install nginx
# nginx starts automatically on Debian

Task 1.2: Verify Installation

Check that nginx is running:

# Check service status
sudo systemctl status nginx

# Check if port 80 is listening
sudo ss -tlnp | grep :80

# Test locally
curl http://localhost

Open your browser and navigate to: http://localhost

You should see the default nginx welcome page.

Task 1.3: Understand the nginx Directory Structure

graph TD
    A[nginx Configuration] --> B[/etc/nginx/]
    B --> C[nginx.conf - Main config]
    B --> D[conf.d/ - Additional configs]
    B --> E[sites-available/ - Site configs]
    B --> F[sites-enabled/ - Enabled sites]

    G[Web Content] --> H[/var/www/html/]

    I[Logs] --> J[/var/log/nginx/]
    J --> K[access.log]
    J --> L[error.log]

    style B fill:#e1f5ff
    style H fill:#c8e6c9
    style J fill:#fff4e1

Part 2: Custom Webpage

Task 2.1: Create Your Custom Page

Replace the default nginx page with your own:

# Backup the original
sudo cp /var/www/html/index.html /var/www/html/index.html.backup

# Create your custom page
sudo nano /var/www/html/index.html

Paste this content:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Linux Server</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            max-width: 800px;
            margin: 50px auto;
            padding: 20px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
        }
        .container {
            background: rgba(0,0,0,0.3);
            padding: 30px;
            border-radius: 10px;
        }
        h1 { color: #fff; }
        .info { background: rgba(255,255,255,0.1); padding: 15px; margin: 10px 0; border-radius: 5px; }
        .footer { margin-top: 30px; font-size: 0.9em; opacity: 0.8; }
    </style>
</head>
<body>
    <div class="container">
        <h1>Welcome to My Linux Server!</h1>
        <p>This server is proudly running on Linux.</p>

        <div class="info">
            <h3>System Information</h3>
            <ul>
                <li>Operating System: Linux</li>
                <li>Web Server: nginx</li>
                <li>Course: Linux for Everyone</li>
                <li>Status: <strong style="color: #4ade80;">Online</strong></li>
            </ul>
        </div>

        <div class="info">
            <h3>Skills Demonstrated</h3>
            <ul>
                <li>System Administration</li>
                <li>Web Server Configuration</li>
                <li>File Permissions</li>
                <li>Service Management</li>
            </ul>
        </div>

        <div class="footer">
            <p>Powered by Linux | Configured by [Your Name]</p>
        </div>
    </div>
</body>
</html>

Task 2.2: Verify Custom Page

Refresh your browser at http://localhost. You should now see your custom page.


Part 3: Automated Backup Script

Task 3.1: Create Backup Directory

mkdir -p ~/backups

Task 3.2: Write the Backup Script

Create a comprehensive backup script:

nano ~/backup-script.sh

Add the following content:

#!/bin/bash

#==============================================
# Linux Server Backup Script
# Course: Linux for Everyone - Capstone Project
#==============================================

# Configuration
BACKUP_DIR="$HOME/backups"
WEB_DIR="/var/www/html"
NGINX_CONF="/etc/nginx"
DATE=$(date +"%Y%m%d_%H%M%S")
BACKUP_NAME="server_backup_$DATE"
LOG_FILE="$BACKUP_DIR/backup.log"

# Create backup directory if it doesn't exist
mkdir -p "$BACKUP_DIR"

# Log function
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

# Start backup
log "========== Starting Backup: $BACKUP_NAME =========="

# Create backup archive
log "Creating backup archive..."
tar -czf "$BACKUP_DIR/$BACKUP_NAME.tar.gz" \
    -C / \
    "$WEB_DIR" \
    "$NGINX_CONF" \
    2>/dev/null

if [ $? -eq 0 ]; then
    log "Backup created successfully: $BACKUP_NAME.tar.gz"

    # Get file size
    SIZE=$(du -h "$BACKUP_DIR/$BACKUP_NAME.tar.gz" | cut -f1)
    log "Backup size: $SIZE"
else
    log "ERROR: Backup creation failed!"
    exit 1
fi

# Remove backups older than 30 days
log "Cleaning old backups (older than 30 days)..."
find "$BACKUP_DIR" -name "server_backup_*.tar.gz" -mtime +30 -delete
REMOVED=$(find "$BACKUP_DIR" -name "server_backup_*.tar.gz" | wc -l)
log "Backups remaining: $REMOVED"

# Display disk usage
log "Current disk usage of backup directory:"
du -sh "$BACKUP_DIR" | tail -1 | tee -a "$LOG_FILE"

log "========== Backup Complete =========="
echo ""

# List recent backups
echo "Recent backups:"
ls -lht "$BACKUP_DIR"/server_backup_*.tar.gz 2>/dev/null | head -5

Task 3.3: Make Script Executable and Test

# Make executable
chmod +x ~/backup-script.sh

# Run manually to test
~/backup-script.sh

# Verify the backup was created
ls -lh ~/backups/

Task 3.4: Schedule with Cron

Automate the backup to run daily:

# Edit crontab
crontab -e

# Add this line to run daily at 2 AM
0 2 * * * /home/$(whoami)/backup-script.sh

Verify your crontab:

crontab -l

Part 4: Git Version Control

Task 4.1: Initialize Git Repository

Track your server configuration with Git:

# Create project directory
mkdir -p ~/server-project
cd ~/server-project

# Initialize Git repository
git init

# Create project structure
mkdir -p config docs scripts

# Copy configuration files (readable copies)
cp /etc/nginx/nginx.conf config/ 2>/dev/null || sudo cat /etc/nginx/nginx.conf > config/nginx.conf
sudo cat /var/www/html/index.html > config/index.html

# Copy your backup script
cp ~/backup-script.sh scripts/

# Create README
cat > README.md << 'EOF'
# Personal Linux Server

## Overview
This is my capstone project for the Linux for Everyone course.

## System Specifications
- OS: Linux (Fedora/Debian)
- Web Server: nginx
- Automation: cron + bash script
- Version Control: Git

## Setup Instructions

### 1. Install nginx
**Fedora:**
```bash
sudo dnf install nginx
sudo systemctl enable --now nginx

Debian:

sudo apt install nginx

2. Deploy Web Content

sudo cp config/index.html /var/www/html/index.html
sudo cp config/nginx.conf /etc/nginx/nginx.conf
sudo systemctl reload nginx

3. Setup Backups

chmod +x scripts/backup-script.sh
sudo cp scripts/backup-script.sh /usr/local/bin/
crontab -e  # Add: 0 2 * * * /usr/local/bin/backup-script.sh

Maintenance

  • Check logs: sudo journalctl -u nginx -f
  • View backups: ls -lh ~/backups/
  • Test web server: curl http://localhost

Author

[Your Name] - Linux for Everyone Course EOF


### Task 4.2: Make Initial Commit

```bash
# Add all files
git add .

# Make initial commit
git commit -m "Initial commit: Server configuration and backup script"

# Verify
git log --oneline

Part 5: (Optional) Docker Challenge

If you want to showcase your Docker skills, run the web server in a container:

Task 5.1: Stop nginx Service

sudo systemctl stop nginx
sudo systemctl disable nginx

Task 5.2: Run nginx in Docker

# Create data directory
mkdir -p ~/docker-nginx/html

# Copy your custom page
cp ~/server-project/config/index.html ~/docker-nginx/html/

# Run nginx container
docker run -d \
  --name my-nginx \
  -p 80:80 \
  -v ~/docker-nginx/html:/usr/share/nginx/html:ro \
  nginx:alpine

# Verify
curl http://localhost
docker logs my-nginx

Task 5.3: Enable Container on Boot

# Create systemd service for docker container
sudo nano /etc/systemd/system/docker-nginx.service

Add this content:

[Unit]
Description=Docker nginx container
Requires=docker.service
After=docker.service

[Service]
Restart=always
ExecStart=/usr/bin/docker start -a my-nginx
ExecStop=/usr/bin/docker stop -t 2 my-nginx

[Install]
WantedBy=multi-user.target

Enable the service:

sudo systemctl daemon-reload
sudo systemctl enable docker-nginx
sudo systemctl start docker-nginx

Verification Checklist

Before presenting your capstone, verify each component:

Web Server

# [ ] nginx is running
sudo systemctl status nginx

# [ ] Website is accessible
curl -I http://localhost

# [ ] Custom page displays correctly
curl http://localhost | grep "My Linux Server"

Backup System

# [ ] Backup script exists and is executable
ls -l ~/backup-script.sh

# [ ] Backup directory exists
ls -ld ~/backups

# [ ] Recent backup exists
ls -lht ~/backups/ | head -2

# [ ] Cron job is scheduled
crontab -l | grep backup-script

Git Repository

# [ ] Repository initialized
cd ~/server-project && git status

# [ ] All files tracked
git ls-files

# [ ] Commit history exists
git log --oneline

(Optional) Docker

# [ ] Docker container running
docker ps | grep nginx

# [ ] Container accessible
curl http://localhost

# [ ] Container restarts with system
systemctl status docker-nginx

Documentation

Task: Create System Documentation

Document your entire setup:

cat > ~/server-project/docs/SETUP.md << 'EOF'
# Server Setup Documentation

## System Information
- **Hostname:** $(hostname)
- **Distribution:** $(cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2)
- **Kernel:** $(uname -r)
- **IP Address:** $(hostname -I | awk '{print $1}')
- **Date Configured:** $(date)

## Web Server Configuration

### nginx Installation
- **Service:** nginx
- **Version:** $(nginx -v 2>&1 | cut -d'/' -f2)
- **Config Location:** /etc/nginx/nginx.conf
- **Web Root:** /var/www/html/
- **Port:** 80

### Management Commands
```bash
# Check status
sudo systemctl status nginx

# Restart service
sudo systemctl restart nginx

# View logs
sudo journalctl -u nginx -f

# Test configuration
sudo nginx -t

Backup Configuration

Backup Script

  • Location: ~/backup-script.sh
  • Backup Directory: ~/backups/
  • Schedule: Daily at 2:00 AM
  • Retention: 30 days

Manual Backup

~/backup-script.sh

Restore Procedure

# Extract backup
tar -xzf backups/server_backup_YYYYMMDD_HHMMSS.tar.gz -C /

# Restart services
sudo systemctl restart nginx

Git Repository

Repository Structure

~/server-project/
├── config/          # Configuration files
├── docs/           # Documentation
├── scripts/        # Automation scripts
└── README.md       # Project overview

Commands

# View status
cd ~/server-project && git status

# View log
git log --oneline

# Add changes
git add .
git commit -m "Update configuration"

Troubleshooting

Web Server Issues

  1. Check if nginx is running: sudo systemctl status nginx
  2. Check firewall: sudo firewall-cmd --list-all
  3. Check logs: sudo journalctl -u nginx -n 50
  4. Test config: sudo nginx -t

Backup Issues

  1. Check script permissions: ls -l ~/backup-script.sh
  2. Check cron: crontab -l
  3. Check backup log: cat ~/backups/backup.log

Docker Issues (if applicable)

  1. Check container: docker ps -a
  2. View logs: docker logs my-nginx
  3. Restart: docker restart my-nginx EOF

---

## Presentation Guide

When presenting your capstone, be prepared to demonstrate:

### Live Demonstration (5-10 minutes)

1. **Show your web server** — Open localhost in browser
2. **Demonstrate Git workflow** — Show commits and make a change
3. **Run backup manually** — Execute backup-script.sh and show results
4. **Show automation** — Display crontab and explain scheduled tasks
5. **(Optional) Docker** — Show containerized nginx running

### Explanation (3-5 minutes)

Explain your choices:

- **Why nginx?** (Lightweight, fast, industry standard)
- **Why cron?** (Built-in, reliable, simple)
- **Why Git?** (Version control, change tracking, rollback capability)
- **Why this structure?** (Separation of concerns, maintainability)

### Challenges Overcome (2-3 minutes)

Discuss:
- Permissions issues you solved
- Configuration challenges
- Debugging steps you took
- What you learned from each part

---

## Extension Ideas

Want to go further? Here are extension ideas:

### Easy Extensions

1. **Add SSL/TLS**
   ```bash
   sudo dnf install certbot python3-certbot-nginx  # Fedora
   sudo apt install certbot python3-certbot-nginx   # Debian
   sudo certbot --nginx -d yourdomain.com
  1. Add Monitoring

    # Install htop for monitoring
    sudo dnf install htop  # Fedora
    sudo apt install htop   # Debian
    
  2. Add Multiple Pages

    sudo cp /var/www/html/index.html /var/www/html/about.html
    # Edit about.html with different content
    

Medium Extensions

  1. Add Database Backend

    sudo dnf install postgresql postgresql-server  # Fedora
    sudo apt install postgresql postgresql-contrib  # Debian
    
  2. Add Logging Dashboard

    • Install GoAccess for log analysis
    • Create real-time web dashboard
  3. Add Firewall Rules

    # Fedora
    sudo firewall-cmd --permanent --add-service=http
    sudo firewall-cmd --permanent --add-service=https
    sudo firewall-cmd --reload
    

Advanced Extensions

  1. Containerize Everything

    • Run nginx in Docker
    • Run database in Docker
    • Use Docker Compose
  2. Add Monitoring Stack

    • Prometheus for metrics
    • Grafana for visualization
    • AlertManager for notifications
  3. Add CI/CD Pipeline

    • GitHub Actions for testing
    • Automated deployment
    • Configuration validation

Success Criteria

Your capstone is successful when you can:

  • Access your custom webpage in a browser
  • Explain how nginx serves files (directory structure, configuration)
  • Run the backup script manually and verify it creates backups
  • Show the cron job that automates daily backups
  • Demonstrate Git commands (status, log, add, commit)
  • Explain your design choices (why this structure, why these tools)
  • Troubleshoot basic issues (what to check when something fails)

Congratulations!

Completing this capstone demonstrates that you have the skills to:

  • Administer a Linux system (services, processes, logs)
  • Configure web servers (nginx, virtual hosts, firewalls)
  • Automate tasks with shell scripts (backup automation)
  • Use version control professionally (Git workflow)
  • Deploy containerized applications (Docker, optional)
  • Document technical systems (comprehensive documentation)

You Are Now Ready To:

  1. Use Linux confidently in your development career
  2. Manage Linux servers in production environments
  3. Automate repetitive system administration tasks
  4. Contribute to open-source projects
  5. Continue learning advanced Linux topics

What's Next?

  • Explore advanced topics (kernel tuning, security hardening)
  • Contribute to Linux documentation or open-source projects
  • Set up a home server or VPS
  • Learn about cloud platforms (AWS, GCP, Azure)
  • Study for Linux certifications (LFCS, RHCSA)

The Linux journey has just begun. Welcome to the community! 🐧


Resources

Cheat Sheet

Quick reference for the most essential Linux commands.

CommandDescription
pwdPrint working directory
lsList directory contents
cd <path>Change directory
cd ~Go to home directory
cd -Go to previous directory

File Operations

CommandDescription
touch <file>Create empty file
mkdir <dir>Create directory
cp <src> <dst>Copy file/directory
mv <src> <dst>Move/rename file
rm <file>Remove file
rm -r <dir>Remove directory

Viewing Files

CommandDescription
cat <file>Display file contents
less <file>View file with pagination
head <file>Show first 10 lines
tail <file>Show last 10 lines
tail -f <file>Follow file (live updates)
CommandDescription
grep <pattern> <file>Search in file
grep -r <pattern> <dir>Search recursively
find <dir> -name <pattern>Find files
locate <name>Quick file search

Permissions

CommandDescription
chmod <perms> <file>Change permissions
chown <user> <file>Change owner
sudo <command>Run as superuser
chmod +x <script>Make executable

Package Management

Fedora (DNF)

CommandDescription
dnf search <pkg>Search package
dnf install <pkg>Install package
dnf remove <pkg>Remove package
dnf updateUpdate packages

Debian (APT)

CommandDescription
apt search <pkg>Search package
apt install <pkg>Install package
apt remove <pkg>Remove package
apt update && apt upgradeUpdate system

Processes

CommandDescription
ps auxShow all processes
topInteractive process viewer
kill <pid>Terminate process
systemctl status <svc>Service status
journalctl -u <svc>Service logs

Networking

CommandDescription
ip addrShow IP addresses
ping <host>Test connectivity
ssh user@hostRemote login
scp <src> <dst>Secure copy

Git

CommandDescription
git initInitialize repo
git statusShow status
git add <file>Stage changes
git commit -m "msg"Commit
git logShow history

Docker

CommandDescription
docker pull <img>Pull image
docker run <img>Run container
docker psList containers
docker stop <id>Stop container

Keyboard Shortcuts

ShortcutDescription
TabAuto-complete
Ctrl+CCancel command
Ctrl+LClear screen
Ctrl+AStart of line
Ctrl+EEnd of line
Ctrl+UClear to start
Ctrl+KClear to end
Ctrl+RSearch history
↑/↓Browse history

Command Reference

Comprehensive reference for commands covered in this course.

File System Commands

pwd - Print Working Directory

Syntax: pwd [options]

Common Options:

  • -P - Physical path (resolve symlinks)

Example:

$ pwd
/home/student

ls - List Directory Contents

Syntax: ls [options] [directory]

Common Options:

  • -l - Long format (permissions, owner, size, date)
  • -a - Include hidden files (starting with .)
  • -h - Human-readable sizes
  • -R - Recursive listing
  • -t - Sort by modification time

Examples:

$ ls -lh
total 16K
drwxr-xr-x 2 student student 4.0K Feb  5 12:00 documents
-rw-r--r-- 1 student student  123 Feb  5 12:00 notes.txt

$ ls -la
total 32K
drwxr-xr-x 5 student student 4.0K Feb  5 12:00 .
drwxr-xr-x 3 root     root     4.0K Feb  4 00:00 ..
-rw-r--r-- 1 student student  123 Feb  5 12:00 notes.txt
drwx------ 2 student student 4.0K Feb  5 12:00 .ssh

cd - Change Directory

Syntax: cd [directory]

Special Paths:

  • ~ - Home directory
  • - - Previous directory
  • .. - Parent directory
  • . - Current directory

Examples:

$ cd /var/log
$ pwd
/var/log

$ cd ~
$ pwd
/home/student

$ cd -
/var/log

mkdir - Make Directory

Syntax: mkdir [options] <directory>

Common Options:

  • -p - Create parent directories as needed
  • -v - Verbose (print each directory)

Examples:

$ mkdir project
$ mkdir -p parent/child/grandchild
$ ls
parent  project

touch - Create Empty File / Update Timestamp

Syntax: touch [options] <file>

Common Options:

  • -c - Don't create if doesn't exist
  • -d - Use specified date/time

Examples:

$ touch newfile.txt
$ ls
newfile.txt

cp - Copy Files/Directories

Syntax: cp [options] <source> <destination>

Common Options:

  • -r - Recursive (for directories)
  • -i - Interactive (prompt before overwrite)
  • -v - Verbose
  • -p - Preserve attributes

Examples:

$ cp file.txt backup.txt
$ cp -r src/ dst/

mv - Move/Rename Files

Syntax: mv [options] <source> <destination>

Common Options:

  • -i - Interactive (prompt before overwrite)
  • -v - Verbose

Examples:

$ mv oldname.txt newname.txt
$ mv file.txt /tmp/

rm - Remove Files/Directories

Syntax: rm [options] <file>

Common Options:

  • -r - Recursive (for directories)
  • -i - Interactive (prompt before removal)
  • -f - Force (ignore nonexistent files)

Warning: rm is permanent. Use with caution!

Examples:

$ rm file.txt
$ rm -r directory/

Text Processing Commands

cat - Concatenate and Display Files

Syntax: cat [options] <file>

Common Options:

  • -n - Number lines
  • -b - Number non-blank lines

Example:

$ cat -n file.txt
     1	First line
     2	Second line

less - Page Through Files

Syntax: less <file>

Navigation:

  • Space / f - Forward one page
  • b - Backward one page
  • g - Go to first line
  • G - Go to last line
  • /pattern - Search forward
  • q - Quit

head / tail - Display File Start/End

Syntax:

head [options] <file>
tail [options] <file>

Common Options:

  • -n N - Show N lines (default 10)
  • -f - Follow file (tail only, live updates)

Examples:

$ head -n 5 file.txt    # First 5 lines
$ tail -f /var/log/syslog  # Follow log file

grep - Print Matching Lines

Syntax: grep [options] <pattern> <file>

Common Options:

  • -i - Case insensitive
  • -r - Recursive directory search
  • -v - Invert match (show non-matching)
  • -n - Show line numbers
  • -c - Count matches

Examples:

$ grep "error" log.txt
ERROR: Connection failed

$ grep -r "TODO" src/
src/main.c: // TODO: Fix this

$ grep -n "main" file.txt
42: int main() {

find - Search for Files

Syntax: find [path] [options]

Common Tests:

  • -name <pattern> - Name matches pattern
  • -type <type> - File type (f=file, d=directory)
  • -size <n> - File size
  • -mtime <n> - Modified n days ago

Examples:

$ find . -name "*.txt"
./notes.txt
./todo.txt

$ find /var/log -type f -name "*.log"
/var/log/system.log

$ find . -type f -mtime -7    # Modified in last 7 days

Permission Commands

chmod - Change Mode (Permissions)

Syntax: chmod [options] <mode> <file>

Symbolic Mode:

chmod u+x file    # Add execute for user
chmod g-w file    # Remove write for group
chmod o=r file    # Set read-only for others
chmod a+rw file   # Add read-write for all

Numeric Mode:

chmod 755 file    # rwxr-xr-x
chmod 644 file    # rw-r--r--
chmod 777 file    # rwxrwxrwx (not recommended)

Permission Values:

  • 4 = Read (r)
  • 2 = Write (w)
  • 1 = Execute (x)

chown - Change Owner

Syntax: chown [options] <user>[:<group>] <file>

Examples:

$ sudo chown john file.txt
$ sudo chown john:developers file.txt
$ sudo chown -R john:john directory/    # Recursive

sudo - Execute as Superuser

Syntax: sudo [options] <command>

Examples:

$ sudo apt install nginx
$ sudo systemctl restart ssh
$ sudo -u postgres psql    # Run as postgres user

Process Commands

ps - Process Status

Syntax: ps [options]

Common Options:

  • aux - Show all processes for all users
  • -u <user> - Show processes for user
  • -p <pid> - Show specific PID

Example:

$ ps aux
USER   PID  %CPU  %MEM  COMMAND
root     1   0.0   0.1  systemd
root   123   0.5   1.2  nginx

top / htop - Process Monitor

Interactive process viewers.

top keys:

  • q - Quit
  • k - Kill process
  • M - Sort by memory
  • P - Sort by CPU

kill - Send Signal to Process

Syntax: kill [options] <pid>

Common Signals:

  • SIGTERM (15) - Terminate gracefully
  • SIGKILL (9) - Force kill
  • SIGHUP (1) - Reload configuration

Examples:

$ kill 1234              # Graceful terminate
$ kill -9 1234           # Force kill
$ kill -HUP 1234         # Reload config

Package Management

Fedora (DNF)

CommandDescription
sudo dnf search <pkg>Search for package
sudo dnf install <pkg>Install package
sudo dnf remove <pkg>Remove package
sudo dnf updateUpdate all packages
sudo dnf upgradeUpgrade distribution
sudo dnf list installedList installed packages
sudo dnf info <pkg>Show package info
sudo dnf repolistList repositories

Debian (APT)

CommandDescription
sudo apt updateUpdate package lists
sudo apt upgradeUpgrade packages
sudo apt install <pkg>Install package
sudo apt remove <pkg>Remove package
sudo apt purge <pkg>Remove with config
sudo apt search <pkg>Search packages
sudo apt show <pkg>Show package info
sudo apt autoremoveRemove unused packages

Systemd Commands

systemctl - Control systemd System

Syntax: systemctl [command] [unit]

Commands:

sudo systemctl start <service>     # Start service
sudo systemctl stop <service>      # Stop service
sudo systemctl restart <service>   # Restart service
sudo systemctl status <service>    # Show status
sudo systemctl enable <service>    # Enable at boot
sudo systemctl disable <service>   # Disable at boot
sudo systemctl reload <service>    # Reload config
systemctl list-units --type=service    # List services
systemctl --failed                   # List failed units

Examples:

$ sudo systemctl start nginx
$ sudo systemctl enable nginx
$ systemctl status nginx

journalctl - Query systemd Journal

Syntax: journalctl [options]

Common Options:

  • -u <unit> - Show logs for specific unit
  • -f - Follow logs (live)
  • -b - Show logs from current boot
  • -r - Show in reverse order
  • --since "time" - Show logs since time
  • --until "time" - Show logs until time

Examples:

$ journalctl -u nginx          # Nginx logs
$ journalctl -u nginx -f       # Follow nginx logs
$ journalctl -b -p err         # Errors from current boot
$ journalctl --since "1 hour ago"

Networking Commands

ip - Network Configuration

Show IP addresses:

$ ip addr show
$ ip a      # Short form

Show routes:

$ ip route show

ping - Test Network Connectivity

Syntax: ping [options] <host>

Options:

  • -c <count> - Send count packets
  • -i <interval> - Interval between packets

Example:

$ ping -c 4 google.com
PING google.com (142.250.185.46): 56 data bytes
64 bytes from 142.250.185.46: icmp_seq=0 ttl=54 time=12.3 ms

ssh - Secure Shell

Syntax: ssh [options] [user@]host [command]

Common Options:

  • -p <port> - Specify port
  • -i <identity> - Use identity file
  • -v - Verbose

Examples:

$ ssh user@server.com
$ ssh -p 2222 user@server.com
$ ssh user@server.com 'ls -la'

SSH Key Management:

$ ssh-keygen -t ed25519      # Generate key
$ ssh-copy-id user@host      # Copy public key

scp - Secure Copy

Syntax: scp [options] <source> <destination>

Examples:

$ scp file.txt user@host:/path/    # Upload
$ scp user@host:/path/file.txt .   # Download
$ scp -r directory/ user@host:/path/  # Recursive

Git Commands

Basic Git Commands

CommandDescription
git initInitialize new repository
git clone <url>Clone existing repository
git statusShow working tree status
git add <file>Stage file for commit
git add .Stage all changes
git commit -m "msg"Commit staged changes
git logShow commit history
git log --onelineConcise commit history
git diffShow unstaged changes
git diff --stagedShow staged changes
git branchList branches
git branch <name>Create branch
git checkout <branch>Switch branch
git switch <branch>Switch branch (newer)
git merge <branch>Merge branch into current
git remote -vShow remotes
git pushPush to remote
git pullPull from remote
git stashStash changes
git stash popApply stashed changes

Docker Commands

Basic Docker Commands

CommandDescription
docker pull <image>Pull image from registry
docker run [options] <image>Run container
docker psList running containers
docker ps -aList all containers
docker stop <container>Stop container
docker start <container>Start stopped container
docker rm <container>Remove container
docker rmi <image>Remove image
docker imagesList images
docker exec -it <container> bashExecute in container
docker logs <container>Show container logs
docker inspect <object>Show low-level info

Common Run Options

docker run -d              # Detached (background)
docker run -it             # Interactive + TTY
docker run -p 80:80        # Port mapping host:container
docker run -v /host:/container  # Volume mount
docker run --name myname   # Name container
docker run --rm           # Remove on exit

Examples

# Run nginx in background
docker run -d -p 80:80 --name web nginx

# Run Ubuntu interactively
docker run -it ubuntu bash

# Run with volume mount
docker run -v $(pwd):/app -w /app python:3.11 python script.py

Troubleshooting Guide

Solutions to common problems you may encounter while learning Linux.

Permission Errors

"Permission denied"

Symptom:

$ touch /etc/test.txt
touch: cannot touch '/etc/test.txt': Permission denied

Solutions:

  1. Use sudo for system operations:

    sudo touch /etc/test.txt
    
  2. Check if you need to own the file:

    sudo chown $USER /etc/test.txt
    
  3. Check file permissions:

    ls -l /etc/test.txt
    

Command Not Found

"command not found"

Symptom:

$ git
git: command not found

Solutions:

  1. Check spelling:

    # Common typos
    cd /hme/user      # Wrong
    cd /home/user     # Correct
    
  2. Install missing package:

    Fedora:

    sudo dnf install git
    

    Debian:

    sudo apt install git
    
  3. Check PATH:

    echo $PATH
    which git
    

File System Issues

"No such file or directory"

Symptom:

$ cd documents
bash: cd: documents: No such file or directory

Solutions:

  1. List current directory contents:

    ls -la
    
  2. Check your location:

    pwd
    
  3. Use tab completion to avoid typos:

    cd doc<Tab>    # Completes to documents/
    
  4. Search for the file:

    find ~ -name "documents" -type d
    

"Directory not empty"

Symptom:

$ rm directory/
rm: cannot remove 'directory/': Is a directory

Solutions:

  1. Use recursive remove:

    rm -r directory/
    
  2. Remove with confirmation:

    rm -ri directory/
    

Package Management Issues

"Could not get lock /var/lib/dpkg/lock"

Symptom (Debian):

E: Could not get lock /var/lib/dpkg/lock-frontend

Solutions:

  1. Wait for another package manager to finish

  2. Check for running processes:

    ps aux | grep apt
    
  3. Remove lock (if stuck):

    sudo rm /var/lib/dpkg/lock-frontend
    sudo rm /var/lib/dpkg/lock
    

"Cannot update repository metadata"

Symptom (Fedora):

Error: Cannot update repository metadata

Solutions:

  1. Clean metadata cache:

    sudo dnf clean all
    sudo dnf makecache
    
  2. Check network connection:

    ping -c 3 fedoraproject.org
    
  3. Refresh repositories:

    sudo dnf refresh
    

Process Issues

Process won't stop

Symptom: Application freezes and won't close.

Solutions:

  1. Find the process ID:

    ps aux | grep application_name
    
  2. Try graceful termination:

    kill <PID>
    
  3. Force kill if needed:

    kill -9 <PID>
    
  4. Kill by name:

    pkill application_name
    killall application_name
    

Service won't start

Symptom:

$ sudo systemctl start nginx
Job for nginx.service failed.

Solutions:

  1. Check service status:

    systemctl status nginx
    
  2. View service logs:

    journalctl -u nginx -n 50
    
  3. Check configuration:

    sudo nginx -t    # Test nginx config
    
  4. Check for port conflicts:

    sudo ss -tulpn | grep :80
    

Network Issues

Cannot connect to WiFi

Solutions:

  1. Check network interface:

    ip link show
    
  2. Bring interface up:

    sudo ip link set wlan0 up
    
  3. Use NetworkManager (GUI or CLI):

    nmcli dev wifi list
    nmcli dev wifi connect "SSID" password "password"
    
  4. Restart network service:

    sudo systemctl restart NetworkManager
    

SSH connection refused

Symptom:

$ ssh user@host
ssh: connect to host port 22: Connection refused

Solutions:

  1. Check if SSH server is running:

    systemctl status sshd       # Fedora
    systemctl status ssh        # Debian
    
  2. Start SSH server:

    sudo systemctl start sshd
    sudo systemctl enable sshd
    
  3. Check firewall:

    sudo firewall-cmd --list-all    # Fedora
    sudo ufw status                 # Debian
    
  4. Check if port 22 is open:

    sudo ss -tulpn | grep :22
    

Disk Space Issues

"No space left on device"

Symptom:

$ touch file.txt
touch: cannot touch 'file.txt': No space left on device

Solutions:

  1. Check disk usage:

    df -h
    
  2. Find large files:

    du -h ~ | sort -hr | head -20
    
  3. Clean package cache:

    Fedora:

    sudo dnf clean all
    

    Debian:

    sudo apt clean
    sudo apt autoremove
    
  4. Empty trash:

    rm -rf ~/.local/share/Trash/*
    
  5. Clean old logs:

    sudo journalctl --vacuum-time=7d
    

Git Issues

"fatal: not a git repository"

Symptom:

$ git status
fatal: not a git repository (or any of the parent directories)

Solutions:

  1. Initialize repository:

    git init
    
  2. Clone existing repository:

    git clone <url>
    

Merge conflicts

Symptom:

$ git merge feature
Auto-merging file.txt
CONFLICT (content): Merge conflict in file.txt

Solutions:

  1. Edit the file and resolve conflicts manually

  2. Mark as resolved:

    git add file.txt
    git commit
    
  3. Abort merge if needed:

    git merge --abort
    

Docker Issues

"Permission denied while trying to connect to the Docker daemon"

Symptom:

$ docker ps
permission denied while trying to connect to the Docker daemon socket

Solutions:

  1. Use sudo:

    sudo docker ps
    
  2. Add user to docker group:

    sudo usermod -aG docker $USER
    
  3. Log out and back in for changes to take effect.


Container exits immediately

Symptom:

$ docker run nginx
$ docker ps -a
CONTAINER ID   STATUS
abc123         Exited (0) 5 seconds ago

Solutions:

  1. Container may have no foreground process

  2. Use -d for detached mode:

    docker run -d nginx
    
  3. Check logs:

    docker logs <container_id>
    

Getting Help

Built-in Help

Man pages (manual):

man <command>      # e.g., man ls
man -k <keyword>   # Search man pages

Help flag:

<command> --help   # e.g., ls --help

Info pages:

info <command>

Online Resources

  • Fedora Documentation: https://docs.fedoraproject.org/
  • Debian Documentation: https://www.debian.org/doc/
  • Arch Wiki (excellent general reference): https://wiki.archlinux.org/
  • Linux Command Library: https://linux.die.net/
  • Stack Overflow: https://stackoverflow.com/questions/tagged/linux

Community Forums

  • Fedora Discussion: https://discussion.fedoraproject.org/
  • Debian Forums: https://forums.debian.net/
  • Reddit r/linux4noobs: https://reddit.com/r/linux4noobs

Debugging Commands

CommandPurpose
journalctl -xbView boot messages
dmesgKernel ring buffer
systemctl --failedList failed services
strace <command>Trace system calls
ltrace <command>Trace library calls
tail -f /var/log/syslogFollow system log