| title | Shell script debugging checklist for agent jobs | ||||||
|---|---|---|---|---|---|---|---|
| domain | devops | ||||||
| tags |
|
||||||
| status | published | ||||||
| lang | en | ||||||
| source | uncledad96-glitch | ||||||
| translated_from | lessons/contrib/shell-script-debugging.md | ||||||
| created | 2026-07-22 | ||||||
| updated | 2026-07-22 | ||||||
| confidence | 0.9 |
A bash script exits with no useful error, or “works in terminal” but fails under cron. Earn loops look dead.
- Missing
set -euo pipefail→ failures ignored. - Cron has empty PATH / no DISPLAY.
- Pipeline exit status is last command only without
pipefail. - Silent redirects hide stderr.
#!/usr/bin/env bash
set -euo pipefail
export PATH="$HOME/.local/bin:/usr/bin:/bin"
log() { printf '[%s] %s\n' "$(date '+%F %T')" "$*" | tee -a "$HOME/.local/state/job.log"; }
log "start"
command -v python3
python3 script.py
log "ok"Debug run:
bash -x ./job.sh 2>&1 | tee /tmp/trace.txt
# or
PS4='+${BASH_SOURCE}:${LINENO}: ' bash -x ./job.shCron line must use absolute paths and log:
*/5 * * * * $HOME/bin/job.sh >>$HOME/.local/state/job.log 2>&1bash -n job.sh
bash job.sh; echo exit:$?
tail -20 ~/.local/state/job.log- Prefer a long-lived supervisor (
mm-desktop start) for loops; cron for thin snipers. - Never put secrets in the script body; source a mode-600 env file.