Lab — Shell Ops Script Hardening¶
Lab Overview¶
Purpose: Practise the Shell Scripting track under pressure — fix a deliberately unsafe ops script until it is schedulable.
Scenario: A nightly “cleanup” job has been emailing false successes, deleting the wrong paths when names contain spaces, and overlapping itself when cron drifts.
Expected outcome: A hardened script with set -euo pipefail, quoted paths, mktemp+trap, flock, stderr logging, and documented exit codes.
This is a lab, not a tutorial
Apply Shell Scripting skills. Prefer small verified steps over rewriting everything at once.
Business Scenario¶
On-call inherited cleanup.sh from a paste in Slack. It “works on my machine”, uses unquoted rm -rf $TARGET, ignores pipeline failures, and has no lock. You must ship a version safe for cron on a shared bastion.
Learning Objectives¶
By the end of this lab, you will be able to:
- Reproduce failures from unquoted expansions and missing
pipefail - Add strict mode, logging helpers, and an exit taxonomy
- Protect the job with
flockand clean up withtrap - Validate success and failure paths before scheduling
Prerequisites¶
Knowledge¶
- Error Handling, Logging, and Debugging
- Process Automation — Signals and Traps
- Production Shell Scripting
- Troubleshooting Shell Scripts
Software¶
| Tool | Notes |
|---|---|
| Bash 4.2+ | bash --version |
| flock | util-linux (standard on Linux) |
| mktemp | coreutils |
Estimated cost: £0.
Architecture¶
Environment¶
Any Linux host or WSL2. Work under ~/rebash-lab-shell.
Initial State¶
mkdir -p ~/rebash-lab-shell/{inbox,safe-target}
cd ~/rebash-lab-shell
printf 'x\n' > "inbox/my file.txt"
printf 'y\n' > inbox/keep.txt
Broken script (starting point)¶
cat > cleanup-broken.sh << 'EOF'
#!/bin/bash
TARGET=$1
grep ERROR /var/log/syslog | wc -l
rm -rf $TARGET/*
echo SUCCESS
EOF
chmod +x cleanup-broken.sh
Task¶
Step 1 – Reproduce the quoting bug¶
# DANGEROUS demo only inside the lab tree:
./cleanup-broken.sh ~/rebash-lab-shell/inbox || true
ls -la inbox || true
Recreate files if needed. Observe how spaces break the command.
Step 2 – Rewrite with strict mode and quotes¶
Create cleanup.sh:
#!/usr/bin/env bash+set -euo pipefail- Require a target under
$HOME/rebash-lab-shell - Refuse paths outside that prefix (
realpath+ prefix check) - Quote all expansions
- Log to stderr; print
RESULT status=...on stdout
Step 3 – Add temp dir, trap, and flock¶
mktemp -dfor staging if neededtrap cleanup EXIT INT TERMflock -non~/rebash-lab-shell/cleanup.lock(exit 0 if already running)
Step 4 – Exit taxonomy¶
| Code | Meaning |
|---|---|
| 0 | Success |
| 2 | Usage / invalid path |
| 3 | Lock not acquired (optional alternate: 0) |
| 4 | Operational failure |
Step 5 – Validate¶
./cleanup.sh # expect usage -> 2
./cleanup.sh "$HOME/rebash-lab-shell/safe-target"
./cleanup.sh /tmp || echo "refused exit=$?"
Run two copies in parallel to confirm locking.
Validation¶
- Broken behaviour understood (spaces / missing pipefail)
- Hardened script uses strict mode and quoted paths
- Prefix check blocks
/tmp - Lock prevents overlap
- Trap removes temp dirs
Troubleshooting¶
| Symptom | Fix |
|---|---|
| flock missing | Install util-linux / use Linux VM |
| realpath missing | readlink -f on some distros |
| trap not firing | Ensure EXIT is included |
Cleanup¶
Stretch Goals¶
- Emit a machine-readable
RESULTline for CI - Add
-vverbose logging - Wrap with a systemd oneshot unit sketch