You added a cron job. It works when you run it manually. But cron just… doesn’t run it. No errors, no output, nothing.

This is one of the most frustrating debugging experiences in Linux. Here’s a systematic checklist to find out what’s actually wrong.

1. Check If Cron Is Running

First, make sure the cron daemon is actually running:

1
2
3
4
5
6
7
# systemd systems
systemctl status cron
# or
systemctl status crond

# Older init systems
service cron status

If it’s not running, start it:

1
2
sudo systemctl start cron
sudo systemctl enable cron

2. The PATH Problem (Most Common)

This is the #1 reason cron jobs fail.

When you run a command in your terminal, you have a full PATH with /usr/local/bin, /home/user/.local/bin, etc. Cron has a minimal PATH—usually just /usr/bin:/bin.

Your cron job:

python3/home/user/script.py

Fails because cron can’t find python3 (it’s in /usr/bin/python3 which should work, but what about pip-installed tools?).

Fix: Use absolute paths for everything:

1
* * * * * /usr/bin/python3 /home/user/script.py

Or set PATH at the top of your crontab:

1
2
3
PATH=/usr/local/bin:/usr/bin:/bin:/home/user/.local/bin

* * * * * python3 /home/user/script.py

Find the absolute path of any command with which:

1
2
3
4
5
$ which python3
/usr/bin/python3

$ which node
/home/user/.nvm/versions/node/v20.0.0/bin/node

3. Environment Variables Are Missing

Cron runs with a minimal environment. Your script might depend on:

  • HOME
  • USER
  • Custom variables like DATABASE_URL or API_KEY
  • Virtual environment activation

Fix: Source your environment or set variables explicitly:

1
2
3
4
5
6
7
8
9
# Option 1: Set variables in crontab
DATABASE_URL=postgres://localhost/mydb
* * * * * /usr/bin/python3 /home/user/script.py

# Option 2: Source a file
* * * * * . /home/user/.env && /usr/bin/python3 /home/user/script.py

# Option 3: Use a wrapper script
* * * * * /home/user/run-job.sh

The wrapper script approach is cleanest:

1
2
3
4
5
6
7
8
#!/bin/bash
# /home/user/run-job.sh

source /home/user/.bashrc
source /home/user/venv/bin/activate
cd /home/user/project

python3 script.py

4. Check the Cron Log

Cron logs vary by distro:

1
2
3
4
5
6
7
8
# Ubuntu/Debian
grep CRON /var/log/syslog

# RHEL/CentOS/Rocky
cat /var/log/cron

# Or use journalctl
journalctl -u cron --since "1 hour ago"

Look for entries like:

CRON[12345]:(user)CMD/home/user/script.py)

If you don’t see your job at all, cron isn’t picking it up.

5. Crontab Syntax Errors

A single syntax error can break your entire crontab. Validate your timing:

#####0#0CmEE3E9oi0vvvrn-eeeru5rrret9yyycetmdM1h0iaofo-n/y/n/ou2uppdprr3taaaaametttytadhhhta/3/a/:ytattt-omooo1//9/f-ssas-3ccmcm1rrroiiinppptttthmo1n-t1h2day-0o-f7-weekcommand

Common mistakes:

  • Using */ incorrectly: */15 means “every 15 minutes”, not “at minute 15”
  • Forgetting that day-of-week 0 and 7 are both Sunday
  • Extra spaces or tabs in the wrong places

Use crontab.guru to validate expressions.

6. Permission Problems

Check if your script is executable:

1
2
3
4
5
ls -la /home/user/script.py
# Should show: -rwxr-xr-x

# If not:
chmod +x /home/user/script.py

Also verify the cron user can access all paths in the script. If you’re editing root’s crontab but the script tries to write to /home/user/, permissions will fail.

7. Capture Output for Debugging

Cron swallows stdout and stderr by default. Redirect to see what’s happening:

1
* * * * * /usr/bin/python3 /home/user/script.py >> /home/user/cron.log 2>&1

The 2>&1 sends stderr to the same place as stdout—crucial for catching Python tracebacks.

Or email output (if mail is configured):

1
2
MAILTO=you@example.com
* * * * * /usr/bin/python3 /home/user/script.py

8. Are You Editing the Right Crontab?

There are multiple places cron jobs can live:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# User crontab (most common)
crontab -e

# System crontab (includes username field)
/etc/crontab

# Drop-in directories
/etc/cron.d/
/etc/cron.daily/
/etc/cron.hourly/

If you’re editing /etc/crontab or files in /etc/cron.d/, remember to include the username:

1
2
# /etc/crontab format (note the 'root' user field)
* * * * * root /path/to/script

Quick Debugging Checklist

  1. ✅ Is cron running? (systemctl status cron)
  2. ✅ Using absolute paths? (/usr/bin/python3 not python3)
  3. ✅ Environment variables set?
  4. ✅ Script is executable? (chmod +x)
  5. ✅ Logging output? (>> /path/to/log 2>&1)
  6. ✅ Check cron log for errors? (grep CRON /var/log/syslog)
  7. ✅ Syntax validated? (crontab.guru)

Nine times out of ten, it’s the PATH. Start there.