Troubleshooting Linux Cron Jobs That Don't Run
Comprehensive guide to diagnosing why cron jobs fail to execute on Linux, covering permissions, PATH, environment variables, and cron service issues.
Troubleshooting Linux Cron Jobs That Don't Run
Cron jobs are supposed to be set-and-forget, but when they silently stop working, debugging can be frustrating. A scheduled data backup cron job on my Lisbon server stopped running for three days before I noticed. This guide covers systematic troubleshooting.
Environment
- OS: Ubuntu 22.04 LTS
- Cron version: cron 3.0pl1
- Use case: Scheduled backup script
$ dpkg -l | grep cron
ii cron 3.0pl1-128ubuntu2 amd64 process scheduling daemonThe Problem
# Check if cron job is set
$ crontab -l
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
# Check if it ran last night
$ grep "backup" /var/log/syslog
# No output - cron job never executed
# Check backup log
$ cat /var/log/backup.log
# Empty or last entry is from 3 days agoAnalysis
Step 1: Verify cron Service is Running
$ sudo systemctl status cron
โ cron.service - Regular background program processing daemon
Loaded: loaded (/lib/systemd/system/cron.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2025-06-10 08:00:00 WET; 2h ago
# If not running
$ sudo systemctl start cron
$ sudo systemctl enable cronStep 2: Check cron Service Logs
# Check cron logs
$ sudo grep CRON /var/log/syslog | tail -20
Jun 10 02:00:00 server CRON[12345]: (root) CMD (/opt/scripts/backup.sh)
Jun 10 02:00:00 server CRON[12345]: (CRON) error (grandchild #12346 failed with exit status 1)
# Or check cron's own log
$ sudo cat /var/log/cron.log
# Some systems use /var/log/cron insteadStep 3: Test the Script Manually
# Run the script as the cron user would
$ sudo -u root /opt/scripts/backup.sh
bash: /opt/scripts/backup.sh: Permission denied
# Check permissions
$ ls -la /opt/scripts/backup.sh
-rw-r--r-- 1 root root 256 Jun 10 08:00 /opt/scripts/backup.sh
# Missing execute permission!Step 4: Check Environment Differences
Cron runs with a minimal environment. Commands that work in your shell may not work in cron:
# Test what cron sees
$ env -i /bin/sh -c 'echo $PATH'
/usr/bin:/bin
# Compare with your shell
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbinStep 5: Check User Permissions
# Check if user has crontab access
$ cat /etc/cron.allow
# If this file exists, only listed users can use cron
$ cat /etc/cron.deny
# If this file exists, listed users cannot use cron
# Check if user is denied
$ grep username /etc/cron.deny
username # User is denied!Solution
Fix 1: Add Execute Permission
$ sudo chmod +x /opt/scripts/backup.sh
$ ls -la /opt/scripts/backup.sh
-rwxr-xr-x 1 root root 256 Jun 10 08:00 /opt/scripts/backup.shFix 2: Use Full Paths in Cron
# BAD: relies on PATH
0 2 * * * backup.sh
# GOOD: full paths to everything
0 2 * * * /usr/bin/bash /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
# Include PATH in crontab
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1Fix 3: Add Environment Variables
# Create environment file
$ cat > /opt/scripts/cron-env << 'EOF'
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
HOME=/root
LANG=en_US.UTF-8
PYTHONPATH=/opt/scripts/lib
EOF
# Use in crontab
0 2 * * * source /opt/scripts/cron-env && /opt/scripts/backup.sh >> /var/log/backup.log 2>&1Fix 4: Fix cron.deny/cron.allow
# Remove user from deny list
$ sudo sed -i '/username/d' /etc/cron.deny
# Or add to allow list
$ echo "username" | sudo tee -a /etc/cron.allowFix 5: Add Error Handling to Scripts
#!/bin/bash
# /opt/scripts/backup.sh
set -euo pipefail
# Log start
echo "$(date): Starting backup"
# Check dependencies
if ! command -v mysqldump &> /dev/null; then
echo "ERROR: mysqldump not found in PATH"
exit 1
fi
# Run backup
mysqldump --all-databases > /data/backup/db-$(date +%Y%m%d).sql
# Log completion
echo "$(date): Backup completed successfully"Common Cron Issues and Fixes
| Issue | Symptom | Fix |
|---|---|---|
| No execute permission | "Permission denied" | `chmod +x script.sh` |
| Wrong PATH | "command not found" | Use full paths in crontab |
| Wrong user | Script runs as wrong user | Check crontab owner |
| Output not logged | Silent failures | Redirect stdout/stderr |
| Cron service stopped | No jobs run | `systemctl start cron` |
| User denied | "You (username) are not allowed" | Edit cron.allow/cron.deny |
Debugging Commands
# Check cron is running
$ systemctl status cron
# View cron jobs for user
$ crontab -l
# View system cron jobs
$ ls -la /etc/cron.d/
$ ls -la /etc/cron.daily/
$ ls -la /etc/cron.hourly/
# Check cron logs
$ sudo grep CRON /var/log/syslog
# Test crontab syntax
$ crontab -l | crontab -
# If no error, syntax is valid
# Check user permissions
$ grep username /etc/cron.allow /etc/cron.deny 2>/dev/nullLessons Learned
- Always use full paths in cron jobs - PATH is minimal in cron environment.
- Redirect output to a log file - silent failures are the hardest to debug.
- Set execute permissions on scripts before adding to crontab.
- Check
/var/log/syslogfor cron execution logs. - Test scripts manually with
env -ito simulate cron's minimal environment.
This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.