Environment Guide
Why your script works in the terminal but fails in cron—and how to fix it.
The Problem
You write a script. You test it in your terminal. It works perfectly. You add it to crontab, wait for it to run, and... nothing. Or worse, it runs but produces garbage output.
This happens because cron doesn't run your script the same way your terminal does. Cron executes jobs in a minimal, isolated environment that's missing most of the configuration you take for granted.
Common symptom
command not found errors for commands that work fine when you run them manually.
Key Differences: Terminal vs Cron
| Aspect | Your Terminal | Cron |
|---|---|---|
| PATH | Full PATH from your shell config | /usr/bin:/bin (minimal) |
| Shell | bash/zsh with your rc files | /bin/sh (no rc files) |
| Working Directory | Wherever you run the command | User's home directory |
| Environment Variables | All your exports and configs | Almost none |
| Aliases | All your custom aliases | None |
Solutions
1. Use Absolute Paths
Instead of relying on PATH, use the full path to every command.
python script.py/usr/bin/python3 /home/user/scripts/script.pyFind the full path with: which python3
2. Set PATH in Crontab
Define the PATH variable at the top of your crontab file.
PATH=/usr/local/bin:/usr/bin:/bin:/home/user/.local/bin0 9 * * * python3 script.py3. Source Your Profile
Load your shell configuration before running the command.
0 9 * * * source ~/.bashrc && /path/to/script.shThis works but adds overhead. Use absolute paths when possible for faster execution.
4. Use a Wrapper Script
Create a wrapper script that sets up the environment, then call that from cron.
#!/bin/bash export PATH=/usr/local/bin:/usr/bin:/bin export NODE_ENV=production cd /home/user/myapp ./run-backup.sh >> /var/log/backup.log 2>&1
0 3 * * * /home/user/scripts/wrapper.shDebugging Tips
Capture cron's environment
Add this to crontab to see exactly what environment cron has:
* * * * * env > /tmp/cron-env.txtLog everything
Redirect both stdout and stderr to a log file:
0 9 * * * /path/to/script.sh >> /var/log/myjob.log 2>&1Test with CronLabs
Point your script at a CronLabs webhook endpoint to verify it's actually running and see what it sends:
0 9 * * * curl -X POST https://webhook.cronlabs.dev/catch/YOUR_ID -d "status=running"Common Pitfalls
Using ~ in paths
Cron may not expand ~. Use /home/username instead.
Relying on .bashrc aliases
Aliases like ll or python don't exist in cron.
Assuming current directory
Relative paths like ./data/input.csv will fail. Always cd first or use absolute paths.
Forgetting about % escaping
In crontab, % means newline. Escape it: \%