Cron Job Not Running? 10 Causes and Fixes
Your cron job isn't running, and cron isn't telling you why. The frustrating part is that cron fails silently — no popup, no obvious error, just a task that never happened. The good news: almost every case of a cron job not running comes down to one of ten causes, and each takes under a minute to check.
Run through this checklist first, then read the detailed fixes below.
Quick Diagnostic Checklist
- Is the cron daemon running? →
systemctl status cron - Did cron try to start your job? →
grep CRON /var/log/syslog - Are you using absolute paths for every command and file?
- Is the script executable? →
ls -l /path/to/script.sh - Are you checking the right user's crontab? →
crontab -lvssudo crontab -l - Does the schedule mean what you think? → verify at crontab.guru
- Is output being captured anywhere? → add
>> /tmp/job.log 2>&1 - Does the command contain an unescaped
%? - Does the crontab end with a newline?
- Do both day fields conflict? (day-of-month vs day-of-week is an OR)
Nine times out of ten, the answer is in items 1–3. Let's dig into each cause.
First: Determine Whether Cron Started the Job at All
This single distinction cuts your search space in half. Check the cron log:
grep CRON /var/log/syslog | tail -20 # Debian/Ubuntu
sudo grep CRON /var/log/cron | tail -20 # RHEL/CentOS
journalctl -u cron --since "1 hour ago" # any systemd distro
- You see your job in the log → cron is fine; the command is failing. Skip to the environment section.
- No entry at the scheduled time → cron never launched it. The problem is the daemon, the schedule, or the crontab itself.
When Cron Never Launches the Job
The cron daemon isn't running
Rare, but check it first because it explains everything:
systemctl status cron # Debian/Ubuntu
systemctl status crond # RHEL/Fedora
If it's dead, sudo systemctl start cron and sudo systemctl enable cron.
You're looking at the wrong crontab
Each user has a separate crontab, and root's is distinct from yours. A job added under sudo crontab -e will not appear in crontab -l. Check both:
crontab -l
sudo crontab -l
Also remember /etc/crontab and /etc/cron.d/* use a six-field format with a username between the schedule and the command. Pasting a five-field user entry there shifts everything by one word and breaks the job.
The schedule doesn't mean what you think
Two classics:
5 * * * *runs hourly at minute 5 — not every 5 minutes (*/5 * * * *).- Setting both day-of-month and day-of-week creates an OR, not an AND.
0 0 13 * 5fires on the 13th and on every Friday.
Paste your expression into crontab.guru and read the English translation back.
The crontab file is malformed
A missing final newline can cause the last line to be ignored on some cron implementations, and a syntax error can invalidate an entry. Always edit through crontab -e — it validates on save — rather than editing spool files directly.
When Cron Starts the Job but It Fails
This is the more common scenario: syslog shows the job launched, yet nothing happened. The culprit is almost always cron's stripped-down environment.
PATH and environment differences
Your interactive shell has a rich PATH, aliases, and profile scripts. Cron has almost none of that — typically just /usr/bin:/bin. So python3 script.py works at your prompt and dies in cron.
Fixes, in order of preference:
# 1. Absolute paths everywhere
*/10 * * * * /usr/bin/python3 /home/user/app/task.py
# 2. Or set PATH at the top of the crontab
PATH=/usr/local/bin:/usr/bin:/bin
Find any binary's full path with which python3.
Relative paths inside the script
Cron runs jobs from your home directory. A script that does ./data/input.csv or writes output.log in "the current directory" behaves differently under cron. Use absolute paths inside scripts too, or cd explicitly on the first line.
The script isn't executable
chmod +x /home/user/scripts/job.sh
Or sidestep permissions by invoking the interpreter: /bin/bash /home/user/scripts/job.sh.
The % character
Cron treats an unescaped % as a newline and passes everything after it to the command's stdin. This breaks innocent-looking commands:
# Broken
0 0 * * * /usr/bin/tar czf /backups/site-$(date +%F).tgz /var/www
# Fixed
0 0 * * * /usr/bin/tar czf /backups/site-$(date +\%F).tgz /var/www
Make the Job Tell You What's Wrong
Stop guessing — capture the output. Append redirection to the entry:
*/10 * * * * /home/user/scripts/job.sh >> /tmp/job-debug.log 2>&1
Wait for the next run, then read /tmp/job-debug.log. The actual error — command not found, permission denied, a Python traceback — will be sitting right there. Alternatively, set MAILTO=you@example.com at the top of the crontab if the machine can send mail.
To reproduce cron's environment interactively when debugging:
env -i /bin/sh -c '/home/user/scripts/job.sh'
If it fails there, it fails in cron — and now you can iterate quickly.
Best Practices That Prevent the Next Mystery
- Redirect every job's output to a log from day one.
- Use absolute paths reflexively, in the crontab and inside scripts.
- Comment each entry with its purpose and owner.
- Test new jobs on a
* * * * *schedule for a few minutes before setting the real one. - Add monitoring to critical jobs — a silent failure discovered in a log three weeks later is the expensive kind.
Conclusion
When a cron job is not running, split the problem in two with one command: grep CRON /var/log/syslog. If cron never started the job, fix the daemon, the schedule, or the crontab location. If cron started it and it failed, capture the output with >> /tmp/job.log 2>&1 and let the error message do the diagnosis. Absolute paths, output logging, and a syntax check at crontab.guru will resolve the overwhelming majority of cases.
Keep our crontab examples handy for known-good schedules, and consider proper cron monitoring so the next failure alerts you instead of hiding.
Frequently Asked Questions
Why is my cron job not running even though the syntax is correct?
Most likely the environment: cron's PATH is minimal, so commands that work in your shell fail under cron. Use absolute paths for every binary and file, and redirect output to a log to see the real error.
How do I check the cron log?
On Debian/Ubuntu run grep CRON /var/log/syslog; on RHEL-family systems check /var/log/cron; on any systemd distro use journalctl -u cron. These show when jobs start — your own redirection shows whether they succeed.
Why does my script run manually but not in cron?
Because your interactive shell loads a profile, aliases, and a full PATH that cron never sees. Test with env -i /bin/sh -c 'your-command' to simulate cron's bare environment and expose the missing piece.
Does crontab need a newline at the end?
Yes — some cron implementations ignore or reject a final line with no trailing newline. Editing with crontab -e handles this automatically, which is one more reason to avoid editing spool files by hand.
Need the expression itself? Build and test any cron schedule in our free visual generator — with live upcoming-run previews in Unix and Quartz formats.
Related guides
References
- man7.org — cron(8) manual page — daemon behavior and logging
- man7.org — crontab(5) manual page — the % rule, environment handling, and syntax
- Ubuntu Community Help Wiki — CronHowto — distro-specific troubleshooting notes