This commit is contained in:
labzy-handson 2025-09-19 08:28:41 +05:30
parent 6ebc0567f0
commit a522d56305
24 changed files with 2961 additions and 13 deletions

1
LICENSE.md Normal file
View File

@ -0,0 +1 @@
Lab content © 2025 Meyi Cloud Solutions Pvt. Ltd. Licensed under CC BY-NC-ND 4.0.

68
README.md Normal file
View File

@ -0,0 +1,68 @@
# Linux Essentials — Detailed Lab Overview
## Duration
**2 Hours (12 Steps)**
## Audience
This lab is designed for **complete beginners** (equivalent to 10th grade students) who are learning Linux and the terminal for the first time.
No prior Linux knowledge is assumed. Each instruction is step-by-step and written in simple language.
## Lab Format
- **Instruction Lab**: You will be guided through commands and concepts directly.
- **Hands-On Practice**: You will type commands into the terminal and observe outputs.
- **Validation Tasks**: At the end, optional tasks (Git & Networking) include helper files and validation scripts.
## Learning Objectives
By the end of this lab, you will be able to:
1. Open and use the Linux terminal effectively.
2. Navigate the filesystem and perform file operations.
3. View, search, and filter text files.
4. Manage processes and jobs (foreground/background).
5. Understand file permissions and change them with `chmod` and `chown`.
6. Gather system information (disk, memory, uptime).
7. Perform basic networking commands (ping, DNS lookups, open ports).
8. Archive and compress files using `tar` and `gzip`.
9. Use the package manager (`apt`) to install and remove software.
10. Write and run simple shell scripts.
11. Initialize and commit code to a Git repository.
12. Troubleshoot connectivity and DNS resolution.
## Structure
- **Steps 110**: Core Linux skills (approx. 100 minutes).
- **Steps 1112**: Validation tasks with helpers (approx. 20 minutes).
- Each step is **10 minutes** on average, but you may take longer as you practice.
## Requirements
- **Operating System**: Ubuntu 24 (or similar Linux distribution).
- **Tools**: Terminal application (bash shell).
- **Network**: Internet connection for package installation and DNS tests.
- **Permissions**: Some tasks require `sudo` access (administrator rights).
## Key Skills Practiced
- Working with the Linux command line
- Creating and organizing files and directories
- Redirecting and searching text output
- Managing processes and monitoring system usage
- Adjusting permissions for files and directories
- Compressing and archiving data
- Installing/removing software with APT
- Writing and running bash scripts
- Using Git for version control
- Troubleshooting basic networking issues
## Suggested Workflow
1. **Follow each step in order.** Each builds on the previous one.
2. **Type commands manually.** Avoid copy-paste to build muscle memory.
3. **Observe the output carefully.** Compare it with expected results.
4. **Repeat tasks** if something doesnt work — troubleshooting is part of learning.
5. **Try variations** (e.g., different filenames, directories) to deepen your understanding.
## Completion Criteria
- You have successfully completed all 10 instructional steps.
- You optionally attempted Steps 11 and 12 and passed the provided validation scripts.
- You are comfortable using the Linux terminal for basic daily tasks.
---
**Next Steps:**
After completing this lab, you are ready to explore more advanced topics such as user management, shell scripting with conditionals/loops, and networking security.

BIN
docs/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -1 +1,68 @@
# Overview
# Linux Essentials — Detailed Lab Overview
## Duration
**3 Hours (12 Steps)**
## Audience
This lab is designed for **complete beginners** (equivalent to 10th grade students) who are learning Linux and the terminal for the first time.
No prior Linux knowledge is assumed. Each instruction is step-by-step and written in simple language.
## Lab Format
- **Instruction Lab**: You will be guided through commands and concepts directly.
- **Hands-On Practice**: You will type commands into the terminal and observe outputs.
- **Validation Tasks**: At the end, optional tasks (Git & Networking) include helper files and validation scripts.
## Learning Objectives
By the end of this lab, you will be able to:
1. Open and use the Linux terminal effectively.
2. Navigate the filesystem and perform file operations.
3. View, search, and filter text files.
4. Manage processes and jobs (foreground/background).
5. Understand file permissions and change them with `chmod` and `chown`.
6. Gather system information (disk, memory, uptime).
7. Perform basic networking commands (ping, DNS lookups, open ports).
8. Archive and compress files using `tar` and `gzip`.
9. Use the package manager (`apt`) to install and remove software.
10. Write and run simple shell scripts.
11. Permissions Challenge.
12. Troubleshoot connectivity and DNS resolution.
## Structure
- **Steps 110**: Core Linux skills (approx. 200 minutes).
- **Steps 1112**: Validation tasks with helpers (approx. 30 minutes).
- Each step is **10 minutes** on average, but you may take longer as you practice.
## Requirements
- **Operating System**: Ubuntu 24 (or similar Linux distribution).
- **Tools**: Terminal application (bash shell).
- **Network**: Internet connection for package installation and DNS tests.
- **Permissions**: Some tasks require `sudo` access (administrator rights).
## Key Skills Practiced
- Working with the Linux command line
- Creating and organizing files and directories
- Redirecting and searching text output
- Managing processes and monitoring system usage
- Adjusting permissions for files and directories
- Compressing and archiving data
- Installing/removing software with APT
- Writing and running bash scripts
- Using Git for version control
- Troubleshooting basic networking issues
## Suggested Workflow
1. **Follow each step in order.** Each builds on the previous one.
2. **Type commands manually.** Avoid copy-paste to build muscle memory.
3. **Observe the output carefully.** Compare it with expected results.
4. **Repeat tasks** if something doesnt work — troubleshooting is part of learning.
5. **Try variations** (e.g., different filenames, directories) to deepen your understanding.
## Completion Criteria
- You have successfully completed all 10 instructional steps.
- You optionally attempted Steps 11 and 12 and passed the provided validation scripts.
- You are comfortable using the Linux terminal for basic daily tasks.
---
**Next Steps:**
After completing this lab, you are ready to explore more advanced topics such as user management, shell scripting with conditionals/loops, and networking security.

View File

@ -1 +0,0 @@
## Initial task

196
docs/01_terminal_basics.md Normal file
View File

@ -0,0 +1,196 @@
# Step 1 — Terminal Basics (Ubuntu 24)
> **Type along** exactly as shown. This step is written for absolute beginners and assumes no prior Linux experience.
> **Estimated time:** ~1015 minutes
---
## What youll learn
- What the *terminal* and the *shell* are
- How to open and close a terminal
- How to find your current shell and username
- How to run basic commands safely
- How to read the command prompt and use helpful keyboard shortcuts
This expands the original brief step (“Open terminal → echo $SHELL → whoami → exit”) into a guided mini-lesson with checks, expected outputs, and troubleshooting.
---
## Prerequisites
- Ubuntu 24 (or a similar Linux distribution)
- A keyboard and mouse (no admin/sudo needed for this step)
- Willingness to try and make small mistakes (thats normal!)
---
## 1) Open the Terminal
You can open the terminal in **three** easy ways — choose the one you like:
1. Press **Ctrl + Alt + T** (keyboard shortcut).
2. Click **Activities** (top-left) → type `terminal` → click **Terminal**.
3. Open **Applications** menu → **Terminal** (or **GNOME Terminal**).
**Expected view:** A window with a prompt like:
```
yourname@your-computer:~$
```
- `yourname` is your **username** (who you are)
- `your-computer` is the **hostname** (your machines name)
- `~` means your **home** directory (e.g., `/home/yourname`)
- `$` is the standard prompt for regular users (a `#` indicates the root/admin shell — you wont use root here)
> If your prompt looks a bit different, thats okay—Linux allows customization. The ideas are the same.
---
## 2) Meet Your Shell
The **shell** is a program that reads your commands and runs them. In Ubuntu its usually **Bash**.
**Find which shell you are using:**
```bash
echo $SHELL
```
**Expected output (typical):**
```
/bin/bash
```
- `echo` prints text
- `$SHELL` is an **environment variable** that stores the path to your current shell
**Alternative cross-check (nice to know):**
```bash
ps -p $$ -o comm=
```
- Prints the name of the program running your current shell (`bash`, `zsh`, etc.)
> Tip: Commands are **case-sensitive**. `Echo` or `ECHO` wont work; use `echo` in lowercase.
---
## 3) Who Am I? Where Am I?
**Show your login name:**
```bash
whoami
```
**Expected output** (your actual username):
```
yourname
```
**Show your current folder (directory):**
```bash
pwd
```
**Expected output** (your home):
```
/home/yourname
```
> Remember: `~` is a shortcut for your home directory. `cd ~` and `cd` (with no arguments) both take you home.
---
## 4) Try a Few Safe Commands
Type each command and press **Enter**. Dont worry—these are read-only.
```bash
date # shows the current date and time
ls # lists files/folders in the current directory
ls -la # lists everything in long form, including hidden “dotfiles”
clear # clears your screen (or press Ctrl+L)
```
If you want to see *what* a command does:
```bash
man ls # the manual for ls (press q to quit)
ls --help # quick built-in help for ls
help echo # help for bash built-in command "echo"
```
> **How to read errors**: If you see a line like `command not found`, check your spelling and spaces. Linux cares about lowercase vs uppercase.
---
## 5) Keyboard Superpowers (Optional but Very Useful)
- **↑ / ↓**: browse history (commands you already typed)
- **Tab**: auto-complete file/command names (press twice to list options)
- **Ctrl + A**: jump to start of line
- **Ctrl + E**: jump to end of line
- **Ctrl + U**: clear from cursor *back* to start
- **Ctrl + K**: clear from cursor *forward* to end
- **Ctrl + W**: delete the previous word
- **Ctrl + L**: clear screen (same as `clear`)
- **Ctrl + C**: cancel/interrupt a running command (do not use while saving in editors)
**Try it:** Type `ec` then press **Tab** — if `echo` is the only match, your shell completes the word for you.
---
## 6) Practice: Your First Echo
`echo` prints whatever you give it. Try these:
```bash
echo Hello, Linux!
echo "Quoting keeps words together like this: two words"
echo $HOME # prints your home directory path
echo $USER # prints your username (same as whoami)
```
**What happened?**
- Without quotes, the shell splits by spaces
- With quotes `"..."`, the shell treats the content as one unit
- `$` means “expand this variable” (`$HOME`, `$USER`, `$SHELL`, `$PATH` are common ones)
---
## 7) Close the Terminal (Two Safe Ways)
1) Type:
```bash
exit
```
2) Or press **Ctrl + D** (sends “end-of-input”, which ends the shell)
If you had any running programs in the foreground, the shell will usually warn you.
---
## Troubleshooting
**Q: I typed `WhoAmI` and got “command not found.”**
A: Commands are case-sensitive. Type `whoami` (all lowercase).
**Q: I see `Permission denied`.**
A: You tried to access something you dont have rights to. In this step, just practice with safe commands (`echo`, `whoami`, `pwd`).
**Q: My terminal is “stuck.”**
A: A command might still be running. Press **Ctrl + C** to cancel. If that doesnt work, close the terminal window.
**Q: My prompt ends with `#`. Is that bad?**
A: That means youre in a **root** (administrator) shell. Close the terminal and open a new one. For learning, stay as a regular user (`$` prompt).
---
## Quick Quiz (1 minute)
- What does `$SHELL` store?
- How do you show your username?
- What does `~` represent?
- Which key shows your previous command?
- Two ways to exit the terminal?
**Answers** (hover/select to reveal): `$SHELL` is your shell path; `whoami`; `~` = home directory; Up Arrow; `exit` and `Ctrl + D`.
---
## Next Step
Youre ready for **Step 2 — Navigation & File Operations**.
Keep this terminal open; well continue in the same window.

View File

@ -0,0 +1,298 @@
# Step 2 — Navigation & File Operations (Ubuntu 24)
> **Type along** exactly as shown. This step is written for absolute beginners and assumes no prior Linux experience.
> **Estimated time:** ~1015 minutes
---
## What youll learn
- What a *path* is (absolute vs. relative)
- How to **move around** with `cd`
- How to **create**, **inspect**, **copy**, **move/rename**, and **delete** files and folders
- How to work safely (confirmation prompts), and handle names with **spaces**
- How to verify your actions with `ls -l`
This expands the original brief step (pwd → mkdir → cd → create file → ls -l) into a guided mini-lesson with checks, expected outputs, and troubleshooting.
---
## 0) Setup (recommended)
Create a clean practice area so you dont accidentally change other files:
```bash
mkdir -p ~/playground && cd ~/playground
```
- `~` is your **home** directory (e.g., `/home/yourname`).
- `mkdir -p` creates all missing parent folders safely.
- `cd` changes your current working directory.
If something goes wrong, you can reset this folder later:
```bash
cd ~ && rm -rf ~/playground && mkdir -p ~/playground && cd ~/playground
```
---
## 1) Where am I? (Print Working Directory)
```bash
pwd
```
**Expected output:** the full path of your current directory (e.g., `/home/yourname/playground`).
This is called an **absolute path** (it starts with `/`).
---
## 2) Create folders (directories)
Create a single folder:
```bash
mkdir projects
```
Create a **nested** folder tree in one go:
```bash
mkdir -p projects/alpha
```
Verify:
```bash
ls -la
```
- `-l` = long list (permissions, owner, size, date)
- `-a` = include hidden items (names starting with a dot)
> Hidden files often store settings and are called **dotfiles** (e.g., `.bashrc`).
---
## 3) Move around with `cd`
Change into the new folder:
```bash
cd projects
pwd
```
Go **down** another level:
```bash
cd alpha
pwd
```
Go **up** one level:
```bash
cd ..
pwd
```
Jump **home** quickly:
```bash
cd ~
pwd
```
Return to your last directory:
```bash
cd -
```
> Think of `cd` as “change directory” — just like opening folders in a file explorer.
---
## 4) Create files (3 common ways)
Make sure youre inside `~/playground` (use `pwd` to check), then:
**A) Create with content (overwrite if exists):**
```bash
echo "Hello Linux" > hello.txt
```
**B) Append more content (keeps existing lines):**
```bash
echo "Second line" >> hello.txt
```
**C) Create an empty file:**
```bash
touch empty.txt
```
**D) Create and edit with a text editor (nano):**
```bash
nano notes.txt
# Type: My first notes line.
# Save: Ctrl+O, Enter. Exit: Ctrl+X
```
Check what you made:
```bash
ls -l
cat hello.txt
```
> `>` writes/overwrites; `>>` appends. `touch` creates an empty file or updates the timestamp if it already exists.
---
## 5) Inspect details with `ls`
List files with extra info:
```bash
ls -l
```
Youll see lines like:
```
-rw-r--r-- 1 yourname yourname 12 Sep 8 10:00 hello.txt
```
- `-rw-r--r--` → **permissions**
- first `yourname` → **owner**
- second `yourname` → **group**
- `12` → file size in bytes
- `hello.txt` → file name
Try human-readable sizes:
```bash
ls -lh
```
Show hidden files too:
```bash
ls -la
```
---
## 6) Copy, move/rename, and delete files
**Copy a file:**
```bash
cp hello.txt hello.bak
ls -l hello*
```
**Move/rename a file (same command):**
```bash
mv hello.bak projects/alpha/
mv empty.txt empty-renamed.txt
ls -l projects/alpha
ls -l empty-renamed.txt
```
**Delete a file (interactive/safe):**
```bash
rm -i empty-renamed.txt
```
> `-i` asks **“remove regular file…?”** before deleting — excellent for beginners.
**Delete a folder tree (careful!):**
```bash
rm -r projects/alpha
mkdir -p projects/alpha # recreate it for the next step
```
> `rm -r` removes directories **recursively** (everything inside). Use with caution.
---
## 7) Names with spaces
Two safe methods:
**Quotes:**
```bash
mkdir "my notes"
echo "a line" > "my notes/file with space.txt"
ls -l "my notes"
```
**Escaping spaces with backslashes:**
```bash
echo "another line" > my\ notes/another\ file.txt
ls -l my\ notes
```
> If you forget quotes/backslashes, the shell will think youre typing **multiple arguments** and show an error like “No such file or directory”.
---
## 8) Wildcards (globbing)
List all `.txt` files:
```bash
ls -l *.txt
```
List everything that starts with `he`:
```bash
ls -l he*
```
> If a wildcard matches nothing, the shell may pass the literal pattern to the command (e.g., `ls: cannot access '*.txt': No such file or directory`). Thats normal.
---
## 9) Verify what you did (mini-checklist)
- Where are you?
```bash
pwd
```
- Do you see the files you created?
```bash
ls -la
```
- Do you see the content you wrote?
```bash
cat hello.txt
```
- Is there a copy in `projects/alpha/`?
```bash
ls -l projects/alpha
```
---
## 10) Cleanup (optional)
If you want to start fresh:
```bash
cd ~ && rm -rf ~/playground && mkdir -p ~/playground && cd ~/playground
```
---
## Troubleshooting
**Q: `Permission denied` when creating files?**
A: Ensure youre working inside your home (e.g., `~/playground`) where you have write permission.
**Q: `No such file or directory` when using spaces?**
A: Use quotes `"like this"` or escape spaces: `my\ notes/that\ file.txt`.
**Q: I ran `rm -r` in the wrong place!**
A: This is why we practice in `~/playground`. In real life, **double-check** paths before you press Enter.
---
## Quick Quiz (1 minute)
- How do you print the current directory path?
- Whats the difference between `>` and `>>`?
- Which command *renames* a file?
- Show a long listing including hidden files—what options do you use?
- Two ways to handle file names with spaces?
**Answers:** `pwd`; `>` overwrites, `>>` appends; `mv`; `ls -la`; quotes or backslashes.
---
## Next Step
Continue to **Step 3 — Searching & Text Viewing** to learn `grep`, `find`, `less`, and more!

239
docs/03_searching_text.md Normal file
View File

@ -0,0 +1,239 @@
# Step 3 — Searching & Text Viewing (Ubuntu 24)
> **Type along** exactly as shown. This step is written for absolute beginners and assumes no prior Linux experience.
> **Estimated time:** ~1015 minutes
---
## What youll learn
- How to **view** text files (`cat`, `less`, `head`, `tail`)
- How to **search inside** files with `grep`
- How to **find files/folders** anywhere with `find`
- How to chain commands together with the **pipe** (`|`) for quick analysis
- How to avoid common mistakes (case, spaces, patterns)
This expands the original brief step to include **practical variations**, **safety notes**, and **troubleshooting**.
> **Setup:** Continue using your practice area from previous steps (recommended):
> ```bash
> mkdir -p ~/playground && cd ~/playground
> ```
---
## 0) Create some sample files to search
Well set up a few files so your searches have something to find.
```bash
cd ~/playground
echo "Hello Linux" > hello.txt
echo "hello again" >> hello.txt
echo "Linux is powerful" > notes.txt
echo "HELLO CAPS" > caps.txt
mkdir -p logs
printf "alpha\nbeta\ngamma\nBeta\nGamma\n" > logs/mixed.txt
```
Verify:
```bash
ls -l
ls -l logs
```
---
## 1) View files quickly (`cat`) and with scrolling (`less`)
**A) View entire file now:**
```bash
cat hello.txt
```
- `cat` prints the file to your screen immediately (great for short files).
**B) Scroll through long files:**
```bash
less notes.txt
```
- **Keys:** Up/Down or PageUp/PageDown to move; `/word` to search; `n` for next match; `q` to quit.
- `less` doesnt load the whole file at once — its ideal for big files and logfiles.
**C) Peek at the top/bottom only (useful for logs):**
```bash
head -n 3 hello.txt # first 3 lines
tail -n 3 hello.txt # last 3 lines
tail -f hello.txt # follow new lines live; press Ctrl+C to stop
```
> **Tip:** Use `tail -f` while another process writes to a log to watch updates in real time.
---
## 2) Search inside files with `grep`
`grep` finds lines **containing** a pattern.
**A) Basic search (case-sensitive by default):**
```bash
grep "Hello" hello.txt
```
- Matches `Hello` but **not** `hello`.
**B) Case-insensitive search:**
```bash
grep -i "hello" hello.txt
```
**C) Show line numbers with matches:**
```bash
grep -n "hello" hello.txt
```
**D) Search multiple files at once:**
```bash
grep -n "linux" *.txt
```
- Matches lines containing `linux` in any `.txt` file (case-sensitive).
**E) Recursive search (search through folders):**
```bash
grep -Rni "beta" .
```
- `-R` = recursive, `-n` = show line numbers, `-i` = ignore case
**F) Show only the filenames that match:**
```bash
grep -Rl "hello" .
```
**G) Regex (advanced but useful):**
Match `Hello` or `HELLO` or `hello` without `-i`, using an **extended** regex:
```bash
grep -En "(?i)hello" *.txt 2>/dev/null || grep -En "(H|h)ELLO|Hello|hello" *.txt 2>/dev/null
```
> Note: The `(?i)` flag is not supported in all `grep` versions; the fallback demonstrates alternation with `-E`. Beginners can skip this for now.
**H) Invert match (show lines that **do not** match):**
```bash
grep -v "hello" hello.txt
```
---
## 3) Find files/folders anywhere with `find`
`find` walks directories and lets you filter by **name**, **type**, **size**, **time**, and more.
**A) Find by name:**
```bash
find . -name "hello.txt"
find . -name "*.txt"
```
**B) Only files vs. only directories:**
```bash
find . -type f -name "*.txt"
find . -type d -name "logs"
```
**C) Limit depth to current folder only:**
```bash
find . -maxdepth 1 -type f -name "*.txt"
```
**D) Find by size (files larger than 1 megabyte):**
```bash
find . -type f -size +1M
```
**E) Find by modified time (edited within last 1 day):**
```bash
find . -type f -mtime -1
```
**F) Do something with each result (`-exec`):**
Show file sizes for all `.txt` files:
```bash
find . -type f -name "*.txt" -exec wc -l {} \;
```
> `wc -l` counts lines; `{}` is replaced by each found file; `\;` ends the `-exec` command.
**G) Safer piping with null terminators (handles spaces in filenames):**
```bash
find . -type f -name "*.txt" -print0 | xargs -0 grep -n "hello"
```
- This combination searches **all** `.txt` files for `hello`, even if filenames contain spaces.
---
## 4) Combine tools with the pipe `|`
**A) Quick counts (how many matches?):**
```bash
grep -Rni "hello" . | wc -l
```
- `wc -l` counts how many **matching lines** were found.
**B) Sort and unique (e.g., see unique matching filenames):**
```bash
grep -Rl "hello" . | sort | uniq
```
**C) Show the 5 most common words in a file (simple demo):**
```bash
tr -cs '[:alnum:]' '\n' < hello.txt | tr '[:upper:]' '[:lower:]' | sort | uniq -c | sort -nr | head -n 5
```
- Splits text into words, lowercases, counts, and shows top 5.
> **Note:** The above is a mini data-processing pipeline — not required for beginners but fun to see whats possible.
---
## 5) Practice tasks (do them now)
1) Show the **first** 2 lines of `logs/mixed.txt`.
2) Show only the lines that contain “Gamma” (any case) in `logs/mixed.txt`.
3) Find all `.txt` files **in this folder only** (not subfolders).
4) Count how many lines in **all** `.txt` files mention “hello” (any case).
5) Show the **filenames only** that contain the word “Linux” (case-insensitive) anywhere under the current folder.
**Hints:**
```bash
head -n 2 logs/mixed.txt
grep -i "gamma" logs/mixed.txt
find . -maxdepth 1 -type f -name "*.txt"
grep -Rni "hello" . | wc -l
grep -Rli "linux" .
```
---
## Troubleshooting
**Q: `grep: *.txt: No such file or directory`**
A: Wildcards expand before grep runs. If nothing matches `*.txt`, your shell might pass the literal string. Make sure youre in the right folder and that `.txt` files exist.
**Q: My search is case-sensitive, but I need any case.**
A: Add `-i` to `grep` (e.g., `grep -i "hello"`).
**Q: `find` prints “Permission denied”.**
A: Youre walking directories you dont own (outside your home). For practice, stay inside `~/playground`.
**Q: `less` wont quit.**
A: Press `q` to exit `less`.
---
## Quick Quiz (1 minute)
- Which command opens a scrollable viewer?
- How do you search recursively and ignore case with `grep`?
- How do you show only filenames that match?
- Which `find` option restricts search to current directory only?
- What does `wc -l` do when piped after `grep`?
**Answers:** `less`; `grep -Rni "term" .`; `grep -Rl "term" .`; `-maxdepth 1`; counts matching lines.
---
## Next Step
Continue to **Step 4 — Process Management** to learn how to view, sort, and control running programs.

View File

@ -0,0 +1,215 @@
# Step 4 — Process Management (Ubuntu 24)
> **Type along** exactly as shown. This step is written for absolute beginners and assumes no prior Linux experience.
> **Estimated time:** ~1015 minutes
---
## What youll learn
- What a **process** is and how to list them
- How to watch the system in real time with **top**
- How to start programs in the **background** and bring them to the **foreground**
- How to **stop/kill** a process safely
- How to view **PIDs** (Process IDs) and understand **signals**
- (Optional) How to adjust priority with **nice/renice**
This expands the original brief step (ps/top/background jobs/kill) into a guided mini-lesson with checks, expected outputs, and troubleshooting.
> **Setup:** Continue using your practice area from previous steps (recommended):
> ```bash
> mkdir -p ~/playground && cd ~/playground
> ```
---
## 0) Whats a “process”?
A **process** is a running program (like the terminal, a text editor, a web browser tab, or a background task).
Linux gives every process a unique number called a **PID** (Process ID). You use the PID to control the process (e.g., to stop it).
---
## 1) List processes with `ps`
Show the first few running processes (system-wide view):
```bash
ps aux | head -n 15
```
- `a` = show processes for **all** users
- `u` = show the user/owner
- `x` = include processes without a controlling terminal
**More readable columns (top 10 by PID):**
```bash
ps -o pid,ppid,user,%cpu,%mem,stat,cmd --sort=pid | head -n 10
```
- `pid` = Process ID
- `ppid` = Parent Process ID
- `%cpu`, `%mem` = CPU and memory usage
- `stat` = state (e.g., `S` sleeping, `R` running, `T` stopped)
- `cmd` = the command used to start the process
---
## 2) Real-time view with `top`
Open an updating view of processes:
```bash
top
```
**Keys you can try inside `top`:**
- `P` = sort by CPU
- `M` = sort by memory
- `1` = show all CPU cores
- `q` = quit
> Optional: Install **htop** (`sudo apt install -y htop`) for a friendlier view. Launch with `htop`, quit with `q`.
---
## 3) Create a background process and manage jobs
Start a harmless background job:
```bash
sleep 300 &
```
- `sleep 300` waits for 300 seconds (5 minutes). The `&` runs it **in the background** so you get your prompt back.
List your jobs:
```bash
jobs
```
Bring the job to the **foreground** (if theres one job, its usually `%1`):
```bash
fg %1
```
Now your terminal is “busy” waiting for `sleep` to finish. Press **Ctrl + C** to stop it.
Start it again in the background and **suspend**, **resume** flow:
```bash
sleep 300 & # start in background
jobs
fg %1 # bring to foreground
# Press Ctrl+Z # suspend the foreground job
bg %1 # resume it in the background
jobs
```
> **Ctrl+Z** = “pause” the foreground process.
> **bg** = continue a paused job in the background.
> **fg** = bring a background job to the foreground.
---
## 4) Find PIDs and kill a process safely
Create a background process to practice on:
```bash
sleep 400 &
```
Find its PID(s):
```bash
pgrep sleep
```
Youll see one or more numbers (PIDs).
**Ask a process to exit nicely (SIGTERM 15):**
```bash
kill 15 <PID>
```
If it doesnt exit after a few seconds, you can **force** it (SIGKILL 9):
```bash
kill -9 <PID>
```
> Use `-9` only if normal signals fail; it doesnt let programs clean up.
**Alternative: kill by name (use carefully):**
```bash
pkill sleep # stops all 'sleep' processes you own
# or
killall sleep
```
Confirm its gone:
```bash
pgrep sleep || echo "No sleep process found"
```
---
## 5) (Optional) Priority: nice and renice
Every process has a **priority** (niceness). Higher nice values (e.g., `+10`) = **lower** priority (more “polite”).
Lower nice values (e.g., `-5`) = **higher** priority (less “polite”). Negative values may require `sudo`.
Start a nice process:
```bash
nice -n 10 sleep 200 &
```
Check niceness (NI column):
```bash
ps -o pid,ni,cmd -p $(pgrep -n sleep)
```
Change niceness of a running process to be **more polite** (higher number):
```bash
renice +15 -p <PID>
ps -o pid,ni,cmd -p <PID>
```
> To set a **negative** niceness (higher priority), you typically need `sudo`.
Stop leftover sleep processes:
```bash
pkill sleep
```
---
## 6) Practice tasks (do them now)
1) Start `sleep 180 &`. Then show your jobs, bring it to the foreground, suspend it, and resume it in the background.
2) Use `pgrep sleep` to find the PID and then terminate the process **politely**. Verify its gone.
3) Launch a “polite” (low-priority) task with `nice` and confirm the NI column shows the expected value.
4) Open `top`, press `P` to sort by CPU and `M` to sort by memory. Quit `top`.
**Hints:**
```bash
sleep 180 &; jobs; fg %1; # then Ctrl+Z
bg %1; jobs
pgrep sleep; kill 15 <PID>; pgrep sleep || echo "done"
nice -n 10 sleep 120 &; ps -o pid,ni,cmd -p $(pgrep -n sleep)
top # then P, M, q
```
---
## Troubleshooting
**Q: I lost my job number. How do I get the PID?**
A: Use `pgrep <name>` (e.g., `pgrep sleep`). Then use `kill` with the PID.
**Q: `kill` didnt stop the process.**
A: Try `kill 15 <PID>` again, wait a moment, then `kill -9 <PID>` as a last resort.
**Q: I see “Operation not permitted” with `renice`.**
A: Negative nice values (higher priority) generally require `sudo`. Increasing the niceness (e.g., `+10`, `+15`) is allowed.
**Q: `top` wont exit.**
A: Press `q` to quit `top`.
---
## Quick Quiz (1 minute)
- What command shows an updating, real-time view of processes?
- Which key in `top` sorts by CPU usage?
- How do you start a command in the background?
- How do you bring job `%1` to the foreground?
- Whats the difference between `kill 15 <PID>` and `kill -9 <PID>`?
**Answers:** `top`; `P`; add `&` at the end; `fg %1`; `15` asks nicely, `-9` forces.
---
## Next Step
Continue to **Step 5 — Permissions & Ownership** to learn how to read and change file permissions and ownership safely.

265
docs/05_permissions.md Normal file
View File

@ -0,0 +1,265 @@
# Step 5 — Permissions & Ownership (Ubuntu 24)
> **Type along** exactly as shown. This step is written for absolute beginners and assumes no prior Linux experience.
> **Estimated time:** ~1015 minutes
---
## What youll learn
- How to **read** Linux permissions and ownership
- How to **change** permissions with `chmod` (symbolic & octal)
- How to change **owner** and **group** with `chown` / `chgrp`
- How **directory** permissions differ from **file** permissions
- How **umask** affects default permissions
- (Optional) What **setuid**, **setgid**, and **sticky** bits do
- (Optional) How to use **ACLs** for finegrained access
> **Setup:** Continue using your practice area (recommended):
> ```bash
> mkdir -p ~/playground && cd ~/playground
> ```
---
## 0) Primer: Users, Groups, and the `rwx` model
Linux tracks access for three classes:
- **u** (user/owner) — typically who created the file
- **g** (group) — collaborators who share a group
- **o** (others) — everyone else
Each class can have:
- **r** (read)
- **w** (write)
- **x** (execute for files / *enter* for directories)
**Example:**
```
-rw-r----- 1 alice devs 42 Sep 8 12:00 notes.txt
```
- Leading `-` = regular **file** (use `d` for directory)
- `rw-` (user), `r--` (group), `---` (others)
- Owner = `alice`, Group = `devs`
> **Tip:** For **directories**, `x` means you can *enter* the directory and access filenames inside. Without `x`, even if you have `r`, you can list names but may not open files.
---
## 1) View permissions & ownership
Create a couple of files and a directory:
```bash
printf 'hello\n' > hello.txt
printf '#!/usr/bin/env bash\necho hi\n' > hello.sh
mkdir project
```
Show long listing:
```bash
ls -l hello.txt hello.sh project
```
Show numeric (octal) permissions and type:
```bash
stat -c '%A %a %U:%G %n' hello.txt hello.sh project
```
See your user and groups:
```bash
id
# or
groups
```
**Expected:** Youll see owner = your username, group = your primary group, and default perms (e.g., `644` for files, `755` for new directories on many systems).
---
## 2) Change permissions with `chmod`
`chmod` can use **symbolic** or **octal** modes.
### A) Symbolic mode
Add **execute** for owner on the script, remove execute for others:
```bash
chmod u+x,o-x hello.sh
ls -l hello.sh
```
Set **exact** bits (owner `rw`, group `r`, others `-`):
```bash
chmod u=rw,g=r,o= hello.txt
ls -l hello.txt
```
Give **group** write on directory for collaboration:
```bash
chmod g+w project
ls -ld project
```
### B) Octal mode
- `r=4`, `w=2`, `x=1` → Sum them per class: `u g o`
Make a common script mode `755` (rwx r-x r-x):
```bash
chmod 755 hello.sh
stat -c '%A %a %n' hello.sh
```
Set a private file `600` (rw- --- ---):
```bash
chmod 600 hello.txt
stat -c '%A %a %n' hello.txt
```
### C) Recurse (be careful!)
Apply to all items beneath a directory:
```bash
mkdir -p project/sub
touch project/sub/todo.txt
chmod -R g+rw project
```
> **Warning:** Recursive changes can break apps. Prefer targeted changes.
---
## 3) Ownership: `chown` and `chgrp`
Ownership is stored as **user:group**.
Change owner (requires privileges if not your own):
```bash
# Example only; may require sudo depending on target user
sudo chown $USER:$USER hello.txt
```
Change **group** when collaborating:
```bash
# switch group ownership to e.g. `devs` (must be a group youre in)
sudo chgrp devs project || echo "Try a group you belong to"
ls -ld project
```
Change owner:group recursively (careful):
```bash
# Example change group across a tree
sudo chown -R :devs project
```
> **Rule of thumb:** Use `chgrp` to hand a folder to a **team group**, then use directory permissions to control access.
---
## 4) Executable scripts: shebang & run
Make sure the script starts with a **shebang** line and is executable:
```bash
head -n1 hello.sh
chmod u+x hello.sh
./hello.sh
```
If you see `Permission denied`, check `ls -l hello.sh` and ensure the containing directory has `x`.
---
## 5) Defaults with `umask`
`umask` subtracts permissions from new files/directories.
Show current umask:
```bash
umask
```
Make a new file/dir and check modes:
```bash
printf 'tmp\n' > new.txt
mkdir newdir
stat -c '%a %n' new.txt newdir
```
Temporarily set a stricter umask for this shell (e.g., disallow “others”):
```bash
umask 007
printf 'secret\n' > secret.txt
stat -c '%a %n' secret.txt
```
> **Typical defaults:** Files start from `666` (rw rw rw) and directories from `777` (rwx rwx rwx), then your `umask` removes bits.
---
## 6) Special bits (advanced)
### setuid (`4xxx` on files)
- Executed with the file **owners** privileges.
- Common on system tools like `passwd`.
> **Dont set setuid on your own scripts**; its risky and often ignored for scripts.
### setgid (`2xxx` on files/dirs)
- On **directories**, new files inherit the directorys **group**, improving collaboration.
Enable setgid on a shared project folder:
```bash
sudo chgrp devs project
sudo chmod g+ws project # the 's' shows setgid on the group bit
ls -ld project
```
New files in `project/` will have group `devs` automatically.
### sticky bit (`1xxx` on dirs)
- On directories like `/tmp`, users can only delete **their own** files even if the dir is world-writable.
Add sticky to a shared drop folder:
```bash
mkdir -p shared_drop
chmod 1777 shared_drop
ls -ld shared_drop
```
---
## 7) ACLs (Access Control Lists) — optional
ACLs allow peruser or pergroup overrides beyond the basic `u/g/o` model.
Inspect ACLs:
```bash
getfacl hello.txt || echo "Install acl package if missing"
```
Grant **alice** read/write:
```bash
setfacl -m u:alice:rw hello.txt
getfacl hello.txt | sed -n '1,20p'
```
Set a **default ACL** on a directory (applies to new files):
```bash
setfacl -m d:u:alice:rwx project
getfacl project | sed -n '1,50p'
```
Remove an entry or clear all:
```bash
setfacl -x u:alice hello.txt
setfacl -b hello.txt # wipe all ACLs
```
> **Note:** On Ubuntu, ACL support is usually enabled by default. If commands are missing: `sudo apt update && sudo apt install -y acl`.
---
## 8) Practice tasks (do these now)
1) Make `hello.sh` executable for **owner only**, and run it.
*Hint:* `chmod 700 hello.sh`
2) Make `hello.txt` readable by **group**, but **no access** for others. Verify with `stat`.
3) Create `project/docs/` and ensure the **group** keeps inheriting on new files.
*Hint:* `chmod g+ws project` and set group ownership.
4) Create a shared `shared_drop/` so **anyone** can write but only delete their own files.
*Hint:* `chmod 1777 shared_drop`
5) (Optional) Give a specific teammate **rw** on `hello.txt` using **ACLs**, then remove it.
---
## Troubleshooting
- **Permission denied**: Check both the **file** and its **directory** for execute (`x`) where needed.
- **Operation not permitted**: Ownership changes or privileged bits may require `sudo`.
- **Script wont run**: Ensure `#!/usr/bin/env bash` shebang and `chmod +x`. Also check the mount isnt `noexec`.
- **Group changes dont “stick”**: Use **setgid** on the directory and correct group ownership.
- **ACLs ignored?** Ensure filesystem supports ACLs and the tools are installed.
---
## Quick Quiz (1 minute)
- What does the **x** bit mean on a **directory**?
- Translate `-rwxr-x---` to octal.
- Which command changes just the **group** of a file?
- What does **setgid** on a directory do?
- How does `umask` affect new files?
**Answers:** enter/traverse; `750`; `chgrp`; new files inherit the directorys group; it subtracts bits from default perms.
---
## Next Step
Continue to **Step 6 — System Info & Monitoring** to learn how to inspect CPU, memory, disk, and logs effectively.

269
docs/06_system_info.md Normal file
View File

@ -0,0 +1,269 @@
# Step 6 — System Info & Monitoring (Ubuntu 24)
> **Type along** exactly as shown. Safe to run on your machine; nothing here makes persistent config changes (a few optional installs use `apt`).
> **Estimated time:** ~1520 minutes
---
## What youll learn
- Identify OS, kernel, uptime, and hardware at a glance
- Inspect **CPU**, **memory**, **disks/partitions**, and **network**
- Watch processes and system load with `top`/`htop`, `ps`, and `vmstat`
- Check running **services** with `systemd` (`systemctl`) and view **logs** (`journalctl`)
- Measure disk/CPU/IO hot spots with `iostat`, `pidstat`, `iotop`
- Run a quick “health sweep” to triage performance issues
> **Setup:** Use your lab folder:
> ```bash
> mkdir -p ~/playground && cd ~/playground
> ```
---
## 0) Snapshot: who, what, where
Start with the fastest highlevel checks.
```bash
whoami
hostnamectl # hostname, OS, kernel
uname -rsm # kernel: release + machine arch
cat /etc/os-release # distro details
uptime -p # human-friendly uptime
uptime # load averages (1/5/15 min)
date # current time (TZ matters!)
```
> **Load average rule of thumb:** On a 4core machine, a 1minute load of ~4 means “fully busy”; much higher means queued work.
---
## 1) CPU & memory
### CPU facts
```bash
lscpu # sockets, cores, threads, flags
nproc # logical CPU count
cat /proc/cpuinfo | grep -m1 'model name'
```
### Memory / swap
```bash
free -h # Mem/Swap usage (human units)
vmstat -s | head -20 # memory counters summary
swapon --show # active swap areas
cat /proc/meminfo | sed -n '1,10p'
```
> **Tip:** High `si/so` (swapin/out) in `vmstat 1` output usually correlates with memory pressure.
---
## 2) Processes, load, and scheduling
### `top` basics (builtin)
```bash
top
```
Useful keys inside **top**:
- `1`: show perCPU cores
- `M`: sort by memory; `P`: sort by CPU; `T`: by time
- `k`: kill a process (enter PID, then signal like `15`)
- `Shift+E`: change units (KiB/MiB)
- `q`: quit
### `htop` (nicer UI)
```bash
sudo apt update && sudo apt install -y htop
htop
```
### Point-in-time listings with `ps`
```bash
ps aux --sort=-%cpu | head -15
ps aux --sort=-%mem | head -15
pstree -a | head -40 || echo 'Install: sudo apt install -y psmisc'
```
### Niceness & signals (be careful)
```bash
nice -n 10 sleep 60 & # start lower priority
pid=$!
renice +5 -p "$pid" # increase niceness (lower priority)
kill -15 "$pid" # graceful
# kill -9 "$pid" # last resort (commented)
```
---
## 3) Disks, partitions, and filesystem usage
### Layout & mounts
```bash
lsblk -f # devices, filesystems, labels
mount | column -t | head -20
findmnt -t ext4,xfs # mounted FS by type
```
### Space usage
```bash
df -hT # size, used, type per mount
# top 20 heavy dirs under /
sudo du -xh / | sort -h | tail -20
# top 10 heavy dirs under /var (faster)
sudo du -h -d1 /var | sort -h | tail -10
# inode pressure
df -i
```
> **When a disk looks full but `df -h` shows space free:** check **inodes** with `df -i`. Lots of tiny files can exhaust inodes.
### Disk performance (optional)
```bash
sudo apt install -y sysstat iotop
# per-disk stats, queue, utilization
iostat -xz 1 3
# per-process IO (press 'o' to filter active)
sudo iotop -oPa
```
---
## 4) Network quick checks
```bash
ip -br a # brief addresses
ip r # routing table
hostname -I # IPs only
resolvectl status | sed -n '1,40p' # DNS view
```
Listening ports and sockets:
```bash
ss -tulpn | head -30 # TCP/UDP listeners with PIDs
ss -s # socket summary
```
Connectivity basics:
```bash
ping -c 3 8.8.8.8
ping -c 3 google.com
sudo apt install -y mtr-tiny dnsutils
mtr -rwbzc 50 google.com # quick route quality report
dig +short google.com
curl -I https://example.com
```
> **If DNS is flaky:** try `dig @1.1.1.1 example.com` to bypass local resolvers.
---
## 5) Services with systemd
List running services and check status:
```bash
systemctl list-units --type=service --state=running | head -30
systemctl status ssh
systemctl is-enabled ssh
```
Restart a service (requires sudo):
```bash
sudo systemctl restart ssh
```
See boot performance & failures:
```bash
systemd-analyze time
systemd-analyze blame | head -20
systemctl --failed
```
---
## 6) Logs: journald and friends
Live/system logs:
```bash
journalctl -n 200 --no-pager # last 200 lines
journalctl -f # follow
journalctl -p warning --since '1 hour ago'
```
Service-specific logs:
```bash
journalctl -u ssh --since 'today' --no-pager
```
Kernel messages and last boot:
```bash
journalctl -k --since '1 hour ago'
journalctl -b -1 --no-pager # previous boot
```
Legacy file logs (some distros still write to these):
```bash
sudo tail -n 200 /var/log/syslog
sudo grep -i 'oom' /var/log/kern.log || true
```
> **Tip:** Use `-g PATTERN` to grep inside `journalctl`, e.g., `journalctl -g "Out of memory" -k`.
---
## 7) Resource pressure signals (advanced but handy)
Linux exposes PSI (Pressure Stall Information):
```bash
cat /proc/pressure/{cpu,io,memory}
```
If you see sustained **some**/**full** memory or IO pressure, correlate with `iostat`, `vmstat`, and logs (possible OOMs or slow disks).
OOM killer evidence:
```bash
journalctl -k -g 'Out of memory' --since '1 day ago'
dmesg -T | grep -i 'killed process' | tail -n 10
```
---
## 8) Quick health sweep (copy/paste)
Run this as a oneshot collection for triage (prints to screen):
```bash
{ echo '=== SNAPSHOT ===';
date; hostnamectl | sed -n '1,8p'; uname -rsm; uptime; echo;
echo '=== CPU/MEM ==='; lscpu | sed -n '1,8p'; free -h; vmstat 1 3; echo;
echo '=== DISK ==='; df -hT; iostat -xz 1 2 2>/dev/null || true; echo;
echo '=== TOP PROCS ==='; ps aux --sort=-%cpu | head -10; ps aux --sort=-%mem | head -10; echo;
echo '=== NET ==='; ip -br a; ss -tulpn | head -20; echo;
echo '=== SERVICES ==='; systemctl --failed || true; systemd-analyze time || true; echo;
echo '=== LOGS (last 50) ==='; journalctl -n 50 --no-pager;
} | sed 's/\x1b\[[0-9;]*m//g'
```
> **Note:** Some parts need packages (`sysstat`) or privileges; missing tools will be gracefully skipped.
---
## 9) Practice tasks (do these now)
1) Find your CPU core/thread count and current load.
*Hint:* `lscpu`, `uptime`, `top` (`1` key).
2) Identify the **top 5** memoryhungry processes and the **top 5** CPUhungry processes.
*Hint:* `ps aux --sort=-%mem` / `--sort=-%cpu`.
3) Determine which directory under `/var` consumes the most space.
*Hint:* `sudo du -h -d1 /var | sort -h | tail -5`.
4) List all listening TCP sockets with owning PIDs.
*Hint:* `ss -tulpn`.
5) Check logs for **ssh** in the last hour and restart the service.
*Hint:* `journalctl -u ssh --since '1 hour ago'`, then `sudo systemctl restart ssh`.
6) (Optional) Install `sysstat` and run `iostat -xz 1 3`; identify any device >90% util.
---
## 10) Troubleshooting quick guide
- **High load avg with low CPU** → usually **IO wait** or many blocked procs. Check `iostat -xz`, `ps` with `STAT` column (`D` = uninterruptible IO sleep).
- **Memory spikes / OOM** → check `journalctl -k -g 'Out of memory'`, watch `free -h`, consider which process grew via `ps --sort=-rss`.
- **Disk full** → use `df -hT`; then `du` to find culprits; also check **inodes** (`df -i`).
- **Service down**`systemctl status <svc>` then `_journalctl -u <svc>_` to see the why; look for ExecStart errors, missing ports.
- **No DNS resolution**`resolvectl status`, try `dig @1.1.1.1 example.com`; if that works, local resolver is suspect.
- **Network seems fine but web fails** → check outbound firewall/proxy, test raw IP `curl -I http://1.1.1.1`.
---
## 11) Quick quiz (1 minute)
- What do the **three** numbers in `uptime` represent?
- Which tool shows **perdisk** queue and utilization quickly?
- How do you list services that **failed** on boot?
- One command to show **listening** sockets with PIDs?
- Where do you look for **OOM killer** events?
**Answers:** 1/5/15min load avgs; `iostat -xz`; `systemctl --failed`; `ss -tulpn`; `journalctl -k -g 'Out of memory'` (or `dmesg`).
---
## Next Step
Proceed to **Step 7 — Users & Authentication** to manage local users, groups, passwords, and SSH hardening.

252
docs/07_networking.md Normal file
View File

@ -0,0 +1,252 @@
# Step 7 — Networking Basics (Ubuntu 24)
> **Type along** exactly as shown. These are safe, readmostly commands. Optional tools will prompt for `sudo apt install`.
> **Estimated time:** ~2025 minutes
---
## What youll learn
- Read your **IP configuration**, MAC, and default route
- Test connectivity at each layer: **link → IP → DNS → TCP/UDP → app**
- Inspect **listening ports** and active connections with `ss`
- Use **DNS tools** (`resolvectl`, `dig`) effectively
- Trace paths and check packet loss with **`mtr`/`traceroute`**
- Do quick HTTP checks with **`curl`** and simple servers (Python, `nc`)
- (Optional) Basics of **firewall** (`ufw`) and **packet capture** (`tcpdump`)
> **Setup:** Use your lab folder:
> ```bash
> mkdir -p ~/playground && cd ~/playground
> ```
---
## 0) A quick model: test from low → high
1) **Link up?** (interface present, carrier)
2) **IP/route OK?** (address/gateway)
3) **DNS OK?** (names resolve)
4) **Transport OK?** (TCP/UDP reach port)
5) **App OK?** (HTTP responds, SSH banner, etc.)
Youll follow this order every time; it prevents wild goose chases.
---
## 1) Interfaces & addresses
### See links and addresses
```bash
ip -br link # link names + state (brief)
ip -br a # addresses (IPv4/IPv6) per interface
hostname -I # IPs only (no names)
```
Show details for your primary interface (replace `eth0`/`ens3`/`enp0s3` with yours):
```bash
ip addr show enp0s3 | sed -n '1,30p'
```
### MAC address & media info (optional)
```bash
sudo apt update && sudo apt install -y ethtool
sudo ethtool -P enp0s3 # permanent MAC
sudo ethtool enp0s3 | sed -n '1,25p' # speed/duplex/link
```
> **Tip:** Interface names vary across platforms (e.g., `wlp3s0` for WiFi). Use `ip -br link` to discover yours.
---
## 2) Routing: where packets go
Show routes and default gateway:
```bash
ip route
ip r get 8.8.8.8 # which interface/gateway would handle this dest?
```
See neighbors/ARP cache:
```bash
ip neigh | head -10
```
> **Rule of thumb:** If `ip r get 8.8.8.8` errors or returns the wrong interface, your default route or subnet mask is wrong.
---
## 3) How you got an IP: DHCP or static (readonly)
### On servers (systemdnetworkd)
```bash
networkctl
networkctl status -a | sed -n '1,80p'
```
### On desktops (NetworkManager)
```bash
nmcli device status
nmcli device show enp0s3 | sed -n '1,80p'
```
View netplan config (do **not** edit during the lab):
```bash
sudo ls /etc/netplan/
sudo sed -n '1,120p' /etc/netplan/*.yaml 2>/dev/null || true
```
---
## 4) Connectivity tests
### Ping (ICMP)
```bash
ping -c 3 1.1.1.1 # raw IP tests routing only
ping -c 3 google.com # adds DNS to the chain
ping -6 -c 3 google.com # IPv6, if available
```
If ping to hostname fails but IP works, its a **DNS** issue, not routing.
### Trace the path (prefer `mtr`)
```bash
sudo apt install -y mtr-tiny
mtr -rwbzc 50 8.8.8.8 # summarize 50 pings across the route
mtr -rwbzc 50 google.com # includes DNS + any CDN hops
```
---
## 5) Name resolution like a pro
### System view (resolvectl)
```bash
resolvectl status | sed -n '1,80p'
resolvectl query example.com
```
### Query types with `dig`
```bash
sudo apt install -y dnsutils
# A/AAAA
dig +short A example.com
dig +short AAAA example.com
# MX/NS/CNAME
dig +short MX example.com
dig +short NS example.com
# Bypass local DNS to test upstream directly
dig @1.1.1.1 +short A example.com
```
Hosts database (rare but handy):
```bash
getent hosts localhost example.com | sed -n '1,10p'
```
---
## 6) Sockets & ports: whos listening?
List listeners by protocol with owning PIDs:
```bash
ss -tulpn | head -30 # TCP/UDP listeners
ss -s # socket summary
```
Filter for a specific port/service:
```bash
ss -tlpn 'sport = :22' # who owns TCP port 22
```
### Mini lab: create a test port and connect
Start a listener (background):
```bash
nc -lv 127.0.0.1 9000 & echo $! > /tmp/nc9000.pid
sleep 1
ss -tlpn 'sport = :9000'
```
Connect to it:
```bash
printf 'hello from client\n' | nc -v 127.0.0.1 9000
```
Clean up:
```bash
kill "$(cat /tmp/nc9000.pid)" 2>/dev/null || true
rm -f /tmp/nc9000.pid
```
> **Why this matters:** When an app “wont start,” check whether the port is already taken (`ss -tulpn`).
---
## 7) Quick HTTP checks
Spin up a tiny web server (Python 3s stdlib):
```bash
python3 -m http.server 8080 --bind 127.0.0.1 & echo $! > /tmp/http8080.pid
sleep 1
ss -tlpn 'sport = :8080'
```
Probe it with `curl`:
```bash
curl -I http://127.0.0.1:8080/
```
Stop the server:
```bash
kill "$(cat /tmp/http8080.pid)" 2>/dev/null || true
rm -f /tmp/http8080.pid
```
> **TLS tip:** To inspect certificates/handshakes: `openssl s_client -connect example.com:443 -servername example.com -brief`.
---
## 8) Firewalls (optional, lab VM only)
Ubuntu ships **UFW** as a frontend to `nftables`.
```bash
sudo ufw status verbose
```
Allow a temporary lab port and verify:
```bash
sudo ufw allow 8080/tcp
sudo ufw status numbered
ss -tlpn 'sport = :8080'
# cleanup
sudo ufw delete allow 8080/tcp
```
> **Caution:** Dont enable/alter firewalls on production hosts without change control. In the lab its fine.
---
## 9) Packet capture (optional but powerful)
```bash
sudo apt install -y tcpdump
# watch ICMP for a few packets
sudo tcpdump -n -c 5 icmp
# capture just port 8080 traffic (run while your test server is up)
sudo tcpdump -n -i any 'tcp port 8080' -c 10
```
> **Privacy note:** Packet captures can include sensitive data. Only capture on systems and networks you own or have permission to test.
---
## 10) Common gotchas & fixes
- **No network**: `ip -br link` shows `DOWN``sudo ip link set enp0s3 up` (or ensure VM NIC attached).
- **Can ping IP but not hostname**: DNS issue → `resolvectl status`, `dig @1.1.1.1 example.com`.
- **Service wont bind**: Port already in use → `ss -tulpn | grep :PORT`, stop the conflicting process.
- **Intermittent timeouts**: Check path with `mtr`; look for loss on the last 23 hops; also check host load (`top`) and disk (`iostat -xz`).
- **Works locally, not remotely**: Local firewall/NAT/security groups. Verify `ufw`, cloud SGs, and that service binds to the **right address** (0.0.0.0 vs 127.0.0.1).
---
## 11) Practice tasks (do these now)
1) Identify your **primary interface**, IPv4/IPv6 addresses, and default gateway.
*Hint:* `ip -br a`, `ip route`.
2) Show the exact route used to reach **1.1.1.1** and **google.com**.
*Hint:* `ip r get`, `mtr -rwbc 30`.
3) Resolve `example.com` to A and AAAA records using **your** resolver and **1.1.1.1**.
*Hint:* `dig +short`, `dig @1.1.1.1`.
4) Start the Python HTTP server on port **8080**, verify with `ss` and `curl`, then stop it.
5) Create a local TCP listener on **9000** with `nc`, send a line of text from a client, confirm it appears, and clean up.
6) (Optional) Add a temporary UFW rule for **8080/tcp**, verify access, then remove it.
---
## 12) Quick quiz (1 minute)
- Which command shows **listening sockets with PIDs**?
- Which tool gives you **route plus packet loss** over time?
- Name two commands to test **DNS** quickly.
- If a hostname fails but an IP succeeds, which layer is broken?
- What does `ip r get 8.8.8.8` tell you?
**Answers:** `ss -tulpn`; `mtr` (or `traceroute` for path only); `resolvectl`, `dig` (also `getent hosts`); DNS; which interface/gateway will carry traffic to that destination.
---
## Next Step
Proceed to **Step 8 — Users & Authentication** (local users, groups, passwords, SSH basics). If your curriculum orders topics differently, adjust the previous steps “Next Step” pointer to match this page.

278
docs/08_archiving.md Normal file
View File

@ -0,0 +1,278 @@
# Step 8 — Archiving & Compression (Ubuntu 24)
> **Type along** exactly as shown. Nothing here alters system config. Optional installs use `apt`.
> **Estimated time:** ~2025 minutes
---
## What youll learn
- The difference between **archiving** (tar) and **compressing** (gzip/xz/zstd/zip/7z)
- Create, list, verify, extract **tar** archives with and without compression
- Choose the right compressor for **speed** vs **size** (gzip, xz, zstd)
- Include/exclude paths, preserve ownership/permissions, and handle **symlinks** and **sparse files**
- Stream archives via **pipes** and **SSH**; split and rejoin large archives
- Verify integrity with `tar -tvf`/`-W` and `sha256sum`
> **Setup:** Work in a safe playground:
> ```bash
> mkdir -p ~/playground/arch && cd ~/playground/arch
> ```
---
## 0) Prepare sample data
Create a small tree with different file types:
```bash
mkdir -p src dirA/dirB
printf 'hello\n' > src/hello.txt
head -c 1M </dev/urandom > src/random.bin
ln -s ../src hello_link # symlink
# create a sparse file (looks big, uses little disk)
truncate -s 500M src/sparse.img
# hidden file, and a file to exclude later
printf 'secret\n' > .env
printf 'ignore me\n' > src/tmp.log
```
Confirm structure:
```bash
find . -maxdepth 3 -printf '%M %u:%g %8s %p\n' | sed -n '1,40p'
```
---
## 1) Archiving 101 — `tar` without compression
Create an archive of **src/** and **dirA/**:
```bash
# c=create, v=verbose, f=filename
tar -cvf lab.tar src dirA
ls -lh lab.tar
```
List contents without extracting:
```bash
tar -tvf lab.tar | head -20
```
Extract into a new folder and compare:
```bash
mkdir extract && tar -xvf lab.tar -C extract
diff -qr src extract/src && echo 'src matches extract/src'
```
> **Note:** `tar` stores paths relative to where you run it; use `-C` to control base paths.
---
## 2) Compressors quick tour
Install common tools:
```bash
sudo apt update && sudo apt install -y zstd xz-utils gzip zip unzip p7zip-full
```
Singlefile compression (no tar):
```bash
# gzip (fast, widespread)
gzip -k src/hello.txt # keeps original with -k
ls -lh src/hello.txt*
# xz (smallest, slower)
xz -k src/random.bin
# zstd (balanced, very fast; levels 119; -T0 = all cores)
zstd -k -T0 src/random.bin
```
Inspect compression ratios:
```bash
gzip -l src/hello.txt.gz
xz -l src/random.bin.xz
zstd -lv src/random.bin.zst
```
> **Rule of thumb:** `zstd` is great default for speed; `xz` for maximum shrink (archives) when time is okay; `gzip` for legacy compatibility.
---
## 3) Tar + compression combos
### Easiest: let `tar` drive the compressor
```bash
# gzip
tar -czvf lab.tar.gz src dirA
# xz
tar -cJvf lab.tar.xz src dirA
# zstd (modern)
tar --zstd -cvf lab.tar.zst src dirA
```
**List** without extracting:
```bash
tar -tvf lab.tar.gz | head -10
tar -tvf lab.tar.xz | head -10
tar -tvf lab.tar.zst | head -10
```
### Custom compressor flags with `-I`
```bash
# zstd level 19, all cores
tar -I 'zstd -T0 -19' -cvf lab-max.tar.zst src dirA
# parallel gzip if `pigz` is installed
# sudo apt install -y pigz
tar -I pigz -cvf lab.tar.gz src dirA
```
---
## 4) Extracting safely
Basic extraction into a target directory:
```bash
mkdir -p /tmp/lab_extract
sudo tar -xvpf lab.tar.zst --zstd -C /tmp/lab_extract
```
Flags used:
- `x` extract, `v` verbose, `p` **preserve perms**, `f` filename
- `--same-owner` (root only) to preserve ownership exactly
Strip leading path components (handy when archive contains a toplevel folder):
```bash
mkdir clean && tar -xvf lab.tar.gz --strip-components=1 -C clean
```
Extract **one** item:
```bash
tar -xvf lab.tar.zst --zstd src/hello.txt -C extract_one
```
---
## 5) Excludes, includes, and quoting
Create an archive but **exclude** logs and hidden files:
```bash
tar --exclude='*.log' --exclude='.*' -cvf lab_nohidden.tar src dirA
tar -tvf lab_nohidden.tar | grep -E '\.log|/\.' || echo 'No logs/hidden files included'
```
Use an **excludefrom** file (one pattern per line):
```bash
printf '*.log\n.env\n*.tmp\n' > exclude.txt
tar --exclude-from=exclude.txt -cvf lab_filtered.tar src dirA
```
> **Quoting tip:** Quote globs (`'*.log'`) so your shell doesnt expand them before `tar` sees them.
---
## 6) Sparse files & symlinks
The sample `src/sparse.img` is **sparse**. Use `--sparse` to store holes efficiently:
```bash
tar --sparse -cvf sparse.tar src/sparse.img
ls -lh sparse.tar
```
Control how symlinks are handled:
```bash
# default: store symlink as link (recommended)
tar -cvf links.tar hello_link
# follow symlinks (stores target content)
tar -h -cvf links_follow.tar hello_link
tar -tvf links_follow.tar | head -3
```
---
## 7) Streaming: pipes & SSH
Create and compress on the fly, no temp file:
```bash
tar -c src | zstd -T0 -19 -o src.tar.zst
```
Send to a remote host over SSH (requires SSH access):
```bash
# on local machine
tar -c src | ssh user@remote 'tar -x -C /tmp'
# or with compression on the wire
tar -c src | zstd -T0 | ssh user@remote 'zstd -d | tar -x -C /tmp'
```
---
## 8) Integrity: list, verify, checksum
**List** is your first sanity check:
```bash
tar -tvf lab.tar.zst --zstd | head -5
```
Ask `tar` to **verify** after writing (`-W`):
```bash
tar --zstd -cvWf lab_verify.tar.zst src dirA
```
Create a strong **checksum** alongside the archive:
```bash
sha256sum lab_verify.tar.zst > lab_verify.tar.zst.sha256
sha256sum -c lab_verify.tar.zst.sha256 # verify later
```
---
## 9) Split & rejoin large archives
Split into ~200 MiB parts:
```bash
tar --zstd -cvf big.tar.zst src dirA
split -b 200M big.tar.zst big.tar.zst.part-
ls -lh big.tar.zst.part-*
```
Rejoin and verify:
```bash
cat big.tar.zst.part-* > big.rejoined.tar.zst
cmp big.tar.zst big.rejoined.tar.zst && echo 'Parts rejoined OK'
```
---
## 10) `zip` and `7z` (crossplatform)
### zip
```bash
zip -r lab.zip src dirA . -x '*.log' .env
unzip -l lab.zip | head -10
unzip lab.zip -d unzip_out
```
### 7Zip / 7z (high ratio, solid archives)
```bash
7z a -t7z -m0=lzma2 -mx=9 lab.7z src dirA
7z l lab.7z | head -15
7z x lab.7z -o7z_out -y
```
---
## 11) Ownership, perms, and umask
- `tar` records **modes, owners, groups, times**. Extraction as nonroot maps owners to **your** user unless you use `sudo` + `--same-owner`.
- Use `-p` to **preserve permissions** even if your `umask` would change them.
- For shared/team archives, consider setting a consistent `umask` before creating, e.g., `umask 022`.
---
## 12) Clean up (optional)
```bash
rm -rf extract extract_one clean unzip_out 7z_out *.tar* *.gz *.xz *.zst *.zip *.7z *.sha256 big.rejoined.tar.zst src dirA hello_link exclude.txt .env
```
---
## 13) Practice tasks (do these now)
1) Create `proj.tar.zst` from `src/` **excluding** `*.log` and hidden files. List its contents.
2) Extract only `src/hello.txt` into `~/playground/arch/single/` and verify checksum with `sha256sum`.
3) Make a **sparse** 1 GiB file and build a spaceefficient archive of it; compare `.tar` size with and without `--sparse`.
4) Streamextract `src/` to `/tmp/arch_stream/` without creating a local archive file.
5) Split `proj.tar.zst` into 100 MiB parts, rejoin, and verify with `cmp`.
6) (Optional) Create `lab.zip` and `lab.7z`, list both, extract to separate folders, and compare with the original tree using `diff -qr`.
---
## 14) Troubleshooting
- **“file changed as we read it”** during tar: the file mutated midarchive; rerun when idle, or snapshot first.
- **Permissions wrong after extract**: add `-p` and (if root) `--same-owner`; check `umask`.
- **Symlinks unexpectedly dereferenced**: you probably used `-h`; remove it to store links as links.
- **Archive too slow**: use `zstd -T0` (multithreaded) or `pigz` for gzip; avoid `xz` for huge trees if you care about speed.
- **Disk full**: prefer streaming (`tar | zstd -o /mnt/big/…`) or `-C` to write on a larger filesystem; check free space with `df -h`.
---
## 15) Quick quiz (1 minute)
- Does `tar` compress by default?
- Which compressor is fastest on multicore systems at decent ratios?
- Which `tar` option keeps original file modes on extract?
- How do you exclude all hidden files?
- Whats the safest way to copy to a remote host without writing a local archive file?
**Answers:** No, `tar` only archives unless you add a compressor; `zstd -T0`; `-p` (and `--same-owner` when root); `--exclude='.*'`; `tar -c dir | ssh host 'tar -x -C /dest'` (optionally compress in the middle).
---
## Next Step
Proceed to **Step 9 — Users & Authentication** (local users, groups, passwords, SSH basics). If your curriculum orders differ, update the previous steps “Next Step” pointer to this page.

266
docs/09_package_mgmt.md Normal file
View File

@ -0,0 +1,266 @@
# Step 9 — Package Management (Ubuntu 24)
> **Type along** exactly as shown. Focuses on APT (Debian/Ubuntu). Optional bits cover `snap` and `flatpak`.
> **Estimated time:** ~2530 minutes
---
## What youll learn
- Discover, install, remove, and upgrade software with **APT**
- Inspect package **metadata**, **versions**, **deps**, and **files**
- Roll back to a **specific version**, **hold** packages, and clean cache
- Diagnose broken packages and locks; read APT/DPKG **logs**
- (Optional) Add thirdparty **repositories** safely with modern **keyrings**
- (Optional) Use **snap** and **flatpak** where appropriate
> **Setup:** Use a lab VM or a machine where you can install harmless utilities like `cowsay`, `sl`, `tree`. Production hosts should follow change control.
---
## 0) Refresh indexes & basic system hygiene
```bash
sudo apt update # refresh package lists
apt list --upgradable # see pending upgrades (no sudo needed)
sudo apt upgrade -y # safe upgrade of installed packages
sudo apt autoremove -y # remove unused deps
sudo apt clean # drop cached .deb files
```
> **Tip:** Use `sudo apt full-upgrade` (aka `dist-upgrade`) to allow kernel or dependency changes that add/remove packages.
---
## 1) Find packages
Search by name/description:
```bash
apt search htop | sed -n '1,20p' # quick text search
```
Show detailed metadata:
```bash
apt show htop | sed -n '1,40p'
```
See available versions & repository **origin**:
```bash
apt policy htop
```
List reverse deps (who depends on whom):
```bash
apt-cache rdepends --installed bash | sed -n '1,20p'
```
---
## 2) Install & remove packages
Install with confirmation and see what else will be pulled in:
```bash
sudo apt install -y htop tree
```
Remove software but keep config files:
```bash
sudo apt remove -y tree
```
Remove **and** purge config files:
```bash
sudo apt purge -y tree
```
### Verify installation contents
Which files did a package install?
```bash
dpkg -L htop | sed -n '1,40p' # list files owned by installed package
```
Which package owns a file path?
```bash
dpkg -S /usr/bin/htop
```
Find package **for an uninstalled** file path (requires apt-file):
```bash
sudo apt install -y apt-file
sudo apt-file update
apt-file search bin/ncdu | head -10
```
---
## 3) Versions: pin, hold, and roll back
See available versions across repos:
```bash
apt policy openssh-server
```
Install a **specific version**:
```bash
sudo apt install openssh-server=1:9.6p1-3ubuntu13 # example; use a version shown by `apt policy`
```
Temporarily **hold** at current version (dont upgrade):
```bash
sudo apt-mark hold openssh-server
apt-mark showhold
# later, unhold
sudo apt-mark unhold openssh-server
```
### Advanced: pin priority (optional)
Create a pin to prefer Ubuntu main over a PPA for a package (edit safely):
```bash
sudo mkdir -p /etc/apt/preferences.d
sudo tee /etc/apt/preferences.d/openssh.pref >/dev/null <<'EOF'
Package: openssh-server
Pin: release a=noble
Pin-Priority: 600
EOF
```
> **Rules of thumb:** Priority >1000 forces downgrade if needed; 500 is default; 600 prefers that source.
---
## 4) Inspect dependencies & health
Show dependencies:
```bash
apt-cache depends htop | sed -n '1,40p'
```
Simulate an install (no changes):
```bash
sudo apt -s install ncdu
```
Check package status (installed?, config state):
```bash
dpkg -s htop | sed -n '1,40p'
```
---
## 5) Fix common issues
### Broken dependencies / interrupted dpkg
```bash
sudo dpkg --configure -a # finish interrupted installs
sudo apt -f install # attempt to fix broken deps
```
### Lock is held
If another process is using APT/DPKG (GUI updater, unattendedupgrades):
```bash
ps aux | egrep 'apt|dpkg|unattended' | egrep -v 'egrep'
# Wait for it to finish or stop the offending process if safe.
```
### Stuck halfinstalled package
```bash
sudo apt purge -y <packagename>
sudo apt install -y <packagename>
```
### Where to read logs
```bash
sudo tail -n 100 /var/log/apt/history.log
sudo tail -n 100 /var/log/dpkg.log
```
---
## 6) Repositories the **right** way (modern keyrings) — optional
> Avoid legacy `apt-key`. Use perrepo **keyrings** and `signed-by=`.
Example: add a vendor repo safely (replace placeholders with a real vendors URLs):
```bash
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://vendor.example.com/keys/repo.gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/vendor.gpg
# Add source list (adjust codename e.g., noble, jammy)
. /etc/os-release
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/vendor.gpg] \
https://vendor.example.com/apt $VERSION_CODENAME main" | \
sudo tee /etc/apt/sources.list.d/vendor.list >/dev/null
sudo apt update
apt policy vendor-package-name
```
Remove the repo cleanly later:
```bash
sudo rm -f /etc/apt/sources.list.d/vendor.list /etc/apt/keyrings/vendor.gpg
sudo apt update
```
### PPAs (Launchpad) — optional
```bash
sudo apt install -y software-properties-common
sudo add-apt-repository -y ppa:graphics-drivers/ppa
sudo apt update
```
Remove:
```bash
sudo add-apt-repository -r ppa:graphics-drivers/ppa
sudo apt update
```
---
## 7) Kernel & reboot awareness
List kernels and check if a reboot is pending:
```bash
dpkg -l 'linux-image*' | sed -n '1,20p'
[ -f /var/run/reboot-required ] && echo 'Reboot required' || echo 'No reboot pending'
```
---
## 8) Snap & Flatpak (optional)
### Snap
```bash
snap list
snap find jq | head -10
sudo snap install jq
sudo snap remove jq
```
### Flatpak
```bash
sudo apt install -y flatpak
sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak search org.gnome.Calculator | head -5
sudo flatpak install -y flathub org.gnome.Calculator
flatpak list
sudo flatpak uninstall -y org.gnome.Calculator
```
> **When to use:** Prefer APT for system packages; `snap/flatpak` for sandboxed desktop apps or when newer versions are only available there.
---
## 9) Cleanup & space management
```bash
sudo apt autoremove --purge -y
sudo apt clean
sudo du -h /var/cache/apt/archives | tail -1
```
---
## 10) Practice tasks (do these now)
1) **Search** for `ncdu`, inspect details (`apt show`), and install it.
2) Use `dpkg -L ncdu` to list files; find which package owns `/usr/bin/ncdu` (`dpkg -S`).
3) Install `jq` at a **specific version** if multiple are available (`apt policy`, then `apt install jq=…`).
4) **Hold** `jq`, show holds, then **unhold** it.
5) Install `apt-file`, search which package provides `bin/htop`.
6) (Optional) Add a PPA, install a package from it, then remove the PPA and revert using pins or by installing the Ubuntu version.
7) Read the last 50 lines of both APT and DPKG logs.
---
## 11) Troubleshooting quick guide
- **Broken deps**`sudo dpkg --configure -a`, `sudo apt -f install`, then inspect `/var/log/apt/history.log`.
- **Held or pinned versions** blocking upgrades → check `apt-mark showhold`, and files under `/etc/apt/preferences.d`.
- **Repo GPG errors** → ensure you used keyrings + `signed-by=…`; check permissions on `/etc/apt/keyrings/*.gpg` (0644).
- **“Package not found”** → verify `apt update`, correct **codename** in source (`noble`, `jammy`), and architecture matches.
- **Lock files busy** → another process is running (`unattended-upgrades`, GUI), or left stale lock after crash. Confirm with `ps` and wait/kill cautiously.
---
## 12) Quick quiz (1 minute)
- Which command shows all **available versions** for a package and where they come from?
- Whats the difference between `remove` and `purge`?
- How do you **prevent** a package from upgrading?
- Which logs help you reconstruct what APT did recently?
- Why is `apt-key` deprecated and what should you use instead?
**Answers:** `apt policy`; `remove` keeps config files, `purge` deletes them; `apt-mark hold` (and pins for repo preference); `/var/log/apt/history.log` and `/var/log/dpkg.log`; use perrepo **keyrings** with `signed-by=`.
---
## Next Step
Proceed to **Step 10 — Users & Authentication** (local users, groups, passwords, SSH basics). If your curriculum orders differ, update the previous steps “Next Step” pointers accordingly.

365
docs/10_scripting.md Normal file
View File

@ -0,0 +1,365 @@
# Step 10 — Basic Scripting (Bash on Ubuntu 24)
> **Type along** exactly as shown. Well use **Bash** throughout. Nothing here modifies system config unless stated.
> **Estimated time:** ~3040 minutes
---
## What youll learn
- Write and run your first **Bash** scripts safely
- Use variables, quoting, arithmetic, and **exit codes**
- Branching (`if`), loops (`for`, `while`), and **functions**
- Handle **arguments** (`$1…`, `"$@"`, `getopts`), and **I/O** (stdin/stdout/stderr)
- Robust practices: shebangs, `set -Eeuo pipefail`, `trap`, `ShellCheck`
- Read files linebyline, use pipes, and compose small utilities
> **Setup:**
> ```bash
> mkdir -p ~/playground/scripting && cd ~/playground/scripting
> ```
---
## 0) Shebang, permissions, and running
Create a minimal script and execute it.
```bash
cat > hello.sh <<'EOF'
#!/usr/bin/env bash
# Minimal script
printf 'Hello, %s!\n' "${1:-world}"
EOF
chmod +x hello.sh
./hello.sh
./hello.sh Raghu
```
**Notes**
- `#!/usr/bin/env bash` finds Bash via `$PATH`.
- `chmod +x` makes it executable.
- Use `./script.sh` or full path; **dont** rely on `.` being in `$PATH`.
---
## 1) Safer defaults for real scripts
Create a template with error handling.
```bash
cat > template.sh <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
# ^ E: trap ERR on subshells, e: exit on error, u: unset var error, o pipefail: pipeline fails early
IFS=$'\n\t'
# --- globals ---
SCRIPT_NAME=${0##*/}
VERSION=1.0.0
# --- cleanup & error handling ---
cleanup() {
# runs on EXIT; delete temp files here
:
}
trap cleanup EXIT
err() {
local code=$?
printf 'ERROR(%s): command failed (exit=%d)\n' "$SCRIPT_NAME" "$code" >&2
}
trap err ERR
usage() {
cat <<USAGE
Usage: $SCRIPT_NAME [-n NAME] [-v]
-n NAME who to greet (default: world)
-v print version and exit
USAGE
}
name="world"
while getopts ':n:v' opt; do
case "$opt" in
n) name=$OPTARG ;;
v) printf '%s %s\n' "$SCRIPT_NAME" "$VERSION"; exit 0 ;;
:) printf 'Option -%s requires an argument\n' "$OPTARG" >&2; exit 2 ;;
\?) usage; exit 2 ;;
esac
done
shift $((OPTIND-1))
printf 'Hello, %s!\n' "$name"
EOF
chmod +x template.sh
./template.sh -n Labzy
./template.sh -v
```
> **Reality check:** `set -e` can surprise you with commands that legally return nonzero (e.g., `grep` no matches). Either guard them (`grep ... || true`) or test conditionally (`if grep -q ...; then ... fi`).
---
## 2) Variables, quoting, and arithmetic
```bash
name=Raghu # no spaces around =
num=5
msg="Hi $name" # double quotes expand variables
printf '%s (%d)\n' "$msg" "$num"
# arithmetic
((sum = num + 10))
printf 'sum=%d\n' "$sum"
((sum++))
# command substitution
now=$(date +%F)
printf 'Today: %s\n' "$now"
# arrays (indexed)
fruits=(apple banana cherry)
printf '%s\n' "${fruits[@]}"
# associative arrays (bash >= 4)
declare -A ages=([alice]=30 [bob]=27)
printf 'Alice=%s Bob=%s\n' "${ages[alice]}" "${ages[bob]}"
```
**Quoting rules youll actually use**
- Always **doublequote** variables: `"$var"` (prevents word splitting & globbing)
- Prefer `"${arr[@]}"` to expand arrays safely
- Use single quotes for **literal** strings: `'*.log'`
---
## 3) Conditions and loops
```bash
# if/elif/else
x=7
if (( x > 10 )); then
echo 'big'
elif (( x == 7 )); then
echo 'lucky'
else
echo 'small'
fi
# string tests and files
f='hello.sh'
if [[ -f $f && -x $f ]]; then echo 'script is executable'; fi
# case
case "$1" in
start) echo starting ;;
stop) echo stopping ;;
*) echo usage: $0 '{start|stop}' ;;
esac
# for loop (files)
for p in *.sh; do
printf 'script: %s\n' "$p"
done
# while read loop (robust)
printf 'a\nb\nc\n' > lines.txt
while IFS= read -r line; do
printf 'line=[%s]\n' "$line"
done < lines.txt
```
---
## 4) Functions, returns, and exit codes
```bash
is_port_open() {
local host=$1 port=$2
(echo > /dev/tcp/$host/$port) >/dev/null 2>&1
}
if is_port_open 127.0.0.1 22; then
echo 'ssh seems open'
else
echo 'ssh closed'
fi
# explicit exit codes
some_check() {
[[ -d $1 ]] || return 2 # custom non-zero means a specific failure
}
some_check /nope || echo "some_check failed with: $?"
```
> **Guideline:** exit codes: `0=success`, `1=generic`, `2=bad usage`, `>2` commandspecific.
---
## 5) Stdout vs stderr, pipes, and redirection
```bash
# send normal output to a file
./hello.sh > output.txt
# send errors to a file
./template.sh -z 2> errors.log || true
# merge stderr into stdout
./template.sh -z > all.log 2>&1 || true
# pipelines
seq 1 10 | paste -sd+ - | bc
```
**Heredocs and herestrings**
```bash
cat <<'TXT' > note.txt
multi-line text
with $variables left alone
TXT
# here-string passes a single line as stdin
read -r first <<< "$(head -n1 note.txt)"
```
---
## 6) Mini project: a tiny backup script
Create directories and a script that tars + compresses a folder with date stamps.
```bash
mkdir -p data backups
printf 'demo\n' > data/file1.txt
cat > backup.sh <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
shopt -s nullglob
SRC=${1:-data}
OUT=${2:-backups}
mkdir -p "$OUT"
stamp=$(date +%Y%m%d-%H%M%S)
archive="$OUT/${SRC##*/}-$stamp.tar.zst"
# require tar and zstd
command -v tar >/dev/null || { echo 'tar missing' >&2; exit 127; }
command -v zstd >/dev/null || { echo 'zstd missing: sudo apt install zstd' >&2; exit 127; }
tar --zstd -cvf "$archive" "$SRC" >/dev/null
printf 'Created %s (%s)\n' "$archive" "$(du -h "$archive" | cut -f1)"
EOF
chmod +x backup.sh
./backup.sh data backups
ls -lh backups | tail -n +1
```
**Restore one archive**
```bash
mkdir -p restore
latest=$(ls -1 backups/*.tar.zst | tail -n1)
tar --zstd -xvf "$latest" -C restore
```
---
## 7) Argument parsing with `getopts`
```bash
cat > args_demo.sh <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
usage() { echo "Usage: $0 [-c COUNT] [-o OUTDIR] file"; }
count=1; out=out
while getopts ':c:o:h' opt; do
case "$opt" in
c) count=$OPTARG ;;
o) out=$OPTARG ;;
h) usage; exit 0 ;;
:) echo "Option -$OPTARG needs an argument" >&2; exit 2 ;;
\?) usage; exit 2 ;;
esac
done
shift $((OPTIND-1))
file=${1:-}
[[ -n $file ]] || { usage; exit 2; }
mkdir -p "$out"
for i in $(seq 1 "$count"); do
cp -a "$file" "$out/${file##*/}.$i"
done
echo "Wrote $count copies to $out"
EOF
chmod +x args_demo.sh
./args_demo.sh -c 3 -o copies hello.sh
ls -l copies
```
---
## 8) Reusable helpers and style
Create a tiny **lib** and reuse it.
```bash
cat > lib.sh <<'EOF'
#!/usr/bin/env bash
set -Eeu -o pipefail
log() { printf '[%(%F %T)T] %s\n' -1 "$*"; }
require() { command -v "$1" >/dev/null || { log "need $1"; exit 127; }; }
EOF
cat > use_lib.sh <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
. ./lib.sh
require curl
log "Fetching example.com headers"
curl -I https://example.com >/dev/null
log done
EOF
chmod +x use_lib.sh
./use_lib.sh
```
**Lint your scripts** (highly recommended):
```bash
sudo apt update && sudo apt install -y shellcheck
shellcheck hello.sh template.sh backup.sh args_demo.sh use_lib.sh
```
---
## 9) Cron and scheduling (optional)
Run a script every day at 02:15.
```bash
crontab -e
# add the line below, save & exit
15 2 * * * /home/$USER/playground/scripting/backup.sh /home/$USER/data /home/$USER/backups >>/home/$USER/backup.log 2>&1
```
Check logs or output files to confirm it ran.
---
## 10) Practice tasks (do these now)
1) Add a `-d`/`--dry-run` option to `backup.sh` that prints what would be archived but doesnt create a file.
2) Modify `args_demo.sh` to accept `-p PREFIX` and include it in the output filenames.
3) Write `checksum.sh` that prints a SHA256 for each file passed as arguments; exit `2` if any file doesnt exist.
4) Create `filter.sh` that reads stdin and prints only lines containing a supplied pattern (caseinsensitive) use `grep -i` properly with `set -e`.
5) (Optional) Write `netcheck.sh host port` that returns `0` if TCP is open using the `/dev/tcp` trick; otherwise `1`.
---
## 11) Troubleshooting quick guide
- **Permission denied** → forgot `chmod +x`; or directory lacks `+x` for traversal.
- **`command not found`** → incorrect shebang; missing dependency (use `require` helper).
- **Script exits early with `set -e`** → a command returned nonzero; handle expected failures with `|| true` or `if` guards.
- **Arguments with spaces break** → missing quotes; always use `"$var"` and `"$@"`.
- **Cron works manually but not via cron** → PATH/env differences; use absolute paths and redirect stderr.
---
## 12) Quick quiz (1 minute)
- Why prefer `#!/usr/bin/env bash` over `#!/bin/bash`?
- What does `set -Eeuo pipefail` do in plain English?
- How do you safely loop over lines in a file?
- Whats the difference between `$*` and `"$@"`?
- Which tool flags common Bash mistakes automatically?
**Answers:** Finds Bash via PATH (portable across distros); stricter error handling and earlier failure; `while IFS= read -r line; do …; done < file`; `$*` joins words (unsafe), `"$@"` preserves argument boundaries; **ShellCheck**.
---
## Next Step
Proceed to **Step 11 — Users & Authentication** (or the next topic in your curriculum). Update previous steps “Next Step” pointers if needed.

View File

@ -0,0 +1,46 @@
# Step 11 — Permissions Challenge (Validation Task)
> **Goal:** Configure secure permissions for a small project so only the owner can read “secret” files, while a public folder stays readable by others.
> **Type:** Task with validator (solution is **not** in this doc). Use the helper if youre stuck.
## Scenario
Your team stores notes in a project called `secure-project`. You must:
- Create the directories and files
- Apply **correct permissions** so secrets are private and public readme is worldreadable
- Run the validator to confirm
## Requirements
1) Create folders (under your home practice area):
- `~/playground/secure-project/secrets`
- `~/playground/secure-project/public`
2) Create files with exact contents:
- `~/playground/secure-project/secrets/plan.txt` containing: `TOP SECRET`
- `~/playground/secure-project/public/readme.txt` containing: `Welcome to the project`
3) Set permissions **exactly**:
- Directory `secrets`: `700`
- File `secrets/plan.txt`: `600`
- Directory `public`: `755`
- File `public/readme.txt`: `644`
4) Optional (nice to have, not required for pass):
- Show octal + owner/group using: `stat -c "%A %a %U %G %n" <path>`
## Hints (partial)
- Create folders: `mkdir -p ...`
- Create files: `echo "TEXT" > file`
- Set directory perms: `chmod 700 DIR` (owner `rwx`, others none)
- Set file perms: `chmod 600 FILE` (owner `rw`, others none)
- Public readable directory: `chmod 755 DIR`
- Public readable file: `chmod 644 FILE`
## How to validate
From your terminal, run the validator:
```bash
bash validate/11_permissions_task.sh
```
If everything is correct, it will print **PASS**. Otherwise it prints a helpful **FAIL** message so you can adjust and rerun.

View File

@ -0,0 +1,7 @@
# Step 12: Networking Troubleshooting (Validation Task)
1. Ping localhost: `ping -c 2 127.0.0.1`
2. Ping remote: `ping -c 2 example.com`
3. Trace route: `traceroute example.com`
4. DNS check: `dig example.com`

BIN
helpers/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,22 @@
### Helper — Step 11: Permissions Challenge (Exact Commands)
> Use this only if youre stuck. These commands implement the required state exactly.
```bash
# 1) Workspace
mkdir -p ~/playground/secure-project/{secrets,public}
# 2) Files with exact content
echo "TOP SECRET" > ~/playground/secure-project/secrets/plan.txt
echo "Welcome to the project" > ~/playground/secure-project/public/readme.txt
# 3) Permissions
chmod 700 ~/playground/secure-project/secrets
chmod 600 ~/playground/secure-project/secrets/plan.txt
chmod 755 ~/playground/secure-project/public
chmod 644 ~/playground/secure-project/public/readme.txt
# 4) (Optional) Inspect
stat -c "%A %a %U %G %n" ~/playground/secure-project/secrets ~/playground/secure-project/secrets/plan.txt
stat -c "%A %a %U %G %n" ~/playground/secure-project/public ~/playground/secure-project/public/readme.txt
```

View File

@ -0,0 +1,6 @@
### Helper for Step 12: Networking Troubleshooting
- `ping 127.0.0.1` → local test
- `ping example.com` → remote test
- `traceroute` → shows path
- `dig example.com` → DNS lookup

View File

@ -1,16 +1,68 @@
title: labzy
version: 1.0.0
description: Descrition for tasks .
overview_path: docs/00_overview.md
title: "Linux Essentials — Instruction Lab (Ubuntu 24)"
version: "1.0.0"
description: "Beginner-friendly Linux lab covering 12 steps with optional validation tasks for Git and Networking."
overview_path: "docs/00_overview.md"
sections:
title: Instructions
title: "Instructions"
items:
- id: 1
title: Task 1
path: docs/01_task.md
estimated_minutes: 7
dependencies: []
title: "Terminal Basics"
path: "docs/01_terminal_basics.md"
estimated_minutes: 20
- id: 2
title: "Navigation & File Operations"
path: "docs/02_navigation_file_ops.md"
estimated_minutes: 20
- id: 3
title: "Searching & Text Viewing"
path: "docs/03_searching_text.md"
estimated_minutes: 20
- id: 4
title: "Process Management"
path: "docs/04_process_management.md"
estimated_minutes: 20
- id: 5
title: "Permissions & Ownership"
path: "docs/05_permissions.md"
estimated_minutes: 15
- id: 6
title: "System Info & Monitoring"
path: "docs/06_system_info.md"
estimated_minutes: 20
- id: 7
title: "Networking Basics"
path: "docs/07_networking.md"
estimated_minutes: 25
- id: 8
title: "Archiving & Compression"
path: "docs/08_archiving.md"
estimated_minutes: 25
- id: 9
title: "Package Management"
path: "docs/09_package_mgmt.md"
estimated_minutes: 30
- id: 10
title: "Basic Scripting"
path: "docs/10_scripting.md"
estimated_minutes: 30
- id: 11
title: "Permissions Challenge (Validation Task)"
path: "docs/11_permissions_task.md"
helper_path: "helpers/11_permissions_task.md"
validation_script: "validate/11_permissions_task.sh"
estimated_minutes: 20
- id: 12
title: "Networking Troubleshooting (Validation Task)"
path: "docs/12_network_troubleshooting.md"
helper_path: "helpers/12_network_troubleshooting.md"
validation_script: "validate/12_network_troubleshooting.sh"
estimated_minutes: 10
ui:
default_open_section_id: 1
show_toc: true
collapsible_sections: true
license:
path: "/LICENSE.md"

BIN
validate/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,32 @@
#!/usr/bin/env bash
set -euo pipefail
fail() { echo "FAIL: $1" >&2; exit 1; }
pass() { echo "PASS: Permissions Challenge completed successfully"; exit 0; }
ROOT="$HOME/playground/secure-project"
# 1) Check structure
[ -d "$ROOT/secrets" ] || fail "Missing directory: $ROOT/secrets"
[ -d "$ROOT/public" ] || fail "Missing directory: $ROOT/public"
[ -f "$ROOT/secrets/plan.txt" ] || fail "Missing file: $ROOT/secrets/plan.txt"
[ -f "$ROOT/public/readme.txt" ] || fail "Missing file: $ROOT/public/readme.txt"
# 2) Check contents
grep -qx "TOP SECRET" "$ROOT/secrets/plan.txt" || fail "plan.txt content must be exactly: TOP SECRET"
grep -qx "Welcome to the project" "$ROOT/public/readme.txt" || fail "readme.txt content must be exactly: Welcome to the project"
# 3) Check permissions (octal)
perm_dir_secrets=$(stat -c "%a" "$ROOT/secrets")
[ "$perm_dir_secrets" = "700" ] || fail "secrets directory should be 700 (got $perm_dir_secrets)"
perm_plan=$(stat -c "%a" "$ROOT/secrets/plan.txt")
[ "$perm_plan" = "600" ] || fail "secrets/plan.txt should be 600 (got $perm_plan)"
perm_dir_public=$(stat -c "%a" "$ROOT/public")
[ "$perm_dir_public" = "755" ] || fail "public directory should be 755 (got $perm_dir_public)"
perm_readme=$(stat -c "%a" "$ROOT/public/readme.txt")
[ "$perm_readme" = "644" ] || fail "public/readme.txt should be 644 (got $perm_readme)"
pass

View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -e
ping -c 1 127.0.0.1 >/dev/null || { echo "FAIL: Localhost ping failed"; exit 1; }
(getent hosts example.com || dig +short example.com) >/dev/null || { echo "FAIL: DNS failed"; exit 1; }
echo "PASS: Networking Troubleshooting Completed"