Cron Debugging: 7 Common Issues and How to Fix Them

May 26, 20268 min read

Introduction

Cron jobs are the backbone of automated tasks in Unix-like systems, but they're notoriously difficult to debug when things go wrong. The silent nature of cron—running in the background without user interaction—means issues often go unnoticed until something breaks spectacularly.

This guide covers the seven most common cron debugging scenarios, complete with real-world examples and proven fixes.

1. Timezone Mismatch Issues

The Problem: Your cron job runs at the wrong time because the system timezone differs from your expectation.

Wrong approach:

# You think this runs at 9 AM EST, but server is in UTC
0 9 * * * /home/user/backup-script.sh

The fix:

# Check system timezone
timedatectl | grep "Time zone"

# Check cron's timezone interpretation
cat /etc/timezone

# If needed, set TZ variable in crontab
TZ=America/New_York
0 9 * * * /home/user/backup-script.sh

Debugging steps:

  1. Add TZ=UTC date to your cron job temporarily to log what time cron thinks it is
  2. Compare with date command output in your terminal
  3. Remember: cron doesn't read your shell's TZ environment variable

2. Day-of-Month + Day-of-Week Logic Confusion

The Problem: The man 5 crontab page states these fields have OR logic, not AND—a common source of confusion.

The misconception:

# Many think this runs "on the 15th AND on Mondays"
# Actually runs "on the 15th OR on Mondays"
0 0 15 * 1 /home/user/script.sh

The fix for AND logic:

# Use a conditional check inside the script
0 0 * * 1 /home/user/script.sh  # Runs every Monday

# Then inside script.sh:
#!/bin/bash
if [ "$(date +\%d)" -eq 15 ]; then
    # Actually do the work
    echo "Running because it's the 15th AND a Monday"
fi

3. Missing Environment Variables

The Problem: Cron runs with a minimal PATH and no user environment variables. Scripts work in terminal but fail in cron.

The error you'll see in logs:

/home/user/script.sh: line 5: python3: command not found

The fix (Option A - Set in crontab):

# Add at the top of crontab
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin

# Or set full PATH for specific commands
0 * * * * PATH=/usr/local/bin:/usr/bin:/bin python3 /home/user/script.py

The fix (Option B - Set in script):

#!/bin/bash
# At the top of your script
export PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin

# Now use commands
python3 /path/to/script.py

Debugging tip: Add env command to a cron job and check the output:

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

4. Output Not Redirected

The Problem: Cron sends email for every output line, which either floods your mailbox or gets silently discarded if no MTA is configured.

The silent failure:

# This might email you or do nothing
0 2 * * * /home/user/backup.sh

The fix:

# Redirect stdout and stderr to a log file
0 2 * * * /home/user/backup.sh >> /var/log/backup.log 2>&1

# Or redirect to /dev/null if you don't need output
0 2 * * * /home/user/backup.sh > /dev/null 2>&1

# For timestamped logs
0 2 * * * /home/user/backup.sh >> /var/log/backup.log 2>&1 && echo "$(date): Backup completed" >> /var/log/backup.log

5. Relative Path Problems

The Problem: Scripts use relative paths that work in your current directory but fail when cron runs from cron's home directory (usually /).

The broken script:

#!/bin/bash
# This works when you're in /home/user/project/
python3 main.py  # Looks for ./main.py
cat data.txt     # Looks for ./data.txt

The fix (Option A - cd first):

#!/bin/bash
cd /home/user/project || exit 1
python3 main.py
cat data.txt

The fix (Option B - Absolute paths):

#!/bin/bash
python3 /home/user/project/main.py
cat /home/user/project/data.txt

The fix (Option C - In crontab):

0 2 * * * cd /home/user/project && ./script.sh

6. Percent Signs in Crontab

The Problem: The percent sign % is a special character in crontab—it gets replaced with a newline. This breaks date formatting commands.

The broken cron entry:

# This will NOT work as expected
0 0 * * * tar -czf backup-$(date +%Y-%m-%d).tar.gz /home/user/data

The fix (escape the percent signs):

# Escape each % with \
0 0 * * * tar -czf backup-$(date +\%Y-\%m-\%d).tar.gz /home/user/data

Better fix (use a script):

# In crontab - call a script instead
0 0 * * * /home/user/backup-wrapper.sh

# In backup-wrapper.sh
#!/bin/bash
tar -czf "backup-$(date +%Y-%m-%d).tar.gz" /home/user/data

7. Permission and Ownership Issues

The Problem: Cron jobs run as the user who owns the crontab, but file permissions may prevent access to required resources.

Common symptoms:

  • "Permission denied" errors in logs
  • Script works when manually run with sudo, but fails in cron
  • Cannot write to log files or output directories

The fix:

# Check what user the cron runs as
* * * * * whoami > /tmp/cron-user.txt

# Ensure script is executable
chmod +x /home/user/script.sh

# Ensure log directory is writable
touch /var/log/my-script.log
chmod 644 /var/log/my-script.log

# If you need root privileges, use root's crontab
sudo crontab -e  # Edit root's crontab

# Or use sudo in the cron job (configure sudoers appropriately)
0 2 * * * sudo /home/user/root-required-script.sh

Debugging Workflow

When a cron job isn't working, follow this systematic approach:

  1. Check cron is running:
    systemctl status cron  # or crond on some systems
    ps aux | grep cron
    
  2. Check cron logs:
    grep CRON /var/log/syslog      # Debian/Ubuntu
    grep CRON /var/log/cron        # RHEL/CentOS
    journalctl -u cron -f          # systemd systems
    
  3. Test your command manually:
    # Simulate cron's environment
    env -i SHELL=/bin/sh PATH=/usr/bin:/bin /bin/sh -c "your-command-here"
    
  4. Add logging to your script:
    #!/bin/bash
    exec >> /tmp/my-script-debug.log 2>&1
    echo "Script started at $(date)"
    set -x  # Enable command tracing
    # ... your script content ...
    

Quick Reference: Common Cron Debug Commands

CommandPurpose
crontab -lList current user's cron jobs
crontab -eEdit current user's cron jobs
grep CRON /var/log/syslogCheck cron execution logs
systemctl status cronVerify cron daemon is running
env -i /bin/sh -c "cmd"Test command with minimal environment
  • Cron Parser - Decode any cron expression and see next run times