Home/Blog/How do I debug cron jobs that aren
Web Development

How do I debug cron jobs that aren

Learn systematic debugging techniques for troubleshooting cron jobs that fail to execute, from checking syntax to diagnosing environment and permission issues.

By Inventive HQ Team
How do I debug cron jobs that aren

Troubleshooting Cron Jobs

One of the most frustrating aspects of cron is that when something goes wrong, there's often little feedback. The job simply doesn't run, leaving you to investigate why. Systematic debugging can quickly identify the issue.

Step 1: Verify Cron Expression Syntax

Start by verifying that your cron expression is valid.

Common Syntax Errors

An invalid cron expression won't run:

# Invalid - only 4 fields instead of 5
0 2 * *

# Valid - 5 fields
0 2 * * *

Test your cron expression using an online validator like crontab.guru or with the crontab -e editor, which will highlight syntax errors.

Check Crontab Format

# View your crontab
crontab -l

# Look for your job
# It should be in format: minute hour day month dayofweek command

If the crontab command doesn't appear, it doesn't exist.

Step 2: Verify Cron Daemon is Running

Cron jobs won't run if the cron daemon isn't running.

# Check if cron daemon is running
systemctl status cron
# or
service cron status

# On macOS
sudo launchctl list | grep cron

# Start cron if not running
sudo systemctl start cron

If cron isn't running, start it:

sudo systemctl start cron
sudo systemctl enable cron  # Enable on reboot

Step 3: Check Cron User Permissions

Your cron jobs run under your user account, and you must have permission to use cron.

# Check if you're allowed to use cron
ls -l /etc/cron.allow /etc/cron.deny 2>/dev/null

# If /etc/cron.allow exists, you must be listed there
cat /etc/cron.allow

# If /etc/cron.deny exists, you must NOT be listed there
cat /etc/cron.deny

If you're not in cron.allow or you're in cron.deny, add yourself:

# Add user to cron.allow
sudo usermod -a -G cron username
# or
sudo echo "username" >> /etc/cron.allow

Step 4: Verify the Command Exists and Works

The most common issue: the command in your cron job doesn't exist or fails when run.

Test the command manually:

# If your crontab contains
0 2 * * * /backup/scripts/daily-backup.sh

# Test it directly
/backup/scripts/daily-backup.sh

# Check exit code (0 = success)
echo $?

If the command fails manually, it will fail in cron too.

Check Script Shebang

Scripts must have a proper shebang line:

#!/bin/bash
# ^ This is required

# Your script content

Without a shebang, the script might fail in cron if the shell isn't specified.

Make Script Executable

# Check if script is executable
ls -l /backup/scripts/daily-backup.sh
# Should show -rwxr-xr-x (x = executable)

# Make it executable if needed
chmod +x /backup/scripts/daily-backup.sh

Step 5: Use Absolute Paths

Cron doesn't have the same PATH environment variable as your shell. Use absolute paths for everything.

# BAD - uses PATH to find commands
0 2 * * * backup.sh

# GOOD - explicit path
0 2 * * * /backup/scripts/daily-backup.sh

# BAD - relies on implicit PATH for commands
0 2 * * * mysqldump > backup.sql

# GOOD - explicit paths
0 2 * * * /usr/bin/mysqldump > /backups/backup.sql

Check Script's Dependencies

# If script uses commands, verify they exist at absolute paths
# In your script, use absolute paths:
#!/bin/bash
/usr/bin/mysqldump ...
/bin/gzip ...
/usr/bin/mail ...

Or explicitly set PATH at the beginning of your crontab:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin

0 2 * * * /backup/scripts/daily-backup.sh

Step 6: Check Cron Logs

Enable and check cron logging:

Linux Cron Logs

# View cron logs (location varies by system)
tail -f /var/log/cron       # CentOS/RHEL
tail -f /var/log/syslog     # Debian/Ubuntu
tail -f /var/log/system.log # macOS

# Search for your specific job
grep "backup" /var/log/cron

# Follow logs in real-time
sudo journalctl -u cron -f

Enable More Verbose Cron Logging

# Edit syslog config
sudo nano /etc/rsyslog.d/50-default.conf

# Uncomment or add cron logging
# cron.* /var/log/cron.log

# Restart rsyslog
sudo systemctl restart rsyslog

Parse Cron Logs

Look for:

  • "CROND[PID]: (username) CMD (command)" - job started
  • Error messages explaining why job failed
  • "Unauthorized" - permission issues
  • "MALFORMED CRONTAB" - syntax error

Step 7: Redirect Output and Errors

Make your cron job log output for debugging:

# Log all output
0 2 * * * /backup/scripts/daily-backup.sh >> /var/log/backup.log 2>&1

# Separate stdout and stderr
0 2 * * * /backup/scripts/daily-backup.sh >> /var/log/backup.log 2>> /var/log/backup-errors.log

# Email output if job fails
0 2 * * * /backup/scripts/daily-backup.sh 2>&1 | mail -s "Backup Report" [email protected]

In your script, explicitly log:

#!/bin/bash
LOG_FILE="/var/log/backup.log"

echo "[$(date)] Backup started" >> "$LOG_FILE"

# Your backup commands
mysqldump ... >> "$LOG_FILE" 2>&1

if [ $? -eq 0 ]; then
  echo "[$(date)] Backup succeeded" >> "$LOG_FILE"
else
  echo "[$(date)] Backup failed" >> "$LOG_FILE"
  exit 1
fi

Step 8: Test Timing

Verify that the time in your cron expression is correct and accounts for time zones.

# Check current time and timezone
date
timedatectl  # Linux
systemsetup -gettimezone  # macOS

# Is your server in UTC?
# Test by scheduling something 1 minute in the future
* * * * * echo "test" >> /tmp/cron-test.log

# Wait a minute, check /tmp/cron-test.log

Step 9: Check Environment Variables

Cron runs with minimal environment variables. Variables set in your shell (.bashrc, .bash_profile) aren't available to cron.

# See what environment cron has
0 * * * * env | sort > /tmp/cron-env.txt

# Compare with your shell
env | sort > /tmp/shell-env.txt
diff /tmp/shell-env.txt /tmp/cron-env.txt

Export required variables at the top of your crontab:

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
HOME=/home/username
[email protected]

0 2 * * * /backup/scripts/daily-backup.sh

Step 10: Run as Root if Needed

If your job needs root privileges:

# View root's crontab (requires sudo)
sudo crontab -l

# Edit root's crontab
sudo crontab -e

# Add your job to root's crontab
0 2 * * * /backup/scripts/daily-backup.sh

Be cautious: root cron jobs can have high impact. Test thoroughly.

Step 11: Check Disk Space

Some jobs fail silently if there's no disk space:

# Check disk usage
df -h

# Check if output directory has space
du -sh /var/log
du -sh /backups

If disk is full, the job can't write output and fails silently.

Step 12: Test with Explicit Time

Set up a temporary cron job to run a few minutes in the future:

# Current time: 14:35
# Schedule for 14:37
37 14 * * * echo "test" >> /tmp/cron-test.log 2>&1

# Wait for the time to pass
# Check /tmp/cron-test.log

This confirms cron is running and can execute commands.

Complete Debugging Checklist

# 1. Validate syntax
crontab -e  # Editor should not show errors

# 2. Verify daemon
systemctl status cron

# 3. Check logs
tail -f /var/log/cron

# 4. Test command
/backup/scripts/daily-backup.sh

# 5. Check permissions
ls -l /backup/scripts/daily-backup.sh
# Should show executable (x)

# 6. Verify paths
which mysqldump  # Ensure command exists
# Use absolute path

# 7. Check environment
0 * * * * env > /tmp/cron-env.log

# 8. Verify time
date
timedatectl

# 9. Test with explicit output
0 * * * * echo "test" >> /tmp/cron-test.log 2>&1

# 10. Check disk space
df -h

Common Issues and Solutions

IssueCauseSolution
Command not foundRelative path usedUse absolute path
Permission deniedFile not executablechmod +x script
No outputPaths/variables wrongAdd logging with absolute paths
Runs but failsDependencies missingVerify all commands exist
Wrong timeTimezone/syntaxCheck date, validate expression
MALFORMED CRONTABSyntax errorCheck for exactly 5 fields
Not running at allCron daemon stoppedsystemctl start cron

Systematic debugging typically reveals the issue quickly. The most common problems are wrong paths, missing permissions, and syntactical errors. By following these steps, you can identify and fix almost any cron issue.

Need Expert IT & Security Guidance?

Our team is ready to help protect and optimize your business technology infrastructure.