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

AspectYour TerminalCron
PATHFull PATH from your shell config/usr/bin:/bin (minimal)
Shellbash/zsh with your rc files/bin/sh (no rc files)
Working DirectoryWherever you run the commandUser's home directory
Environment VariablesAll your exports and configsAlmost none
AliasesAll your custom aliasesNone

Solutions

1. Use Absolute Paths

Instead of relying on PATH, use the full path to every command.

# ❌ Bad - relies on PATH
python script.py
# ✅ Good - absolute path
/usr/bin/python3 /home/user/scripts/script.py

Find the full path with: which python3

2. Set PATH in Crontab

Define the PATH variable at the top of your crontab file.

# Add this at the top of your crontab
PATH=/usr/local/bin:/usr/bin:/bin:/home/user/.local/bin

# Then your jobs can use commands normally
0 9 * * * python3 script.py

3. Source Your Profile

Load your shell configuration before running the command.

0 9 * * * source ~/.bashrc && /path/to/script.sh
💡

This 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.

# wrapper.sh
#!/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
# crontab
0 3 * * * /home/user/scripts/wrapper.sh

Debugging Tips

Capture cron's environment

Add this to crontab to see exactly what environment cron has:

* * * * * env > /tmp/cron-env.txt

Log everything

Redirect both stdout and stderr to a log file:

0 9 * * * /path/to/script.sh >> /var/log/myjob.log 2>&1

Test 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: \%