Cron Environment Hardening and Debug Wrapper Prompt
Diagnose and fix the classic 'works in my shell, fails in cron' problem — minimal PATH, missing env, no TTY, swallowed output — by wrapping jobs in a hardened runner that logs, locks, and captures failures.
- Target user
- Engineers whose cron jobs fail silently or only in cron
- Difficulty
- Beginner
- Tools
- Claude, ChatGPT
The prompt
You are a senior ops engineer who has lost hours to cron jobs that run perfectly by hand and silently do nothing on schedule. You know the culprits cold: cron's stripped-down environment, minimal PATH, no profile sourcing, and discarded output. I will provide: - The crontab line(s) and the script(s) they call - The symptom (nothing happens / partial run / "command not found") - The OS and which user the job runs as Your job: 1. **Explain the environment gap** — cron runs with a near-empty environment: a minimal `PATH` (often `/usr/bin:/bin`), no `~/.bashrc`/`~/.profile`, `HOME` maybe unset, no TTY, and a different locale. Map each of my symptoms to one of these causes. 2. **Make the script self-sufficient** — don't rely on cron's env. At the top of the script: set an explicit `PATH`, `export` the few vars actually needed (or source a dedicated env file, not the interactive profile), set `LANG`/`LC_ALL`, and use absolute paths or `command -v` checks for every external binary. 3. **Build a debug wrapper** — a `run-cron.sh` that: sets strict mode, redirects stdout+stderr to a timestamped log, records start/exit time and exit code, and on non-zero exit emails/alerts with the tail of the log. Cron's MAILTO is unreliable — capture output yourself. 4. **Prevent overlap** — wrap the real job in `flock -n` so a slow run can't pile up on the next tick; log and skip if the lock is held. 5. **Reproduce cron locally** — give me a command to run the job with cron's stripped env (`env -i`) so I can reproduce the failure interactively instead of guessing. 6. **Crontab hygiene** — set `PATH`, `SHELL`, and `MAILTO` at the top of the crontab; quote `%` (cron treats it specially); use absolute script paths; document the schedule in a comment. 7. **Consider graduating to systemd** — note when a systemd timer (with `Environment=`, journald logging, and `OnFailure=`) is the better answer than hardening cron. Output: (a) the hardened script header, (b) the reusable `run-cron.sh` wrapper with logging + flock + failure alert, (c) the corrected crontab line, (d) the `env -i` reproduction command. Bias toward self-sufficient scripts and capturing output yourself rather than trusting cron's defaults.