How to Debug Cron Jobs That Aren't Running
Cron jobs fail silently by default — no error, no output, nothing. This guide walks through every common reason a cron job stops working, from the obvious (it's not enabled) to the subtle (PATH vs. your terminal PATH).
Quick Debugging Checklist
- cron daemon is running (`systemctl status cron`)
- crontab has no syntax errors — validated in /debugger
- output is redirected to a log file (`>> /tmp/cron.log 2>&1`)
- all paths in the command are absolute
- the script file is executable (`chmod +x`)
- required environment variables are set in the crontab
- the server timezone matches your expected schedule
- cron logs show the job being triggered
Check if cron is running
First verify the cron daemon itself is active.
systemctl status cron
# Debian/Ubuntu
systemctl status crond
# RHEL/CentOS/Fedora
ps aux | grep cron
# Any Linux — look for a cron process
Verify cron is logging
Enable cron logs if they're disabled, then tail them live.
tail -f /var/log/syslog | grep CRON
# Debian/Ubuntu
tail -f /var/log/cron
# RHEL/CentOS
journalctl -u cron -f
# systemd systems
Check the crontab syntax
Open your crontab and verify the expression is valid.
crontab -e
# Edit your crontab
crontab -l
# List current entries
Capture cron output
By default, cron discards stdout and stderr (or mails them). Redirect output to a log file to see what's happening.
* * * * * /path/to/script.sh >> /tmp/cron.log 2>&1
# Redirect stdout + stderr to a file
* * * * * /path/to/script.sh 2>/tmp/cron-errors.log
# Redirect only stderr
Fix PATH issues — the #1 cause of failures
Cron runs with a minimal PATH: usually `/usr/bin:/bin`. Commands that work in your terminal (node, python3, npm, docker) may not be found by cron.
which node
# Find the full path to a binary
PATH=/usr/local/bin:/usr/bin:/bin
# Add this line at the top of your crontab
* * * * * /usr/local/bin/node /home/user/app/script.js
# Use absolute paths in the command
Check environment variables
Cron does not load your shell's environment. Variables set in `.bashrc`, `.profile`, or `.zshrc` are NOT available to cron jobs.
MYVAR=value * * * * * /path/script.sh
# Define variables at the top of the crontab
* * * * * . /home/user/.bashrc && /path/script.sh
# Source your profile (careful with interactive-only items)
* * * * * env -i HOME=/home/user /path/script.sh
# Explicit clean environment
Verify file permissions
The script must be executable by the user running the cron job.
ls -la /path/to/script.sh
# Check file permissions
chmod +x /path/to/script.sh
# Make the script executable
ls -la /path/to/
# The directory must also be accessible by the cron user
Test the command directly as the cron user
Simulate the cron environment by running the command as the same user and with a minimal environment.
sudo -u cronuser env -i HOME=/home/cronuser /path/script.sh
# Run as the cron user, clean env
su -s /bin/sh cronuser -c '/path/script.sh'
# Alternative: switch user and run
Check for timezone/timing mismatches
Cron uses the system clock in the system timezone. If you expect 9 AM local time but the server is UTC, your job fires at the wrong time.
date
# Shows current server time + timezone
timedatectl
# Shows timezone info on systemd systems
TZ=America/New_York 0 9 * * * /path/script.sh
# Set timezone per-crontab (supported on modern cron)
Common Error Patterns
Validate your cron expression
Use our free Debugger to validate syntax, see plain-English descriptions, and preview the next 10 run times — all in the browser.