ArunNetworkingPro
🤫

Linux+ Break Room · Case 08

The script that whispers lies

"SUCCESS: backed up 6 files." There are only 4 files. It never backed up most of them.

Every night, a little bash script backs up the house's most precious papers. Every night it whispers SUCCESS. Nobody has checked in months. Agatha's diary has never been saved. A strange file called 100 keeps appearing next to it. And when a file can't be read at all, it still says everything went perfectly. Catch every lie, and make it tell the truth.

Case 08 of 10Automation & scriptingTroubleshootingNo sudo

🧰 What you need

Get the case

Rule 4: read it before you run it, less breakroom-mission-08.sh. The top of the file lists everything it creates and how --clean removes it.

curl -O https://arunnetworkingpro.com/labs/breakroom-mission-08.sh
bash breakroom-mission-08.sh
cd ~/breakroom/mission-08

At any point, ask the house how many ghosts are left:

bash breakroom-mission-08.sh --check

Part A: catch it lying

A1

Does it keep its promise?

./backup.sh
ls data | wc -l
ls vault

How many files does it say it saved? How many are really in the vault? Which ones are missing?

Hint

Compare the number it prints with ls data and ls vault. What do the missing files have in common? Look at their names.

A2

Watch it think

bash -x ./backup.sh

Follow what really happens to Agatha's diary.txt. Then fix the loop so every file makes it, whatever its name.

Hint

bash -x prints every command after expansion. $(ls ...) splits names at spaces, and $f without quotes splits them again. Loop over a glob instead: for f in "$SRC"/*, and quote every variable: "$f". And stop hiding errors with 2>/dev/null.

A3

The file called 100

Where does the file called 100 come from? Fix the test so it compares numbers.

Hint

Inside [ ], > isn't "greater than", it's a redirect into a file. Numbers use -gt: [ "$count" -gt 100 ]. Or bash's own (( count > 100 )).

Part B: make it honest

B1

SUCCESS, no matter what

chmod 000 data/candles.list
./backup.sh; echo "exit code: $?"

A file can't be read, and it still says SUCCESS with exit code 0. Make it report the failure and exit with a non-zero code. Then chmod 644 data/candles.list again.

Hint

Three lies stack up here. | true throws away tar's exit status. [ $? ] is always true (it only tests "is this text non-empty?"). And exit 0 at the end overrides everything. Count failed copies, check tar directly with if ! tar ...; then, and exit 1 when anything failed.

B2

Count the truth

Make it count files it actually copied, not words it looped over.

Hint

Only add one when cp succeeds: if cp -- "$f" "$DEST/"; then count=$((count+1)); else failed=$((failed+1)); fi.

✅ How you know you won

bash breakroom-mission-08.sh --check tests your script on fresh copies, a normal night and a night with a locked file, and says Verdict: 4/4. No more whispers. The script tells the truth now. Case closed.

Answer key (no peeking until you've tried)

A1: it says 6 files; only 2 reach the vault (candles.list, notes.txt). Both names with spaces are lost. A2: $(ls) plus missing quotes split Agatha's diary.txt into Agatha's and diary.txt; 2>/dev/null hid the errors. A3: [ $count > 100 ] redirects into a file named 100; use -gt. B1: remove | true, [ $? ] and the unconditional exit 0; exit 1 if tar or any copy failed. B2: count inside if cp ...; then.

💥 Let it haunt you again

Run the script again. The haunting starts over, fresh:

bash breakroom-mission-08.sh

Now do it without the hints. And when you're done for good: bash breakroom-mission-08.sh --clean.

🧠 The ghost, explained

Verdict: not a ghost. Seven ordinary bash mistakes, each one hiding the one before it.

Quote your variables. Always. Unquoted $f is split at spaces and has wildcards expanded. "$f" stays one word. Filenames with spaces aren't rare: they're what real people make.

Never loop over ls. for f in $(ls) turns a list of names into a pile of words. for f in "$dir"/* hands you each name whole.

Exit codes are how scripts tell the truth. 0 means success, anything else means failure, and every command sets $?. Anything after a command (even echo) replaces it, | true hides it, and exit 0 at the end overrules everything. Cron, systemd and other scripts all trust your exit code, so a script that always exits 0 is lying to all of them.

[ ] is a command, not magic. [ takes words as arguments, so > means redirect, -gt means greater-than, and [ $? ] just checks "is there some text?". set -euo pipefail and shellcheck catch a lot of this for you.

← Case 07 · All cases · Case 09 → · Stuck, or found a better way? Email me

🎉 Got it, thank you!

Your comment just landed in my inbox. I read every one, and I'll reply by email.

🤔 That didn't go through

Something in the form looked off. Check your name, email and comment and try again, or just email me.

🐢 Whoa, slow down

That's a lot of comments in a short time, so the box is taking a breather. Try again later, or email me.

😴 The comment box is napping

My server is taking a quick break, so your comment couldn't be sent. Sorry! Please email me instead.

💬 Leave a comment

Stuck, found a better way, or just built it and want to brag? Tell me. It comes straight to my inbox (nothing is posted publicly), and I'll reply by email.

Your email is only used to reply to you. Never shared, never added to any list.