How to debug a cron job that isn't running
Cron jobs fail quietly — no error, no output, just a task that never ran. Work through this checklist in order and you'll find the cause.
The maddening thing about cron is that a broken job usually produces nothing at all — no error, no email, no log. Work through these checks in order and you'll almost always find the cause in the first three.
1. Confirm the schedule is what you think
The most common "it's not running" is really "it's not running when I expected". Paste the expression into the parser and check the next run times. Watch for the classic traps: */5 vs 5, the day-of-month / day-of-week OR rule, and the 24-hour clock (midnight is 0, not 24).
2. Read the cron logs
Cron logs every job it starts. Where depends on the distro:
# Debian / Ubuntu
grep CRON /var/log/syslog
# RHEL / Fedora / CentOS
grep CROND /var/log/cron
# systemd-based systems
journalctl -u cron # or -u crond on RHEL
If you see your job being started here, cron is doing its part and the problem is in the command. If you don't see it, the schedule or the crontab itself is the problem — recheck step 1 and that you saved the file with crontab -e.
3. Capture the output
If cron starts the job but it doesn't do its work, you need to see why. Redirect both output streams to a file:
* * * * * /path/to/job >> /tmp/job.log 2>&1
The 2>&1 is the important part — it captures stderr (errors), not just stdout. Alternatively, put MAILTO="you@example.com" at the top of the crontab (if mail is configured) to have output emailed to you.
4. Fix the environment
Cron runs with a minimal environment — this is the single biggest cause of "works in my shell, fails in cron". Cron does not load your .bashrc, .profile or your interactive PATH.
- Use absolute paths for every binary:
/usr/local/bin/node, notnode. - Set any environment variables your script needs explicitly, at the top of the crontab or inside the script.
- Don't assume the working directory —
cdto where you need to be, or use absolute paths throughout.
5. Check permissions and the interpreter
- Is the script executable?
chmod +x /path/to/job. - Does it have a correct shebang (
#!/usr/bin/env bash,#!/usr/bin/python3)? Cron runs commands with/bin/sh, so a script relying on bash features needs the right interpreter line — or call it explicitly:bash /path/to/job. - Does the user whose crontab it is have permission to read the script and everything it touches?
6. Is the cron daemon even running?
Rare, but worth ruling out — especially in minimal containers, which often ship without a running cron daemon:
systemctl status cron # or crond
If it's not active, start and enable it (systemctl enable --now cron). In a Docker container you usually have to start cron yourself in the entrypoint.
The fast debugging loop
Don't wait an hour to test an hourly job. Temporarily set it to run every minute, tail -f your log file, and iterate in real time. Once it works, restore the real schedule. A tight loop turns a frustrating afternoon into five minutes.