ArunNetworkingPro
🌙

Linux+ Break Room · Case 09

Things that go bump at midnight

The midnight jobs never ran. The spell book has been tampered with. Nobody saw a thing.

Every minute, cron is supposed to knock once and light a lantern. The heartbeat log is empty, and the lantern log only says "not found". A systemd timer should run a ritual at midnight: it has never fired, not once. And the grimoire, a git repository of spells, has been quietly changed. A secret was committed and "removed", a spell was broken, and a protection charm was deleted. The history remembers everything. Make the house quiet again.

Case 09 of 10Automation & scriptingTroubleshootingNo sudo

🧰 What you need

Get the case

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

curl -O https://arunnetworkingpro.com/labs/breakroom-mission-09.sh
bash breakroom-mission-09.sh

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

bash breakroom-mission-09.sh --check

Part A: cron

A1

The heartbeat that never beats

crontab -l
ls ~/breakroom/mission-09/cron

The knock job runs every minute, yet its log file never appears. Find out what cron actually ran. Then fix it.

Hint

cron writes down each command it starts: sudo journalctl --since -5min | grep CMD (or grep CRON /var/log/syslog). Look at where the command stops. In a crontab, % means "newline", so it has to be escaped as \%. Edit with crontab -e.

A2

Command not found

cat ~/breakroom/mission-09/cron/lantern.log
~/breakroom/mission-09/bin/lantern-check

It works when you run it. cron can't find it. Why? Fix the job.

Hint

cron runs jobs with a tiny PATH (usually just /usr/bin:/bin), not yours. Use the full path to the program in the crontab line, or set PATH= at the top of the crontab.

Part B: the midnight timer

B1

A time that doesn't exist

systemctl --user start breakroom-09-midnight.timer
systemctl --user status breakroom-09-midnight.timer

Find what's wrong with the schedule, fix it so it fires every night at midnight, and make it survive a reboot.

Hint

systemd-analyze calendar '...' tests any schedule and shows the next time it would fire. Clocks go from 00:00 to 23:59. To enable it, the timer needs [Install] with WantedBy=timers.target. Then daemon-reload, enable --now, and systemctl --user list-timers. (User timers only run while you're logged in, unless loginctl enable-linger $USER is on.)

B2

Don't wait for midnight

Run the ritual right now, once, to prove it works.

Hint

A timer only triggers its service. You can start the service yourself: systemctl --user start breakroom-09-midnight.service, then cat ~/breakroom/mission-09/ritual.log.

Part C: the grimoire's history

C1

The secret that was "removed"

cd ~/breakroom/mission-09/grimoire
git log --oneline

Someone committed a secret, then deleted it. What was the secret?

Hint

Deleting a file in a new commit doesn't erase it from history. git log --oneline --all -- .env lists commits that touched it. git show <commit>:.env prints the file as it was in that commit.

C2

Who broke the spell?

bash spell.sh

Find the commit that broke spell.sh, and who made it. Undo it without rewriting history.

Hint

git log -p -- spell.sh shows every change to one file, with its author. git revert --no-edit <commit> adds a new commit that undoes it (--no-edit skips opening an editor). (git bisect can hunt it down automatically in bigger histories.)

C3

Bring back the protection

protection.txt was deleted. Bring it back from history, and commit it.

Hint

git log --oneline --diff-filter=D -- protection.txt finds the commit that deleted it. The file still exists in the commit before that one: git checkout <commit>^ -- protection.txt, then git commit -m "Bring back protection".

✅ How you know you won

bash breakroom-mission-09.sh --check says Verdict: 6/6. Nothing goes bump anymore. It was Linux all along. Case closed. (The cron checks need a minute or two after your fix.)

Answer key (no peeking until you've tried)

A1: cron ran echo "knock at $(date + and stopped: the % cut the line. Write date +\%H:\%M. A2: lantern-check isn't on cron's PATH; use $HOME/breakroom/mission-09/bin/lantern-check (the full path). B1: OnCalendar=*-*-* 24:00:00 is invalid; use *-*-* 00:00:00 (or daily), add [Install] / WantedBy=timers.target, daemon-reload, enable --now. B2: systemctl --user start breakroom-09-midnight.service. C1: summon_key=candle-7734-agatha (commit 2136ba9, "Add summoning config"). C2: 0d0e70f "Tidy up spells" by Agatha (exti 0); git revert --no-edit 0d0e70f. C3: deleted in a2b4668; git checkout a2b4668^ -- protection.txt and commit.

💥 Let it haunt you again

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

bash breakroom-mission-09.sh

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

🧠 The ghost, explained

Verdict: not a ghost. The midnight bumps were a percent sign, a PATH, an impossible time and a git history that remembered everything.

cron is not your shell. It runs jobs with almost no environment: a tiny PATH, no aliases, no .bashrc. Full paths and explicit logging (>> file 2>&1) save hours. And % is special in crontabs, a detail that has broken countless date commands.

systemd timers are cron's modern cousin. A .timer starts a .service on a schedule. OnCalendar= uses its own format, which systemd-analyze calendar checks for you. Persistent=true runs missed jobs after the machine was off, and list-timers shows when everything fires next.

git never forgets. A secret that was ever committed is in the history until someone rewrites it, and every clone has a copy. The real fix for a leaked secret is to change the secret itself.

Undo with new commits. git revert adds a commit that reverses an old one, so everyone else's history stays valid. git checkout <commit> -- file (or git restore --source) brings back any file from any point in time.

← Case 08 · All cases · Case 10 → · 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.