05 February 2026
Troubleshooting Cron Jobs: Why Your Script Won't Run
Quick one-liner: Your script works fine from the terminal but fails as a cron job. Here's how to debug it — and why $PATH is almost always to blame.
🤔 Why This Matters
I've lost count of how many times a perfectly working script refused to run when scheduled as a cron job. The script runs fine when you execute it manually — no errors, no warnings. But when cron triggers it? Nothing.
The frustrating part is that cron's default logging tells you almost nothing. You get a timestamp in /var/log/cron but no stdout, no stderr, no explanation of what went wrong.
🔍 Step 1: Capture the Output
The quickest way to see what's happening is to redirect your script's output to a log file.
Add this line to the end of your crontab entry:
30 2 * * * /path/to/myscript.sh > /tmp/cronscript.log 2>&1
Or add it inside the script itself:
#!/bin/bash
exec > /tmp/cronscript.log 2>&1
# ... rest of your script
Now when the cron job runs, you'll see every error message, every warning, every output line in /tmp/cronscript.log:
cat /tmp/cronscript.log
💡 The Usual Suspect: Missing $PATH
Here's the hint that solves 80% of cron job problems: cron runs with a minimal $PATH.
When you run a script from your terminal, it inherits your shell's environment — including /usr/local/bin, /usr/bin, and maybe some custom paths. When cron runs the same script, the $PATH is usually just:
/usr/bin:/bin
If your script calls python3, docker, rsync, or anything outside that minimal path, cron can't find it.
Fix it two ways:
Option 1: Use absolute paths in your script:
#!/bin/bash
/usr/local/bin/python3 /opt/myscript.py
/usr/bin/rsync -avz /data/ /backup/
Option 2: Set $PATH at the top of your script:
#!/bin/bash
export PATH=/usr/local/bin:/usr/bin:/bin:/opt/bin
# ... rest of your script
Option 3: Set $PATH in your crontab:
PATH=/usr/local/bin:/usr/bin:/bin:/opt/bin
30 2 * * * /path/to/myscript.sh
🔧 Other Common Issues
Your script isn't executable:
chmod +x /path/to/myscript.sh
Missing environment variables:
Cron doesn't load your ~/.bashrc or ~/.profile. If your script depends on environment variables like JAVA_HOME, ORACLE_SID, or custom config paths, you need to set them explicitly:
#!/bin/bash
export JAVA_HOME=/usr/lib64/jvm/java
export ORACLE_SID=PROD
export MY_CONFIG=/etc/myapp/config.ini
Wrong user:
Cron jobs run as the user who created the crontab. If your script needs to access files owned by another user, or requires root privileges, you need to set up the crontab for the correct user:
# As root
crontab -e
# As a specific user
sudo crontab -u username -e
Relative paths in the script:
If your script uses cd relative/path or reads ./config.ini, it's looking relative to cron's working directory (usually the user's home directory). Always use absolute paths:
# Bad
cd data && process.sh
# Good
cd /opt/myapp/data && /opt/myapp/process.sh
✅ Quick Debug Checklist
When a cron job fails, go through these steps:
- Add output logging →
> /tmp/cronscript.log 2>&1 - Check the log →
cat /tmp/cronscript.log - Check
$PATH→ does every command have an absolute path? - Check permissions → is the script executable?
- Check environment variables → are they set in the script?
- Check the user → does the cron user have access to all files?