Script Works Manually but Not in Cron

Short answer

Cron does not run your script inside the same environment as your interactive terminal. It typically uses a different PATH, a different working directory, a minimal non-login shell, and sometimes a different user — and it doesn’t load your shell profile (.bashrc, .zshrc, .profile) by default. A script that depends on any of these implicitly will behave differently, or fail, under cron.

The most common differences

Quick diagnostic checklist

Add this as the first lines of the script (or a wrapper) to capture what cron actually sees, then compare against your interactive shell:

pwd
whoami
env | sort
command -v python3
command -v mysqldump

Run the same four commands manually in your terminal and diff the output. The differences are usually the root cause.

Safe crontab pattern

SHELL=/usr/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin

* * * * * cd /absolute/project && ./script.sh >> logs/cron.log 2>&1

Setting SHELL and an explicit PATH at the top of the crontab, always cd-ing into an absolute project path before running, and redirecting both stdout and stderr to a log file removes most of the ambiguity above in one pattern.

Why this becomes a silent failure

A script that partially runs under cron’s restricted environment doesn’t always crash cleanly. It may create an output file, write a header row, then fail before writing real data — exiting 0 because the failure was swallowed by a missing command, a caught exception, or a masked pipe status. A heartbeat ping or bare exit-code check will not catch this; the process technically completed.

Continuous prevention

The environment mismatch is a one-time debugging problem, but validating that the job actually produced correct output should be continuous. Checking exit code alone tells you the process ran under whatever environment cron gave it — it does not tell you the output is correct.

Where Night Watchman fits

Night Watchman monitors the artifact a cron job produces — not just whether the process exited cleanly. If a PATH or environment mismatch causes a script to silently write an empty or malformed file, Night Watchman checks freshness, size, and shape against history and escalates an evidence dossier citing exactly what it found, rather than trusting the exit code.

FAQ

Why is cron’s PATH different from my shell’s PATH?

Cron starts jobs with a minimal, non-interactive environment and does not source your shell profile (.bashrc, .zshrc, .profile) by default, so anything that profile normally sets up — including PATH extensions from version managers — is missing.

Should I use absolute paths in cron?

Yes. Absolute paths for both the working directory (cd /absolute/project) and any file references remove the ambiguity of “relative to what?” that cron’s working directory otherwise introduces.

How do I know if the output is actually valid, not just that the script ran?

Check the produced artifact directly: file size, row or record count, expected schema/header, freshness, and whether it’s plausible compared with prior runs — not just the script’s exit code.

Try Night Watchman

Install from the public repository:

curl -fsSL https://raw.githubusercontent.com/ssddee-dev/code-batman/main/install.sh | bash
cd ~/night-watchman
.venv/bin/python -m watchman.setup