You’ve written a shell script. It works perfectly when you run it manually. You add it to cron, and… nothing. No output, no errors, just silence.
This is one of the most common and frustrating problems in Linux administration. Here’s why it happens and how to fix it.
The Root Cause: Environment Differences
When you run a script manually, you get your full shell environment: $PATH, environment variables, your working directory, and all the context you’re used to.
Cron runs in a minimal environment. It doesn’t source your .bashrc, doesn’t have your $PATH, and starts from a different working directory.
Fix #1: Use Absolute Paths for Everything
This is the most common culprit. Your script calls python or aws or docker, and cron can’t find them.
Bad:
| |
Good:
| |
Find the full path with which:
| |
Fix #2: Set PATH at the Top of Your Script
If you have many commands, set the PATH explicitly:
| |
Or set it in your crontab:
| |
Fix #3: Set the Working Directory
Scripts often assume they’re running from a specific directory.
Bad:
| |
Good:
| |
Fix #4: Capture Output for Debugging
Cron swallows all output by default. Redirect it to see what’s happening:
| |
Or send errors to yourself:
| |
Fix #5: Source Required Environment Files
If your script needs environment variables (API keys, database URLs), source them explicitly:
| |
Fix #6: Check the Shebang
Make sure your script has the correct shebang and is executable:
| |
Make it executable:
| |
Fix #7: Handle Missing TTY
Some commands behave differently without a terminal. Add these flags:
| |
The Debugging Checklist
When your cron job fails, check these in order:
- Can cron find the script? Use absolute path in crontab
- Can the script find its commands? Use absolute paths or set PATH
- Is the script executable?
chmod +x - What’s the error? Redirect output to a log file
- Does it need environment variables? Source them explicitly
- Is cron even running?
systemctl status cron - Is the syntax correct? Use crontab.guru to verify
Test Like Cron
Simulate cron’s environment to debug locally:
| |
This runs your script with a minimal environment, just like cron does.
Example: A Bulletproof Cron Script
| |
Crontab entry:
| |
This script will log everything, fail fast on errors, and work reliably in cron’s minimal environment.
The difference between a script that works manually and one that works in cron is explicitness. Don’t assume anything about the environment — specify everything.