feat(root01): author Computing & Linux Foundations, and the real 01->05 prerequisite chain
Adds all 6 ROOT 01 modules (how computers run software, the shell, filesystem navigation, files & text, processes, users & permissions foundations), each with a real lesson, demonstration/guided exercise, knowledge check where warranted, a hands-on Lab, and a reflection — 35 activities, 29 new content files. Adds 6 new hands-on Linux scenarios (linux-inspect-hardware, linux-shell-basics, linux-filesystem-navigation, linux-files-and-text, linux-process-management, linux-permissions-foundations) plus 2 MCQ scenarios, using the existing generic scenario/ validation engine (docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md §1) — every one tested end-to-end via the real scenario setup/validate API, including negative tests confirming they correctly FAIL when not actually solved (e.g. the process-management scenario fails while the target process is still running; the permissions scenario is tested against a real `su - labuser` denial). Wires rootnode-linux-foundations-assessment (2 required + 4 random-draw scenarios) using the existing Phase 3B assessment engine. Adds a real, server-side ROOT 01->02->03->04->05 course prerequisite chain (courses.prerequisites) — verified live on two students: one who completed ROOT 01 sees ROOT 02 unlock; a fresh student sees ROOT 02 correctly locked while 03/04/05 stay vacuously satisfied (their own prerequisite courses are still empty). ROOT 06+ and the Capstone are unaffected. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# Processes
|
||||
|
||||
## What a process actually is
|
||||
|
||||
A **process** is a running instance of a program — its own code, its own private memory, and a
|
||||
unique identifier the kernel tracks called a **PID** (Process ID). Run the same program twice
|
||||
(open two terminals both running `bash`), and you get two separate processes with two different
|
||||
PIDs, even though they're running identical code.
|
||||
|
||||
## Foreground vs. background
|
||||
|
||||
A command you run normally occupies your terminal until it finishes (**foreground**) — you
|
||||
can't type anything else until it's done. Append `&` to run it in the **background** instead,
|
||||
freeing your terminal immediately while the process keeps running. `sleep 300 &` starts a
|
||||
300-second sleep in the background and hands your prompt right back.
|
||||
|
||||
## Inspecting processes: `ps` and `top`
|
||||
|
||||
- `ps aux` — a snapshot of every process currently running, including its PID, how much CPU/
|
||||
memory it's using, and the exact command that started it.
|
||||
- `top` (or `htop`, if installed) — the same idea, but live-updating and sorted by resource
|
||||
usage, useful for "what's actually eating CPU/memory right now."
|
||||
|
||||
## Stopping a process: `kill` and signals
|
||||
|
||||
`kill <PID>` doesn't instantly destroy a process — it sends it a **signal**, a message the
|
||||
process can (usually) choose how to respond to. The default signal, `SIGTERM` (15), politely
|
||||
asks a process to shut down, giving it a chance to clean up first. `kill -9 <PID>` sends
|
||||
`SIGKILL`, which the kernel enforces immediately with no chance for the process to react —
|
||||
appropriate only when a process is truly stuck and ignoring `SIGTERM`. `kill -0 <PID>` is a
|
||||
special case: it sends NO real signal at all, just checks whether the PID still exists —
|
||||
exactly how you confirm "did that process actually stop" without side effects.
|
||||
|
||||
## Process hierarchy
|
||||
|
||||
Every process (except the very first one at boot) has a **parent** — the process that started
|
||||
it. Your shell is the parent of every command you run from it. This matters later: a parent
|
||||
process's own lifecycle can affect its children (this is part of why a container, which is
|
||||
often just one process tree, behaves the way it does when its main process exits).
|
||||
|
||||
## Why this matters for containers and Kubernetes
|
||||
|
||||
A container is, underneath, mostly an isolated process (or small process tree) with its own
|
||||
view of the filesystem and network — when people say "a container exited," they mean its main
|
||||
process exited, exactly the same event you'll cause on purpose in this module's Lab. Kubernetes'
|
||||
entire job, at its core, is deciding which machine a process (inside a container) runs on and
|
||||
restarting it if it dies unexpectedly — none of that will feel intuitive without this module's
|
||||
model of what a process actually is.
|
||||
|
||||
## Instructor Notes
|
||||
|
||||
**Lesson goal:** Build a real process mental model (PID, foreground/background, signals,
|
||||
parent/child) that ROOT 04 (containers) and ROOT 06 (Kubernetes workloads) both directly build
|
||||
on without re-explaining.
|
||||
|
||||
**Approximate timing:** 15 minutes read; 10 minutes live.
|
||||
|
||||
**Common misconception to watch for:** students often think `kill` always means "forcefully
|
||||
destroy" — clarify that plain `kill` sends a polite, ignorable request (SIGTERM), and `-9` is
|
||||
the forceful escalation, not the default.
|
||||
|
||||
**Discussion question:** "What do you think happens to a container if its main process exits on
|
||||
its own, versus if something outside kills it?" (Don't need a complete answer yet — just plant
|
||||
the question for later.)
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
# Demonstration: Watching a Process Actually Terminate
|
||||
|
||||
## OBSERVE
|
||||
|
||||
Start a long-running background process and note its PID:
|
||||
|
||||
```
|
||||
$ sleep 300 &
|
||||
[1] 1421
|
||||
```
|
||||
|
||||
`1421` is the PID (yours will differ every time).
|
||||
|
||||
## HYPOTHESIS
|
||||
|
||||
Predict: will `kill -0 1421` print anything if the process is still running?
|
||||
|
||||
## INSPECT
|
||||
|
||||
```
|
||||
$ kill -0 1421 && echo "still running"
|
||||
still running
|
||||
```
|
||||
|
||||
`kill -0` sends no real signal — silence (or, here, our own `echo`) means the process exists.
|
||||
|
||||
## CHANGE
|
||||
|
||||
Now actually terminate it:
|
||||
|
||||
```
|
||||
$ kill 1421
|
||||
```
|
||||
|
||||
## VERIFY
|
||||
|
||||
```
|
||||
$ kill -0 1421 2>/dev/null && echo "still running" || echo "gone"
|
||||
gone
|
||||
```
|
||||
|
||||
The exact same check now reports the opposite result — real, observable proof the process is
|
||||
gone, not an assumption.
|
||||
|
||||
## Instructor Notes
|
||||
|
||||
**Demo goal:** Make "checking before and after" a visible habit, not just narrated — students
|
||||
should see the SAME command return a different real answer once state actually changed.
|
||||
|
||||
**Approximate timing:** 8 minutes live.
|
||||
|
||||
**Common mistake to watch for:** reaching for `kill -9` by default "to be safe" — reinforce that
|
||||
plain `kill` (SIGTERM) is the correct first attempt almost always.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Knowledge Check: Processes
|
||||
|
||||
---
|
||||
|
||||
**1. What does a PID identify?**
|
||||
|
||||
*Answer:* One specific running instance of a program — the kernel's unique identifier for that
|
||||
process, distinct from every other running process, even other copies of the same program.
|
||||
|
||||
---
|
||||
|
||||
**2. What's the actual difference between `kill <pid>` and `kill -9 <pid>`?**
|
||||
|
||||
*Answer:* Plain `kill` sends SIGTERM, a polite request the process can choose to handle (clean
|
||||
up, then exit). `kill -9` sends SIGKILL, which the kernel enforces immediately with no chance
|
||||
for the process to react — an escalation for when SIGTERM is ignored, not the default choice.
|
||||
|
||||
---
|
||||
|
||||
**3. You want to confirm a process is still running WITHOUT affecting it in any way. What do
|
||||
you use?**
|
||||
|
||||
*Answer:* `kill -0 <pid>` — sends no real signal, only checks whether the PID still exists.
|
||||
|
||||
---
|
||||
|
||||
**4. Why might understanding processes matter for understanding containers later?**
|
||||
|
||||
*Answer:* A container is, underneath, mostly an isolated process (or small process tree) — a
|
||||
container "exiting" is really its main process exiting, the exact same event this module's Lab
|
||||
causes on purpose.
|
||||
|
||||
## Instructor Notes
|
||||
|
||||
**Facilitation:** Question 2 is worth confirming explicitly — "kill -9 by default" is a common,
|
||||
worth-correcting habit.
|
||||
|
||||
**Approximate timing:** 5 minutes.
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
# Guided Exercise: Choosing the Right Signal
|
||||
|
||||
This is a paper exercise — commit to an answer before checking it in the Lab.
|
||||
|
||||
## Your task
|
||||
|
||||
For each situation, decide: plain `kill` (SIGTERM) first, or is `kill -9` (SIGKILL) actually
|
||||
justified?
|
||||
|
||||
1. A normal web server process you want to shut down for a routine restart.
|
||||
2. A process that received SIGTERM two minutes ago and is still running, showing no signs of
|
||||
responding.
|
||||
3. A script you just started by mistake, that hasn't done anything harmful yet.
|
||||
|
||||
## A worked shape to check yourself against
|
||||
|
||||
1. Plain `kill` — give it the chance to shut down cleanly (close connections, flush data, etc).
|
||||
2. `kill -9` is now justified — you already gave it the polite chance, and it didn't respond.
|
||||
3. Plain `kill` first, still — "just started" doesn't change the default; SIGKILL is a last
|
||||
resort, not a shortcut for convenience.
|
||||
|
||||
## Instructor Notes
|
||||
|
||||
**Facilitation:** Item 3 sometimes trips students who reach for `-9` out of impatience — worth
|
||||
reinforcing that SIGTERM-first is the discipline REGARDLESS of urgency, since a process that
|
||||
ignores SIGTERM is the actual signal that escalation is warranted.
|
||||
|
||||
**Approximate timing:** 8-10 minutes live discussion; 5 minutes self-paced.
|
||||
@@ -0,0 +1,27 @@
|
||||
# Reflection: You Just Stopped a Real Process, Not a Simulation
|
||||
|
||||
## Reflection questions
|
||||
|
||||
1. Before checking `kill -0` after your `kill`, how confident were you the process was
|
||||
actually gone? What would you have done if it hadn't stopped?
|
||||
2. Why do you think SIGTERM-before-SIGKILL matters more for a real production service than for
|
||||
a throwaway script in a Lab?
|
||||
|
||||
## Real Ops takeaway
|
||||
|
||||
**"I ran the kill command" is not the same as "I confirmed the process is gone."** This module's
|
||||
Lab required you to verify state, not just take an action and assume it worked — that
|
||||
verification step is exactly what separates a confident operator from someone hoping for the
|
||||
best. You'll repeat this exact pattern (act, then verify) constantly for the rest of ROOT_,
|
||||
starting as soon as ROOT 04's containers and continuing all the way through Kubernetes
|
||||
troubleshooting.
|
||||
|
||||
This module is complete. Continue to the next module.
|
||||
|
||||
## Instructor Notes
|
||||
|
||||
**Discussion questions for a live classroom:** question 2 is a good bridge to ROOT 06's later
|
||||
discussion of graceful shutdown/`terminationGracePeriodSeconds` — plant the idea now without
|
||||
naming Kubernetes specifics yet.
|
||||
|
||||
**Approximate timing:** 5-8 minutes live discussion; 5 minutes self-paced writing.
|
||||
Reference in New Issue
Block a user