update
This commit is contained in:
parent
6ebc0567f0
commit
a522d56305
|
|
@ -0,0 +1 @@
|
|||
Lab content © 2025 Meyi Cloud Solutions Pvt. Ltd. Licensed under CC BY-NC-ND 4.0.
|
||||
|
|
@ -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 1–10**: Core Linux skills (approx. 100 minutes).
|
||||
- **Steps 11–12**: 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 doesn’t 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.
|
||||
Binary file not shown.
|
|
@ -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 1–10**: Core Linux skills (approx. 200 minutes).
|
||||
- **Steps 11–12**: 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 doesn’t 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.
|
||||
|
|
@ -1 +0,0 @@
|
|||
## Initial task
|
||||
|
|
@ -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:** ~10–15 minutes
|
||||
|
||||
---
|
||||
|
||||
## What you’ll 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 (that’s 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 machine’s name)
|
||||
- `~` means your **home** directory (e.g., `/home/yourname`)
|
||||
- `$` is the standard prompt for regular users (a `#` indicates the root/admin shell — you won’t use root here)
|
||||
|
||||
> If your prompt looks a bit different, that’s 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 it’s 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` won’t 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**. Don’t 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 don’t 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 doesn’t work, close the terminal window.
|
||||
|
||||
**Q: My prompt ends with `#`. Is that bad?**
|
||||
A: That means you’re 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
|
||||
|
||||
You’re ready for **Step 2 — Navigation & File Operations**.
|
||||
Keep this terminal open; we’ll continue in the same window.
|
||||
|
||||
|
|
@ -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:** ~10–15 minutes
|
||||
|
||||
---
|
||||
|
||||
## What you’ll 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 don’t 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 you’re 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
|
||||
```
|
||||
|
||||
You’ll 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 you’re 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`). That’s 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 you’re 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?
|
||||
- What’s 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!
|
||||
|
|
@ -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:** ~10–15 minutes
|
||||
|
||||
---
|
||||
|
||||
## What you’ll 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
|
||||
|
||||
We’ll 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` doesn’t load the whole file at once — it’s 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 what’s 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 you’re 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: You’re walking directories you don’t own (outside your home). For practice, stay inside `~/playground`.
|
||||
|
||||
**Q: `less` won’t 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.
|
||||
|
|
@ -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:** ~10–15 minutes
|
||||
|
||||
---
|
||||
|
||||
## What you’ll 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) What’s 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 there’s one job, it’s 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
|
||||
```
|
||||
You’ll see one or more numbers (PIDs).
|
||||
|
||||
**Ask a process to exit nicely (SIGTERM 15):**
|
||||
```bash
|
||||
kill 15 <PID>
|
||||
```
|
||||
If it doesn’t exit after a few seconds, you can **force** it (SIGKILL 9):
|
||||
```bash
|
||||
kill -9 <PID>
|
||||
```
|
||||
> Use `-9` only if normal signals fail; it doesn’t let programs clean up.
|
||||
|
||||
**Alternative: kill by name (use carefully):**
|
||||
```bash
|
||||
pkill sleep # stops all 'sleep' processes you own
|
||||
# or
|
||||
killall sleep
|
||||
```
|
||||
|
||||
Confirm it’s 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 it’s 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` didn’t 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` won’t 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?
|
||||
- What’s 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.
|
||||
|
|
@ -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:** ~10–15 minutes
|
||||
|
||||
---
|
||||
|
||||
## What you’ll 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 fine‑grained 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:** You’ll 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 you’re 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 **owner’s** privileges.
|
||||
- Common on system tools like `passwd`.
|
||||
> **Don’t set setuid on your own scripts**; it’s risky and often ignored for scripts.
|
||||
|
||||
### setgid (`2xxx` on files/dirs)
|
||||
- On **directories**, new files inherit the directory’s **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 per‑user or per‑group 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 won’t run**: Ensure `#!/usr/bin/env bash` shebang and `chmod +x`. Also check the mount isn’t `noexec`.
|
||||
- **Group changes don’t “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 directory’s 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.
|
||||
|
||||
|
|
@ -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:** ~15–20 minutes
|
||||
|
||||
---
|
||||
|
||||
## What you’ll 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 high‑level 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 4‑core machine, a 1‑minute 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` (swap‑in/out) in `vmstat 1` output usually correlates with memory pressure.
|
||||
|
||||
---
|
||||
|
||||
## 2) Processes, load, and scheduling
|
||||
### `top` basics (built‑in)
|
||||
```bash
|
||||
top
|
||||
```
|
||||
Useful keys inside **top**:
|
||||
- `1`: show per‑CPU 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 one‑shot 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** memory‑hungry processes and the **top 5** CPU‑hungry 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 **per‑disk** 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/15‑min 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.
|
||||
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
# Step 7 — Networking Basics (Ubuntu 24)
|
||||
|
||||
> **Type along** exactly as shown. These are safe, read‑mostly commands. Optional tools will prompt for `sudo apt install`.
|
||||
> **Estimated time:** ~20–25 minutes
|
||||
|
||||
---
|
||||
|
||||
## What you’ll 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.)
|
||||
|
||||
You’ll 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 Wi‑Fi). 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 (read‑only)
|
||||
### On servers (systemd‑networkd)
|
||||
```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, it’s 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: who’s 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 “won’t start,” check whether the port is already taken (`ss -tulpn`).
|
||||
|
||||
---
|
||||
|
||||
## 7) Quick HTTP checks
|
||||
Spin up a tiny web server (Python 3’s 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 front‑end 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:** Don’t enable/alter firewalls on production hosts without change control. In the lab it’s 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 won’t 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 2–3 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 step’s “Next Step” pointer to match this page.
|
||||
|
||||
|
|
@ -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:** ~20–25 minutes
|
||||
|
||||
---
|
||||
|
||||
## What you’ll 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
|
||||
```
|
||||
Single‑file 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 1–19; -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 top‑level 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 **exclude‑from** 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 doesn’t 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` (cross‑platform)
|
||||
### zip
|
||||
```bash
|
||||
zip -r lab.zip src dirA . -x '*.log' .env
|
||||
unzip -l lab.zip | head -10
|
||||
unzip lab.zip -d unzip_out
|
||||
```
|
||||
### 7‑Zip / 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 non‑root 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 space‑efficient archive of it; compare `.tar` size with and without `--sparse`.
|
||||
4) Stream‑extract `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 mid‑archive; 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` (multi‑threaded) 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 multi‑core systems at decent ratios?
|
||||
- Which `tar` option keeps original file modes on extract?
|
||||
- How do you exclude all hidden files?
|
||||
- What’s 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 step’s “Next Step” pointer to this page.
|
||||
|
||||
|
|
@ -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:** ~25–30 minutes
|
||||
|
||||
---
|
||||
|
||||
## What you’ll 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 third‑party **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 (don’t 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, unattended‑upgrades):
|
||||
```bash
|
||||
ps aux | egrep 'apt|dpkg|unattended' | egrep -v 'egrep'
|
||||
# Wait for it to finish or stop the offending process if safe.
|
||||
```
|
||||
### Stuck half‑installed 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 per‑repo **keyrings** and `signed-by=`.
|
||||
|
||||
Example: add a vendor repo safely (replace placeholders with a real vendor’s 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?
|
||||
- What’s 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 per‑repo **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 step’s “Next Step” pointers accordingly.
|
||||
|
||||
|
|
@ -0,0 +1,365 @@
|
|||
# Step 10 — Basic Scripting (Bash on Ubuntu 24)
|
||||
|
||||
> **Type along** exactly as shown. We’ll use **Bash** throughout. Nothing here modifies system config unless stated.
|
||||
> **Estimated time:** ~30–40 minutes
|
||||
|
||||
---
|
||||
|
||||
## What you’ll 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 line‑by‑line, 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; **don’t** 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 non‑zero (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 you’ll actually use**
|
||||
- Always **double‑quote** 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` command‑specific.
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
**Here‑docs and here‑strings**
|
||||
```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 doesn’t 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 doesn’t exist.
|
||||
4) Create `filter.sh` that reads stdin and prints only lines containing a supplied pattern (case‑insensitive) – 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 non‑zero; 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?
|
||||
- What’s 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.
|
||||
|
||||
|
|
@ -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 you’re 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 world‑readable
|
||||
- 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 re‑run.
|
||||
|
|
@ -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`
|
||||
|
||||
Binary file not shown.
|
|
@ -0,0 +1,22 @@
|
|||
### Helper — Step 11: Permissions Challenge (Exact Commands)
|
||||
|
||||
> Use this only if you’re 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
|
||||
```
|
||||
|
|
@ -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
|
||||
70
lab.yaml
70
lab.yaml
|
|
@ -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"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -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
|
||||
|
|
@ -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"
|
||||
Loading…
Reference in New Issue