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:
- Foundations — Introduction, installation, and desktop environment
- CLI Mastery — File system, commands, text processing, permissions
- System Administration — Packages, processes, scripting, networking
- 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
| Feature | Linux | Windows | macOS |
|---|---|---|---|
| Source Code | Open (anyone can view/modify) | Closed (proprietary) | Closed (proprietary) |
| Cost | Free | $100-$200+ | Included with Apple hardware |
| Customization | Unlimited | Limited | Limited |
| Package Management | Central repositories | Manual downloads | App Store + manual |
| Privacy | Full control | Data collection concerns | Data collection concerns |
| Development | Native environment | WSL/secondary | Unix-based but closed |
| Gaming | Improving rapidly (Proton/Steam) | Excellent | Moderate |
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:
- Freedom 0: The freedom to run the program as you wish, for any purpose
- Freedom 1: The freedom to study how the program works, and change it
- Freedom 2: The freedom to redistribute copies so you can help others
- 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
| Philosophy | Focus | Key Organization |
|---|---|---|
| Free Software | Ethics, user rights | Free Software Foundation (FSF) |
| Open Source | Practical benefits, methodology | Open 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
| Aspect | Fedora | Debian |
|---|---|---|
| Philosophy | Cutting-edge, latest software | Stable, rock-solid |
| Release Cycle | Every ~6 months | When ready (2-3 years) |
| Package Manager | dnf (RPM-based) | apt (DEB-based) |
| Best For | New hardware, developers, enthusiasts | Servers, production, stability |
| Parent/Child | Upstream for RHEL | Upstream for Ubuntu, Mint |
| Community | Red Hat sponsored | Community-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
| Distribution | Use Case |
|---|---|
| Ubuntu | Most popular beginner distro, based on Debian |
| Linux Mint | Windows-like experience, very beginner-friendly |
| Pop!_OS | Ubuntu-based, optimized for developers |
| Arch Linux | Rolling release, DIY, advanced users |
| Kali Linux | Penetration testing and security |
| Raspberry Pi OS | Single-board computers, education |
The Linux Ecosystem
Desktop Environments
Unlike Windows or macOS, Linux lets you choose your complete desktop experience:
| Desktop Environment | Characteristics | Resource Usage | Best For |
|---|---|---|---|
| GNOME | Modern, gesture-based, default on Fedora | Medium | Most users, modern workflows |
| KDE Plasma | Highly customizable, Windows-like | Low-Medium | Power users, Windows refugees |
| XFCE | Lightweight, traditional | Low | Older hardware, minimalists |
| Cinnamon | Traditional, similar to Windows 7 | Low | Windows users |
This course uses GNOME — the default on Fedora and Debian, modern, and well-documented.
Package Managers
| Package Manager | Distributions |
|---|---|
| dnf (Fedora) | Fedora, RHEL, CentOS |
| apt (Debian) | Debian, Ubuntu, Linux Mint |
| pacman (Arch) | Arch Linux, Manjaro |
| zypper | openSUSE |
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:
- Watch Linus Torvalds' 2016 TED Talk: "The mind behind Linux"
- Browse the Linux Foundation's history page
- 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:
- What are the kernel versions in each?
- What desktop environment do they default to?
- Name one advantage of each distribution
- 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:
- The project name
- What programming language it's written in
- 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:
- Timeline Notes: A list of 3+ interesting facts from Linux history
- Distribution Comparison: A documented choice between Fedora and Debian with reasoning
- Open Source Inventory: A list of 5+ open source projects you use
- Philosophy Reflection: A written reflection on software freedom
Further Reading
- The Linux Kernel Archives
- Free Software Foundation
- DistroWatch - Compare hundreds of distributions
- Linux Journey - Interactive learning resource
Discussion Questions
- Why do you think all supercomputers run Linux?
- What are the trade-offs between "bleeding edge" (Fedora) and "stable" (Debian) distributions?
- How does open source change the relationship between software creators and users?
- 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
| Component | Minimum | Recommended |
|---|---|---|
| CPU | 64-bit processor | Modern multi-core |
| RAM | 4 GB | 8 GB+ |
| Storage | 20 GB free space | 50 GB+ SSD |
| USB | 4 GB | 8 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.
- External Drive: Copy important files to external storage
- Cloud Backup: Use Google Drive, Dropbox, OneDrive
- 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).
Step 2: Verify the Download (Optional but Recommended)
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)
- Download from balena.io/etcher
- Open Etcher
- Flash from file: Select your downloaded ISO
- Select target: Choose your USB drive
- Flash! (this will erase all data on the USB)
Option B: Using Fedora Media Writer (Fedora Only)
- Install Fedora Media Writer from the website
- Select "Fedora Workstation 40"
- Choose your USB drive
- 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
| Type | Purpose | Size Recommendation |
|---|---|---|
| EFI System Partition | Boot files (UEFI) | 512 MB |
| Root (/) | System files, applications | 30-50 GB minimum |
| /home | User data, documents | Remainder of disk |
| Swap | Virtual memory (hibernation) | Equal to RAM size |
File Systems
| File System | Description | Use Case |
|---|---|---|
| ext4 | Standard Linux filesystem | Most installations |
| btrfs | Advanced features, snapshots | Fedora default, data safety |
| xfs | High performance, large files | Servers, large datasets |
| NTFS | Windows filesystem | Windows 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
-
Open Disk Management in Windows:
Right-click Start → Disk Management -
Right-click your C: drive → Shrink
-
Enter size to shrink (at least 50 GB, recommended 100 GB+)
-
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:
- Open Control Panel → Power Options
- Click "Choose what the power buttons do"
- Click "Change settings that are currently unavailable"
- Uncheck "Turn on fast startup"
- Save changes
Step 2: Boot from USB
-
Insert your bootable USB
-
Restart your computer
-
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
-
Select your USB drive from the boot menu
Step 3: Install Fedora
Boot Menu
- Select "Start Fedora Workstation 40" (or your version)
- Press Enter to boot
- 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:
| Section | Action |
|---|---|
| LOCALIZATION | Set your time zone |
| SOFTWARE | Accept defaults (or add development tools) |
| SYSTEM | Configure installation destination |
| USER | Create 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
-
Remove USB when prompted
-
Reboot
-
You should see GRUB boot menu:
Fedora Workstation (default) Advanced options for Fedora Windows Boot Manager (on /dev/sda1) -
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:
- Privacy Settings: Enable or disable location services
- Online Accounts: Connect Google, Nextcloud, etc. (optional)
- 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
Recommended VM Software
| Software | Cost | License | Best For |
|---|---|---|---|
| VirtualBox | Free | Open Source | Beginners, cross-platform |
| VMware Workstation Player | Free | Proprietary | Windows host, better performance |
| GNOME Boxes | Free | Open Source | Linux host, simple |
| QEMU/KVM | Free | Open Source | Advanced users, best performance |
Installing with VirtualBox (Recommended)
Step 1: Install VirtualBox
Download from virtualbox.org
Step 2: Create a New VM
- Click New
- Name:
Fedora Linux→ Type: Linux → Version: Fedora 64-bit - Memory: At least 4096 MB (4 GB)
- 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
- Start the VM
- Follow the same installation steps as dual-boot
- The VM will automatically use the entire virtual disk
Step 5: Install Guest Additions (Optional)
After installation, this improves performance:
- In VM menu: Devices → Insert Guest Additions CD image
- 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:
- Open GNOME Software
- Click the menu → Software Repositories
- 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:
- Boot into BIOS/UEFI (F2, Del, F10)
- Find Boot Order settings
- Change boot order to prioritize Linux boot manager
- 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:
| Method | Performance | Safety | Complexity |
|---|---|---|---|
| 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:
-
What is your current system specification?
- CPU model and cores
- RAM amount
- Disk size and free space
- Graphics card
-
Which installation method will you use and why?
- Dual-boot, VM, or replace Windows?
- Justify your choice
-
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
- Download Fedora Workstation ISO
- Verify the checksum (SHA256)
- Create a bootable USB using BalenaEtcher
- 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:
- Shrink Windows partition
- Install Linux alongside Windows
- Verify both OSes boot correctly
If VM:
- Create a virtual machine
- Install Linux inside it
- 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:
- System Assessment: Documented specs and installation plan
- Bootable USB: Working Fedora or Debian USB drive
- Partition Diagram: Clear understanding of disk layout
- Working Linux Installation: System you can boot and use
Further Reading
Discussion Questions
- Why might someone choose a VM over dual-boot, or vice versa?
- What are the risks of dual-booting? How can they be mitigated?
- Why does Linux use different file systems (ext4, btrfs) than Windows (NTFS)?
- 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
| Feature | GNOME | KDE Plasma | XFCE |
|---|---|---|---|
| Philosophy | Modern, minimal | Highly customizable | Traditional, lightweight |
| Resource Usage | Medium | Low-Medium | Low |
| Default on | Fedora, Debian, Ubuntu | Kubuntu, KDE neon | Xubuntu, Mint XFCE |
| Touch/Gestures | Excellent | Good | Basic |
| Learning Curve | Medium | Low-Medium | Low |
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:
| Action | Shortcut |
|---|---|
| Open Activities Overview | Super (Windows key) or Alt+F1 |
| Application Search | Super, then type |
| Switch Windows | Alt+Tab |
| Switch Workspaces | Super+PageUp/PageDown |
| Show All Applications | Super+A |
| Open Terminal | Super+Enter (if configured) |
| Close Window | Alt+F4 or Super+Q |
| Hide Window | Super+H |
| Lock Screen | Super+L |
| Screenshot | PrintScreen |
💡 Pro Tip: The
Superkey is the Windows key on most keyboards. macOS users can useCommandin 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]
Navigating the Overview
Opening Applications
- Press
Superto open Activities - Click the grid icon (bottom-left) to show All Applications
- Scroll or search to find your app
- Click to launch
Switching Between Windows
- Press
Superfor Activities - Click on any window thumbnail to focus it
- Or press
Alt+Tabfor quick switching
Managing Workspaces
- Press
Superfor Activities - Look at the right side — you'll see workspaces
- Drag windows between workspaces
- 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:
- Open Activities → All Applications
- Right-click an app
- Select "Add to Favorites"
To remove a favorite:
- Right-click the app in the Dash
- Select "Remove from Favorites"
Window Management
Window Actions
| Action | Mouse | Keyboard |
|---|---|---|
| Move window | Drag title bar | Alt+F7 then arrows |
| Resize window | Drag edges/corners | Alt+F8 then arrows |
| Maximize | Click maximize button | Super+↑ or Alt+F10 |
| Unmaximize | Click unmaximize | Super+↓ |
| Minimize/Hide | Click minimize | Super+H |
| Close | Click × or Alt+F4 | Alt+F4 |
| Always on Top | Right-click title bar | Not 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 halfSuper+→→ Right halfSuper+↑→ MaximizeSuper+↓→ 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:
| Action | Shortcut |
|---|---|
| Switch to next workspace | Super+PageDown |
| Switch to previous workspace | Super+PageUp |
| Move window to next workspace | Super+Shift+PageDown |
| Open new workspace | Just drag a window to empty space |
Customization (Themes, Extensions)
GNOME Settings Overview
Open Settings via:
- System Menu → Settings (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:
- Open Settings → Appearance
- Click Background or Lock Screen
- 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.
Popular Extensions
| Extension | Purpose |
|---|---|
| Dash to Dock | Transform the Dash into a configurable dock |
| AppIndicator/KStatusNotifierItem | Tray icons (Discord, Spotify, etc.) |
| ArcMenu | Windows-style start menu |
| Blur my Shell | Blur effects on overview, dash |
| GSConnect | Pair Android phone with desktop |
| Caffeine | Prevent screen from automatically locking |
Installing Extensions
Method 1: GNOME Software (Easiest)
- Open GNOME Software
- Search for "Extensions" app
- Install "Extensions" (the manager app)
- Browse and install extensions directly
Method 2: Web Browser
- Visit extensions.gnome.org
- Browse extensions
- Toggle switch to install (requires browser extension)
- 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:
| Setting | Description | Default |
|---|---|---|
| Interface Text | UI font | Cantarell 11 |
| Document Text | Document reading | Sans 11 |
| Monospace Text | Code, terminal | Monospace 11 |
| Legacy Window Titles | Older apps | Sans 11 |
| Antialiasing | Smooth edges | Subpixel |
| Scaling Factor | Text size | 1.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:
- Click the network icon in top bar
- Select your network
- Enter password
Forgetting a network:
- Settings → Network
- Click the gear icon next to the network
- 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
| Setting | Purpose |
|---|---|
| Output | Speakers/headphones |
| Input | Microphone |
| System Sounds | Alert sounds |
| Volume | Master volume level |
Quick Mute: Click volume icon → select Mute
4. Power & Battery
Settings → Power
| Profile | Use Case |
|---|---|
| Balanced Power | Default for most users |
| Power Saver | Extend battery life |
| Performance | Maximum 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:
- Open GNOME Software
- Browse or search for an app
- Click Install
To remove:
- Click Installed tab
- Find the app
- 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
| Category | Recommended Apps |
|---|---|
| Web Browsers | Firefox, Chromium, Brave |
| Office | LibreOffice, OnlyOffice |
| Graphics | GIMP, Inkscape, Krita |
| Media | VLC, Audacity, OBS |
| Communication | Discord, Thunderbird |
| Development | VS Code, Sublime Text |
Summary
Key Takeaways:
- GNOME is the default desktop on Fedora and Debian
- Activities Overview (
Superkey) 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:
| Shortcut | Action |
|---|---|
Super | Open Activities |
Alt+Tab | Switch windows |
Super+Enter | Open terminal |
Super+L | Lock screen |
PrintScreen | Screenshot |
Chapter Quiz
Test your understanding of the GNOME desktop environment:
Exercises
Exercise 1: GNOME Navigation Scavenger Hunt
Complete these tasks as fast as possible:
- Open the Activities Overview
- Find and launch GNOME Terminal
- Open a second workspace
- Move Terminal to workspace 2
- Switch back to workspace 1
- Open GNOME Files (Nautilus)
- Maximize the Files window
- Close the Files window
- Lock the screen
- Unlock and return
Deliverable: Record your time and list which shortcuts you used.
Exercise 2: Desktop Customization
Personalize your desktop:
- Change your desktop background
- Enable dark mode
- Add 5 applications to your favorites/dock
- Install 1 GNOME extension (from Extensions app)
- Change your interface font size
- Configure your power settings
Deliverable: Screenshots of your customized desktop.
Exercise 3: Application Installation
Install these applications:
- Via GNOME Software: Install VLC media player
- Via Flatpak: Install Flatpak, add Flathub, install 1 app
- Via Terminal (preview): Use
dnfto installtree
$ sudo dnf install tree
Deliverable: List the commands/steps you used for each method.
Exercise 4: Workspace Workflow
Create a productive workspace setup:
- Workspace 1: Browser + Terminal
- Workspace 2: Files + Text Editor
- 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:
- Navigation Skills: Can use GNOME efficiently without mouse
- Customized Desktop: Personalized appearance and setup
- Installed Apps: VLC, Flatpak app, and
treecommand - Workspace Workflow: Organized multi-desktop setup
Further Reading
Discussion Questions
- Why does GNOME hide options compared to Windows/macOS? Is this good or bad?
- How does GNOME's dynamic workspace model compare to fixed virtual desktops?
- What are the security implications of installing extensions from the web?
- 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, andls - 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
| Directory | Purpose | What You'll Find There |
|---|---|---|
/home/username | Your home directory | Your personal files, documents, downloads |
/bin | Binaries | Essential commands like ls, cp, cat |
/etc | Etcetera (config) | System-wide configuration files |
/var | Variable data | Logs, web server files, mail queues |
/tmp | Temporary | Files 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:
| Option | Purpose | Example |
|---|---|---|
-l | Long format (details) | ls -l |
-a | Show hidden files (dotfiles) | ls -a |
-h | Human-readable sizes | ls -lh |
-la | Combined: long + all | ls -la |
-t | Sort by time modified | ls -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:
| Symbol | Meaning |
|---|---|
. | 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:
| Command | Destination | Path Type |
|---|---|---|
cd /home/student | /home/student | Absolute |
cd .. | /home/student | Relative |
cd ../Pictures | /home/student/Pictures | Relative |
cd ~/Pictures | /home/student/Pictures | Absolute (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 -rfis 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
- Always use it - It prevents typos and saves keystrokes
- Press Tab twice - If nothing happens, press again to see options
- Works with commands too - Type
cha[TAB]to getchattr,chacl, etc. - 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:
| File | Purpose |
|---|---|
.bashrc | Bash shell configuration |
.bash_history | Command history |
.gitconfig | Git 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
- Open your terminal
- Navigate to
/etc - List the contents
- Go to
/var/log - Return to your home directory using a single command
- 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
- Navigate to
~/linux-course/session01 - Create an empty file called
notes.txt - Go back to
~/linux-course - Use tab completion to navigate to
session01/notes.txt
Exercise 4: Path Practice
Starting from /home/student, use relative paths to:
- Go to
/home/student/Documents - From there, go to
/home/student/Picturesusing only relative paths - Return to
/home/studentusing the shortest command
Exercise 5: Exploration Challenge
- Navigate to
/usr/bin - Count how many executables are there (hint:
ls | wc -l) - Find if
python3exists there (hint:ls python*) - 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, andtail -
Copy and move files with
cpandmv -
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]
| Component | Description | Example |
|---|---|---|
command | The program to run | ls |
options | Modify behavior (usually start with -) | -l, -a, -la |
arguments | What 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:
| Key | Action |
|---|---|
Space or f | Page forward |
b | Page backward |
Arrow keys | Line by line |
/pattern | Search forward |
n | Next search result |
q | Quit |
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
| Task | GUI Action | CLI Command |
|---|---|---|
| Open file | Double-click | cat file.txt |
| View large file | Scroll with mouse | less large.txt |
| Check beginning | Scroll to top | head file.txt |
| Check end | Scroll to bottom | tail file.txt |
| Watch log | Reopen file | tail -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:
| Option | Purpose |
|---|---|
-i | Interactive (prompt before overwriting) |
-r | Recursive (for directories) |
-p | Preserve mode, ownership, timestamps |
-v | Verbose (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 fileless- Scroll through large fileshead/tail- View start/end of files
- File Operations:
cp- Copy files/directoriesmv- 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
- Create a test file:
echo -e "Line 1\nLine 2\nLine 3" > test.txt - View it with
cat - View the first line only
- View the last line only
- View it with
less, then search for "Line 2"
Exercise 2: Copy and Organize
- Create these files:
touch file1.txt file2.txt file3.txt doc1.pdf doc2.pdf - Create directories:
mkdir text docs - Move all
.txtfiles totext/ - Copy all
.pdffiles todocs/ - Verify with
ls
Exercise 3: Pipeline Practice
- List all files in
/bin - Pipe to
wc -lto count them - Pipe to
grep zipto find compression tools - Find the 5 largest files in
/usr/bin(hint:ls -lS | head)
Exercise 4: Redirection
- Create a file with content:
echo "First line" > output.txt - Add another line:
echo "Second line" >> output.txt - View the result
- Count lines:
wc -l < output.txt
Exercise 5: Wildcards
- Create files:
touch file1.txt file2.txt fileA.txt file10.txt data.csv data.txt - List all files starting with "file"
- List all
.txtfiles - List
filefollowed by exactly one character - List
filefollowed 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
sedfor search and replace -
Use
awkfor text extraction and formatting -
Sort, count, and deduplicate with
sort,uniq, andwc - 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
| Option | Purpose | Example |
|---|---|---|
-i | Ignore case | grep -i error log.txt |
-r | Recursive | grep -r "function" src/ |
-n | Show line numbers | grep -n TODO *.py |
-c | Count matches | grep -c "error" log.txt |
-v | Invert match | grep -v "#" config.txt |
-l | List matching files | grep -l "import" *.py |
-w | Whole word only | grep -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
| Operation | Command | Description |
|---|---|---|
| Delete lines | sed '5d' file.txt | Delete line 5 |
| Delete range | sed '5,10d' file.txt | Delete lines 5-10 |
| Print specific | sed -n '5p' file.txt | Print only line 5 |
| Delete pattern | sed '/pattern/d' file.txt | Delete matching lines |
| Print pattern | sed -n '/pattern/p' file.txt | Print 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
| Variable | Meaning |
|---|---|
$0 | Entire line |
$1, $2, ... | Fields 1, 2, ... |
$NF | Number of fields (last field) |
NR | Current record number (line number) |
FS | Field separator (default: space) |
OFS | Output 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:
cat access.log- Read the log fileawk '{print $1}'- Extract first column (IP address)sort- Sort IPs to group duplicatesuniq -c- Count occurrencessort -rn- Sort by count, descending, numericallyhead -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
| Task | Command |
|---|---|
| Search pattern | grep "pattern" file.txt |
| Find file by name | find . -name "file.txt" |
| Replace text | sed 's/old/new/g' file.txt |
| Extract column | awk '{print $1}' file.txt |
| Count lines | wc -l file.txt |
| Sort file | sort file.txt |
| Remove duplicates | sort 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
- Find all lines containing "ERROR"
- Count how many lines have "ERROR"
- Find lines with "ERROR" or "WARNING"
- Show line numbers with matches
Exercise 2: Find and Process
- Find all
.txtfiles in your home directory - Find all files larger than 1MB in
/var/log - Find all files modified in the last 24 hours
- Count how many
.conffiles 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
- Extract the name column (column 1)
- Calculate the average score
- Find rows where age is 25
- Format as: "Name: Alice, Score: 95"
Exercise 4: Pipeline Building
- Create a list of random numbers:
for i in {1..20}; do echo $RANDOM; done > numbers.txt - Find the 5 largest numbers
- Count how many are greater than 10000
- 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
- Count how many 404 errors occurred
- Find the IP address that made the most requests
- Extract all unique pages visited
- 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 -loutput and permission strings -
Change permissions using symbolic and numeric modes with
chmod -
Change file ownership with
chownandchgrp -
Use
sudoto execute commands with elevated privileges -
Manage users and groups with
useradd,usermod, andpasswd
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
| Permission | Symbol | Description | For Files | For Directories |
|---|---|---|---|---|
| Read | r | View contents | Can read file | Can list directory |
| Write | w | Modify contents | Can change file | Can add/remove files |
| Execute | x | Run as program | Can execute file | Can enter directory |
The Three User Classes
| Class | Symbol | Description |
|---|---|---|
| User (Owner) | u | The file's owner |
| Group | g | Users in the file's group |
| Others | o | Everyone 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
| Character | Type |
|---|---|
- | Regular file |
d | Directory |
l | Symbolic link |
b | Block device |
c | Character device |
s | Socket |
p | Named 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:
| Operator | Action |
|---|---|
+ | Add permission |
- | Remove permission |
= | Set exact permission |
Numeric Mode (Power User)
Each permission has a numeric value:
| Permission | Value |
|---|---|
r (read) | 4 |
w (write) | 2 |
x (execute) | 1 |
Add them up for combined permissions:
| Value | Permissions | Meaning |
|---|---|---|
| 0 | --- | No permissions |
| 1 | --x | Execute only |
| 2 | -w- | Write only |
| 3 | -wx | Write + execute |
| 4 | r-- | Read only |
| 5 | r-x | Read + execute |
| 6 | rw- | Read + write |
| 7 | rwx | All 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
| Bit | Prefix | Purpose | Example |
|---|---|---|---|
| SUID | 4 | Execute as owner | 4755 |
| SGID | 2 | Inherit group | 2755 |
| Sticky | 1 | Owner-only delete | 1755 |
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
| umask | File Permissions | Directory Permissions | Use Case |
|---|---|---|---|
| 022 | 644 (rw-r--r--) | 755 (rwxr-xr-x) | Default (shared read) |
| 027 | 640 (rw-r-----) | 750 (rwxr-x---) | Group-private |
| 077 | 600 (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 -loutput - 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
| Task | Command |
|---|---|
| View permissions | ls -l file.txt |
| Make script executable | chmod +x script.sh |
| Set standard file perms | chmod 644 file.txt |
| Set standard dir perms | chmod 755 directory/ |
| Change owner | sudo chown user file.txt |
| Add to group | sudo usermod -aG group user |
| Run as root | sudo command |
| View groups | groups 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
- Note the default permissions
- Add execute permission for owner only
- Remove read permission for group
- Set permissions to
rwxr-xr--using numeric mode - Verify each step with
ls -l
Exercise 2: Create Executable Script
- Create a script that prints "Hello, Linux!"
- Make it executable
- Run it
- 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!
- Write the command to create user "johndoe"
- Write the command to set johndoe's password
- Write the command to add johndoe to the "docker" group
- 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
- Why does this fail?
- What command fixes it?
- What would the permissions be after fixing?
Exercise 5: Set Up Shared Directory
Design commands for a shared team directory:
- Create
/shared/team(requires sudo) - Set ownership to
alice:developers - Set permissions so:
- Team members can read/write/execute
- Others have no access
- 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
| Advantage | Description |
|---|---|
| Security | Packages are signed and verified |
| Dependencies | Automatically handles required libraries |
| Updates | One command updates everything |
| Removal | Clean uninstallation |
| Centralized | No 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
| Task | Fedora (DNF) | Debian (APT) |
|---|---|---|
| Refresh repos | Automatic | sudo apt update |
| Install | sudo dnf install pkg | sudo apt install pkg |
| Remove | sudo dnf remove pkg | sudo apt remove pkg |
| Remove + config | sudo dnf remove pkg | sudo apt purge pkg |
| Update packages | sudo dnf upgrade | sudo apt upgrade |
| Search | dnf search query | apt search query |
| Package info | dnf info pkg | apt show pkg |
| List installed | dnf list installed | apt list --installed |
| Clean cache | sudo dnf clean all | sudo 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.
Flatpak (Recommended for Fedora)
# 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(plusapt updatefor Debian) - Removal:
dnf remove/apt remove(useapt purgeto 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
- Search for the
neovimpackage - View its information
- Install it
- Verify it's installed
Exercise 2: System Update
- Check for available updates
- Update your system
- Review what was updated
Exercise 3: Package Discovery
- Search for image manipulation software
- Find and install
gimp - Use
providesorapt-fileto find which package providesffmpeg
Exercise 4: Cleanup
- List installed packages
- Remove a package you don't need
- Clean the package cache
- Remove orphaned dependencies
Exercise 5: Flatpak (Optional)
- Install Flatpak support
- Add Flathub repository
- Install an app from Flathub (e.g., Spotify)
- 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, andhtop - 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
| Concept | Description |
|---|---|
| PID | Process ID - unique number identifying each process |
| PPID | Parent Process ID - the process that started this one |
| User | Owner of the process (root or your user) |
| State | Running, sleeping, stopped, zombie |
| Priority | How 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
| Column | Meaning |
|---|---|
| USER | Process owner |
| PID | Process ID |
| %CPU | CPU usage percentage |
| %MEM | Memory usage percentage |
| VSZ | Virtual memory size (KB) |
| RSS | Resident Set Size - actual RAM used |
| TTY | Terminal type (?: no terminal) |
| STAT | Process state (S=sleeping, R=running) |
| START | When process started |
| TIME | Total CPU time used |
| COMMAND | Command that started the process |
Process States (STAT column)
| Code | State | Description |
|---|---|---|
| R | Running | Currently running or runnable |
| S | Sleeping | Waiting for something (I/O, etc.) |
| D | Uninterruptible | Waiting for I/O (cannot be interrupted) |
| Z | Zombie | Completed but not yet cleaned up by parent |
| T | Stopped | Paused (usually by SIGSTOP) |
| s | Session leader | |
| + | Foreground process | In 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:
| Key | Action |
|---|---|
q | Quit |
k | Kill a process (enter PID) |
r | Renice (change priority) |
M | Sort by memory |
P | Sort by CPU (default) |
1 | Show per-CPU stats |
u | Filter by user |
h | Help |
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>
| Signal | Number | Description |
|---|---|---|
| SIGTERM | 15 | Terminate politely (asks to close) |
| SIGKILL | 9 | Kill immediately (cannot be ignored) |
| SIGHUP | 1 | Hang up (reload config) |
| SIGINT | 2 | Interrupt (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
| Service | Purpose |
|---|---|
ssh or sshd | SSH server for remote access |
NetworkManager | Network connectivity |
firewalld | Firewall management |
cups | Printing service |
cron or systemd-cron | Scheduled tasks |
nginx | Web server |
docker | Container 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
| Column | Description |
|---|---|
| total | Total RAM |
| used | Used by applications |
| free | Completely free |
| shared | Shared between processes (tmpfs) |
| buff/cache | Cached files (can be freed) |
| available | Available for new apps |
| Swap | Disk 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:
systemctlto manage system services - System Logs:
journalctlfor viewing logs - Resource Monitoring:
free,df,du,top
Chapter Quiz
Test your understanding of processes and services:
Exercises
Exercise 1: Process Exploration
- Run
ps auxand count the processes - Find your shell process
- Find the systemd process (PID 1)
- Use
pstreeto see the process hierarchy
Exercise 2: Monitor with top/htop
- Start
htop(install if needed) - Sort by CPU (press P)
- Sort by memory (press M)
- Watch for 30 seconds and note the top processes
Exercise 3: Service Management
- Check if SSH service is running
- View its status
- Check if it's enabled at boot
- View recent SSH logs with journalctl
Exercise 4: Process Control
- Start a long-running process in background:
sleep 300 & - Find its PID
- Bring it to foreground and then suspend with Ctrl+Z
- Resume it in background
- Kill the process
Exercise 5: Logs and Troubleshooting
- View the last 20 system log entries
- Find any error or warning messages
- Check logs from the last boot
- 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?
| Task | Manual Way | Script Way |
|---|---|---|
| Backup files | Copy each folder | ./backup.sh |
| Deploy app | Type 10 commands | ./deploy.sh |
| Clean logs | Delete each file | ./cleanup.sh |
| Monitor system | Run 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"
| Variable | Description |
|---|---|
$USER | Current username |
$HOME | User's home directory |
$PWD | Present working directory |
$SHELL | Default shell path |
$HOSTNAME | System hostname |
$PATH | Command 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 Test | Meaning |
|---|---|
-f file | File exists |
-d dir | Directory exists |
-e file | Exists (file or dir) |
-r file | File is readable |
-w file | File is writable |
-x file | File is executable |
| String Comparison | Meaning |
|---|---|
"$s1" = "$s2" | Strings equal |
"$s1" != "$s2" | Strings not equal |
-z "$s" | String is empty |
-n "$s" | String is not empty |
| Number Comparison | Meaning |
|---|---|
$n1 -eq $n2 | Equal |
$n1 -ne $n2 | Not equal |
$n1 -gt $n2 | Greater than |
$n1 -ge $n2 | Greater or equal |
$n1 -lt $n2 | Less than |
$n1 -le $n2 | Less 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
| Error | Cause | Fix |
|---|---|---|
command not found | Typo or command not installed | Check spelling |
permission denied | Not executable | Run chmod +x script.sh |
syntax error | Missing quote, bracket, etc. | Check matching pairs |
bad substitution | Wrong variable syntax | Use ${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
- Create a script that asks for your name
- Greets you with the current date
- Tells you how many files are in the current directory
Exercise 2: Number Guessing Game
- Generate a random number:
random=$((1 + RANDOM % 100)) - Ask the user to guess
- Tell them if it's too high or too low
- Continue until they guess correctly
Exercise 3: File Backup
- Create a script that backs up all
.txtfiles - Create a
backup/directory if it doesn't exist - Copy all
.txtfiles with a timestamp prefix - Print a summary of files copied
Exercise 4: System Monitor
- Create a script that checks disk usage
- If disk usage is above 80%, print a warning
- Check if a specific service is running
- Print a summary report
Exercise 5: Calculator
- Create a script that takes two numbers
- Ask for the operation (+, -, *, /)
- Perform the calculation
- 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
| Concept | Description | Example |
|---|---|---|
| IP Address | Unique identifier for a device | 192.168.1.100 |
| Subnet Mask | Defines network range | 255.255.255.0 |
| Gateway | Route to other networks | 192.168.1.1 (router) |
| DNS | Translates names to IPs | google.com → 142.250.x.x |
| Port | Specific service on a machine | 22 for SSH, 80 for web |
| MAC Address | Hardware network ID | 00: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
| State | Meaning |
|---|---|
| UP | Interface is active |
| DOWN | Interface is disabled |
| UNKNOWN | Connection state unknown |
Network Interface Types
| Interface | Description |
|---|---|
| lo | Loopback (localhost) |
| eth0 | Ethernet (wired) |
| wlan0 | Wireless (WiFi) |
| enp0s3 | Modern naming for ethernet |
| wlp3s0 | Modern 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
| Option | Meaning |
|---|---|
-a | Archive mode (preserves permissions, times) |
-v | Verbose (show what's happening) |
-z | Compress during transfer |
--progress | Show progress |
--delete | Delete extra files in destination |
--dry-run | Preview 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
| Problem | Diagnosis | Solution |
|---|---|---|
| No connection | ip addr shows DOWN | Bring interface up |
| Can't reach internet | Gateway unreachable | Check router connection |
| Can't browse sites | DNS failure | Use 8.8.8.8 as DNS |
| Port blocked | nc -zv fails | Check firewall |
| Slow connection | High ping times | Check 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
-
Use key-based auth, not passwords
ssh-keygen -t ed25519 ssh-copy-id user@host -
Disable password authentication (server-side)
# Edit /etc/ssh/sshd_config PasswordAuthentication no -
Change default SSH port
# Edit /etc/ssh/sshd_config Port 2222 -
Use firewall to limit access
sudo ufw allow from 192.168.1.0/24 to any port 22
General Network Security
| Practice | Why |
|---|---|
| Use SSH, not Telnet | Encrypted vs plain text |
| Keep system updated | Security patches |
| Use firewall | Block unwanted access |
| Monitor logs | Detect intrusion |
| Use VPN for public WiFi | Encrypt 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
- Check your IP address
- Check your default gateway
- Check your DNS servers
- List all network interfaces
Exercise 2: Connectivity Testing
- Ping your local gateway
- Ping 8.8.8.8 (Google DNS)
- Ping google.com
- Trace route to google.com
Exercise 3: SSH Connection
- Generate SSH key pair (if you don't have one)
- Copy your public key to a remote machine (or VM)
- Connect using SSH
- Run a remote command via SSH
Exercise 4: File Transfer
- Create a test file
- Copy it to remote machine using scp
- Sync a directory using rsync
- Verify the transfer
Exercise 5: Troubleshooting
- Create a network diagnostic script
- Check interface status
- Test gateway connectivity
- Test DNS resolution
- 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
| Scenario | Without Version Control | With Version Control |
|---|---|---|
| Made a mistake | Restore from backup (hope you have one) | git revert - instant undo |
| Want to experiment | Copy the entire folder | git branch - zero-cost experiments |
| Collaborate | Email files back and forth | git push/pull - seamless sharing |
| See history | Remember when you changed what | git log - complete audit trail |
| Compare versions | Open files side-by-side manually | git 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
- Working Directory: The actual files on your disk
- Staging Area (Index): Files prepared for the next commit
- 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:
- Edit the file to choose which version to keep (or combine both)
git add <resolved-file>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
| Command | Description |
|---|---|
git init | Initialize a new repository |
git clone <url> | Clone an existing repository |
git status | Show working tree status |
git add <file> | Stage changes |
git commit -m "message" | Commit staged changes |
git log | Show commit history |
git diff | Show unstaged changes |
git diff --staged | Show staged changes |
git branch | List/create branches |
git checkout <branch> | Switch branches |
git checkout -b <branch> | Create and switch branch |
git merge <branch> | Merge branch into current |
git remote -v | List remotes |
git push | Push to remote |
git pull | Pull from remote |
git stash | Temporarily save changes |
git stash pop | Restore 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:
- Create a directory called
git-practice - Initialize it as a Git repository
- Create a file called
notes.mdwith some content - Stage and commit the file with a descriptive message
- Add more content to
notes.mdand create a second commit - 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:
- Create a new branch called
experiment - On the
experimentbranch, create a file calledtest.txt - Commit the file
- Switch back to
main - Merge the
experimentbranch intomain - Delete the
experimentbranch - 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:
- Create a file with content, commit it
- Modify the file and commit again
- Use
git reset --soft HEAD~1to undo the last commit (keeps changes staged) - Use
git reset HEAD~1to unstage changes - 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:
- Create a branch called
conflict-test - On
main, createconflict.mdwithVersion Aand commit - Switch to
conflict-test, modify the same line toVersion Band commit - Switch back to
mainand change the same line toVersion Cand commit - Merge
conflict-testintomain - Resolve the conflict by choosing or combining versions
- Complete the merge
Exercise 5: Remote Collaboration (Optional)
If you have a GitHub/GitLab account:
- Create a new repository on the platform
- Add it as a remote to your local repository
- Push your local commits
- Make a change on the web interface
- Pull the changes to your local machine
- Verify the synchronization
Expected Output
After completing these exercises, you should have:
- A working Git repository with multiple commits
- Branching experience — you've created, merged, and deleted branches
- Undo skills — you know how to revert changes at different stages
- Conflict resolution — you've handled and resolved merge conflicts
- (Optional) Remote workflow — you've pushed and pulled from a remote
Further Reading
- Pro Git Book — Free comprehensive Git guide
- Git Interactive Tutorial — Visual branching practice
- GitHub Skills — Hands-on Git and GitHub practice
- Git Cheat Sheet
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
- Why is Git's distributed model better than centralized version control systems like SVN?
- When would you use
git rebaseinstead ofgit merge? - What's the difference between
git pullandgit fetch? - How does Git handle binary files (images, PDFs) differently from text files?
- Why do many projects have a
CONTRIBUTING.mdfile 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
| Aspect | Virtual Machines | Containers |
|---|---|---|
| Operating System | Full guest OS per VM | Share host OS kernel |
| Startup Time | Minutes | Seconds/milliseconds |
| Resource Usage | GBs of RAM | MBs of RAM |
| Disk Space | Multiple GBs | Tens to hundreds of MBs |
| Isolation | Complete | Process-level |
| Portability | Limited | Highly portable |
Why Use Containers?
- Consistency: "It works on my machine" becomes "It works everywhere"
- Isolation: Applications don't interfere with each other
- Portability: Run the same container on laptop, server, or cloud
- Scalability: Easily spawn multiple instances
- Efficiency: Lightweight compared to VMs
- 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
dockergroup 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 (
dockercommand) - 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:
- Docker checked for the
hello-worldimage locally - Not found locally, so it pulled from Docker Hub
- Docker created a container from the image
- 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
| Command | Description |
|---|---|
docker pull <image> | Download an image from registry |
docker images | List locally stored images |
docker rmi <image> | Delete an image |
docker image prune | Remove unused images |
Container Management
| Command | Description |
|---|---|
docker run <image> | Create and start a container |
docker ps | List running containers |
docker ps -a | List 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 prune | Remove stopped containers |
Information and Debugging
| Command | Description |
|---|---|
docker logs <container> | Show container logs |
docker inspect <container> | View container details |
docker exec -it <container> <cmd> | Run command in container |
docker stats | Live 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
| Instruction | Description | Example |
|---|---|---|
FROM | Base image | FROM ubuntu:22.04 |
WORKDIR | Set working directory | WORKDIR /app |
COPY | Copy files from host | COPY . /app |
ADD | Copy files (supports URLs/tar) | ADD app.tar.gz /app |
RUN | Execute command during build | RUN apt-get update |
CMD | Default command to run | CMD ["nginx"] |
ENTRYPOINT | Container's main command | ENTRYPOINT ["python"] |
ENV | Set environment variable | ENV APP_ENV=prod |
EXPOSE | Document exposed port | EXPOSE 80 |
VOLUME | Create mount point | VOLUME /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 Type | Description |
|---|---|
| bridge | Default, containers on same host communicate |
| host | Container uses host's network (no isolation) |
| none | No networking |
| overlay | Multi-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:
- Pull the nginx image
- Run nginx in detached mode on port 8080
- Verify it's running with
curl - View the container logs
- 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:
- Create a directory with an
index.htmlfile - Write a Dockerfile that uses nginx and copies your HTML
- Build the image with tag
my-web - Run the container on port 8081
- Verify your custom page loads
Exercise 3: Multi-Container App
Use Docker Compose to run a web app with database:
- Create a
docker-compose.ymlwith:- A Python/Flask web service
- A PostgreSQL database
- Configure networking between services
- Start with
docker compose up - Verify the services communicate
- Clean up with
docker compose down
Exercise 4: Persistent Data
Practice using volumes:
- Create a named volume
- Run a container that writes to the volume
- Remove the container
- Run a new container with the same volume
- Verify the data persists
Exercise 5: Image Inspection
Explore Docker internals:
- Pull an image (e.g.,
python:3.11) - Use
docker inspectto view image details - Identify the layers, environment variables, and exposed ports
- Run the container and explore the filesystem
- Compare two different image tags
Expected Output
After completing these exercises, you should have:
- Running containers — you've started, stopped, and removed containers
- Custom images — you've built images from Dockerfiles
- Multi-container apps — you've used Docker Compose
- Persistent data — you've used volumes for data persistence
- Docker knowledge — you understand images, containers, and the Docker ecosystem
Further Reading
- Docker Documentation
- Docker Hub — Find and share images
- Dockerfile Best Practices
- Docker Compose Reference
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
- How do containers differ from virtual machines at the kernel level?
- When would you use a bind mount instead of a volume?
- Why might you choose Alpine Linux as a base image?
- How does Docker handle security isolation between containers?
- 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
- Check if nginx is running:
sudo systemctl status nginx - Check firewall:
sudo firewall-cmd --list-all - Check logs:
sudo journalctl -u nginx -n 50 - Test config:
sudo nginx -t
Backup Issues
- Check script permissions:
ls -l ~/backup-script.sh - Check cron:
crontab -l - Check backup log:
cat ~/backups/backup.log
Docker Issues (if applicable)
- Check container:
docker ps -a - View logs:
docker logs my-nginx - Restart:
docker restart my-nginxEOF
---
## 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
-
Add Monitoring
# Install htop for monitoring sudo dnf install htop # Fedora sudo apt install htop # Debian -
Add Multiple Pages
sudo cp /var/www/html/index.html /var/www/html/about.html # Edit about.html with different content
Medium Extensions
-
Add Database Backend
sudo dnf install postgresql postgresql-server # Fedora sudo apt install postgresql postgresql-contrib # Debian -
Add Logging Dashboard
- Install GoAccess for log analysis
- Create real-time web dashboard
-
Add Firewall Rules
# Fedora sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-service=https sudo firewall-cmd --reload
Advanced Extensions
-
Containerize Everything
- Run nginx in Docker
- Run database in Docker
- Use Docker Compose
-
Add Monitoring Stack
- Prometheus for metrics
- Grafana for visualization
- AlertManager for notifications
-
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:
- Use Linux confidently in your development career
- Manage Linux servers in production environments
- Automate repetitive system administration tasks
- Contribute to open-source projects
- 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
- nginx Documentation
- Bash Guide for Beginners
- Pro Git Book
- Docker Documentation
- Linux Command Library
Cheat Sheet
Quick reference for the most essential Linux commands.
Navigation
| Command | Description |
|---|---|
pwd | Print working directory |
ls | List directory contents |
cd <path> | Change directory |
cd ~ | Go to home directory |
cd - | Go to previous directory |
File Operations
| Command | Description |
|---|---|
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
| Command | Description |
|---|---|
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) |
Search
| Command | Description |
|---|---|
grep <pattern> <file> | Search in file |
grep -r <pattern> <dir> | Search recursively |
find <dir> -name <pattern> | Find files |
locate <name> | Quick file search |
Permissions
| Command | Description |
|---|---|
chmod <perms> <file> | Change permissions |
chown <user> <file> | Change owner |
sudo <command> | Run as superuser |
chmod +x <script> | Make executable |
Package Management
Fedora (DNF)
| Command | Description |
|---|---|
dnf search <pkg> | Search package |
dnf install <pkg> | Install package |
dnf remove <pkg> | Remove package |
dnf update | Update packages |
Debian (APT)
| Command | Description |
|---|---|
apt search <pkg> | Search package |
apt install <pkg> | Install package |
apt remove <pkg> | Remove package |
apt update && apt upgrade | Update system |
Processes
| Command | Description |
|---|---|
ps aux | Show all processes |
top | Interactive process viewer |
kill <pid> | Terminate process |
systemctl status <svc> | Service status |
journalctl -u <svc> | Service logs |
Networking
| Command | Description |
|---|---|
ip addr | Show IP addresses |
ping <host> | Test connectivity |
ssh user@host | Remote login |
scp <src> <dst> | Secure copy |
Git
| Command | Description |
|---|---|
git init | Initialize repo |
git status | Show status |
git add <file> | Stage changes |
git commit -m "msg" | Commit |
git log | Show history |
Docker
| Command | Description |
|---|---|
docker pull <img> | Pull image |
docker run <img> | Run container |
docker ps | List containers |
docker stop <id> | Stop container |
Keyboard Shortcuts
| Shortcut | Description |
|---|---|
Tab | Auto-complete |
Ctrl+C | Cancel command |
Ctrl+L | Clear screen |
Ctrl+A | Start of line |
Ctrl+E | End of line |
Ctrl+U | Clear to start |
Ctrl+K | Clear to end |
Ctrl+R | Search 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 pageb- Backward one pageg- Go to first lineG- Go to last line/pattern- Search forwardq- 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- Quitk- Kill processM- Sort by memoryP- Sort by CPU
kill - Send Signal to Process
Syntax: kill [options] <pid>
Common Signals:
SIGTERM(15) - Terminate gracefullySIGKILL(9) - Force killSIGHUP(1) - Reload configuration
Examples:
$ kill 1234 # Graceful terminate
$ kill -9 1234 # Force kill
$ kill -HUP 1234 # Reload config
Package Management
Fedora (DNF)
| Command | Description |
|---|---|
sudo dnf search <pkg> | Search for package |
sudo dnf install <pkg> | Install package |
sudo dnf remove <pkg> | Remove package |
sudo dnf update | Update all packages |
sudo dnf upgrade | Upgrade distribution |
sudo dnf list installed | List installed packages |
sudo dnf info <pkg> | Show package info |
sudo dnf repolist | List repositories |
Debian (APT)
| Command | Description |
|---|---|
sudo apt update | Update package lists |
sudo apt upgrade | Upgrade 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 autoremove | Remove 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
| Command | Description |
|---|---|
git init | Initialize new repository |
git clone <url> | Clone existing repository |
git status | Show working tree status |
git add <file> | Stage file for commit |
git add . | Stage all changes |
git commit -m "msg" | Commit staged changes |
git log | Show commit history |
git log --oneline | Concise commit history |
git diff | Show unstaged changes |
git diff --staged | Show staged changes |
git branch | List 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 -v | Show remotes |
git push | Push to remote |
git pull | Pull from remote |
git stash | Stash changes |
git stash pop | Apply stashed changes |
Docker Commands
Basic Docker Commands
| Command | Description |
|---|---|
docker pull <image> | Pull image from registry |
docker run [options] <image> | Run container |
docker ps | List running containers |
docker ps -a | List all containers |
docker stop <container> | Stop container |
docker start <container> | Start stopped container |
docker rm <container> | Remove container |
docker rmi <image> | Remove image |
docker images | List images |
docker exec -it <container> bash | Execute 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:
-
Use
sudofor system operations:sudo touch /etc/test.txt -
Check if you need to own the file:
sudo chown $USER /etc/test.txt -
Check file permissions:
ls -l /etc/test.txt
Command Not Found
"command not found"
Symptom:
$ git
git: command not found
Solutions:
-
Check spelling:
# Common typos cd /hme/user # Wrong cd /home/user # Correct -
Install missing package:
Fedora:
sudo dnf install gitDebian:
sudo apt install git -
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:
-
List current directory contents:
ls -la -
Check your location:
pwd -
Use tab completion to avoid typos:
cd doc<Tab> # Completes to documents/ -
Search for the file:
find ~ -name "documents" -type d
"Directory not empty"
Symptom:
$ rm directory/
rm: cannot remove 'directory/': Is a directory
Solutions:
-
Use recursive remove:
rm -r directory/ -
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:
-
Wait for another package manager to finish
-
Check for running processes:
ps aux | grep apt -
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:
-
Clean metadata cache:
sudo dnf clean all sudo dnf makecache -
Check network connection:
ping -c 3 fedoraproject.org -
Refresh repositories:
sudo dnf refresh
Process Issues
Process won't stop
Symptom: Application freezes and won't close.
Solutions:
-
Find the process ID:
ps aux | grep application_name -
Try graceful termination:
kill <PID> -
Force kill if needed:
kill -9 <PID> -
Kill by name:
pkill application_name killall application_name
Service won't start
Symptom:
$ sudo systemctl start nginx
Job for nginx.service failed.
Solutions:
-
Check service status:
systemctl status nginx -
View service logs:
journalctl -u nginx -n 50 -
Check configuration:
sudo nginx -t # Test nginx config -
Check for port conflicts:
sudo ss -tulpn | grep :80
Network Issues
Cannot connect to WiFi
Solutions:
-
Check network interface:
ip link show -
Bring interface up:
sudo ip link set wlan0 up -
Use NetworkManager (GUI or CLI):
nmcli dev wifi list nmcli dev wifi connect "SSID" password "password" -
Restart network service:
sudo systemctl restart NetworkManager
SSH connection refused
Symptom:
$ ssh user@host
ssh: connect to host port 22: Connection refused
Solutions:
-
Check if SSH server is running:
systemctl status sshd # Fedora systemctl status ssh # Debian -
Start SSH server:
sudo systemctl start sshd sudo systemctl enable sshd -
Check firewall:
sudo firewall-cmd --list-all # Fedora sudo ufw status # Debian -
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:
-
Check disk usage:
df -h -
Find large files:
du -h ~ | sort -hr | head -20 -
Clean package cache:
Fedora:
sudo dnf clean allDebian:
sudo apt clean sudo apt autoremove -
Empty trash:
rm -rf ~/.local/share/Trash/* -
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:
-
Initialize repository:
git init -
Clone existing repository:
git clone <url>
Merge conflicts
Symptom:
$ git merge feature
Auto-merging file.txt
CONFLICT (content): Merge conflict in file.txt
Solutions:
-
Edit the file and resolve conflicts manually
-
Mark as resolved:
git add file.txt git commit -
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:
-
Use sudo:
sudo docker ps -
Add user to docker group:
sudo usermod -aG docker $USER -
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:
-
Container may have no foreground process
-
Use
-dfor detached mode:docker run -d nginx -
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
| Command | Purpose |
|---|---|
journalctl -xb | View boot messages |
dmesg | Kernel ring buffer |
systemctl --failed | List failed services |
strace <command> | Trace system calls |
ltrace <command> | Trace library calls |
tail -f /var/log/syslog | Follow system log |