Common Cron Expression Mistakes to Avoid
Learn the most common cron expression mistakes and how to fix them. Avoid these pitfalls when scheduling tasks with cron to ensure reliable job execution.
Having trouble? Try the tool
Test your with our interactive tool
Top 10 Common Mistakes
Using Relative Paths Instead of Absolute Paths
Symptoms
- • Commands fail with "command not found" errors
- • Scripts execute manually but fail in cron
- • Intermittent failures that depend on current directory
Root Cause
Cron jobs run with a minimal environment and an unpredictable working directory (often the user's home directory or /root). Relative paths depend on the current directory, which is not guaranteed in cron context.
Solution
Always use absolute paths for all commands, scripts, and file references. Explicitly set the working directory if needed using `cd` before your command.
❌ Wrong
# Wrong - uses relative paths
*/5 * * * * python script.py
*/5 * * * * ./scripts/backup.sh
✅ Correct
# Correct - uses absolute paths
*/5 * * * * /usr/bin/python3 /opt/scripts/script.py
*/5 * * * * cd /opt/scripts && ./backup.sh
*/5 * * * * /opt/scripts/backup.sh
Ignoring Environment Variables
Symptoms
- • Scripts work in shell but fail in cron
- • Commands not found despite being in PATH when running manually
- • Applications fail due to missing environment configuration
Root Cause
Cron runs with a severely limited environment - typically only HOME, LOGNAME, SHELL, and a minimal PATH (/usr/bin:/bin). Environment variables from your shell profile (.bashrc, .zshrc) are not loaded.
Solution
Explicitly define required environment variables in the crontab or script. Set PATH, and any application-specific variables needed.
❌ Wrong
# Wrong - assumes shell environment
*/5 * * * * python script.py
*/5 * * * * ./data_process.sh
✅ Correct
# Correct - explicit environment
PATH=/usr/local/bin:/usr/bin:/bin
NODE_ENV=production
DB_HOST=localhost
*/5 * * * * /usr/bin/python3 /opt/scripts/script.py
*/5 * * * * /opt/scripts/data_process.sh
Forgetting to Redirect Output and Errors
Symptoms
- • No way to debug failed cron jobs
- • Output emails sent to system mail (often never read)
- • Disk space fills up with unlogged output
Root Cause
Cron sends any output to the job owner's email by default. Without explicit redirection, errors and logs are lost in email or the void.
Solution
Always redirect stdout and stderr to log files. Use `>>` to append and `2>&1` to redirect both streams.
❌ Wrong
# Wrong - output goes to email or is lost
*/5 * * * * /opt/scripts/check.sh
✅ Correct
# Correct - output logged to file
*/5 * * * * /opt/scripts/check.sh >> /var/log/check.log 2>&1
*/5 * * * * /opt/scripts/check.sh 1>> /var/log/check.out.log 2>> /var/log/check.err.log
Using Both Day of Month and Day of Week
Symptoms
- • Jobs run more frequently than expected
- • Jobs run on unexpected days
- • Confusion about when jobs will execute
Root Cause
In standard cron, if BOTH day of month (1-31) and day of week (0-6) are restricted (not *), the job runs when EITHER field matches. This is a common source of confusion.
Solution
Use `?` or `*` for one of the fields when you want to restrict the other. If you need "the 15th AND only if it's a Monday", implement logic in the script itself.
❌ Wrong
# Wrong - runs on ANY 15th OR ANY Friday
0 0 15 * 5 /script.sh # Runs on the 15th of every month AND every Friday
✅ Correct
# Correct - runs only on Friday the 15th (logic in script)
0 0 * * 5 /scripts/check_friday_15th.sh # Script checks if today is 15th
# OR use modern cron with ? for non-restrictive field
0 0 15 * ? /scripts/monthly.sh # Runs on 15th, day of week ignored
0 0 ? * 5 /scripts/weekly.sh # Runs every Friday, day of month ignored
Missing Execute Permissions on Scripts
Symptoms
- • Cron job fails with "Permission denied"
- • Job is scheduled but never executes
- • No error message or cryptic error in logs
Root Cause
Scripts must have execute permissions (+x) to be run directly. Without execute permissions, the script cannot be invoked by cron.
Solution
Always set execute permissions on scripts with `chmod +x`. Alternatively, call the script with the interpreter explicitly (e.g., `bash script.sh`).
❌ Wrong
# Wrong - script may not be executable
*/5 * * * * /opt/scripts/myscript.sh
✅ Correct
# Correct options:
# 1. Make script executable
$ chmod +x /opt/scripts/myscript.sh
*/5 * * * * /opt/scripts/myscript.sh
# 2. Call with interpreter
*/5 * * * * /bin/bash /opt/scripts/myscript.sh
# 3. Add shebang and make executable
#!/bin/bash
# script content
Incorrect Time Zone Handling
Symptoms
- • Jobs run at the wrong time
- • Jobs run an hour early or late
- • Inconsistent behavior across systems
Root Cause
Cron uses the system's configured time zone. In cloud environments or containers, this may be UTC rather than your local time zone. Time zone changes (DST) can also affect schedules.
Solution
Explicitly set the timezone in crontab with CRON_TZ, or use UTC universally. Document which timezone your cron assumes.
❌ Wrong
# Wrong - assumes system timezone (may vary)
0 9 * * * /scripts/morning_report.sh # Runs at 9 AM, but which timezone?
✅ Correct
# Correct - explicit timezone
CRON_TZ=America/New_York
0 9 * * * /scripts/morning_report.sh # 9 AM Eastern
# OR use UTC and document
# All cron times in UTC
0 14 * * * /scripts/morning_report.sh # 9 AM Eastern = 2 PM UTC
Not Handling Overlapping Jobs
Symptoms
- • Multiple instances of the same job running
- • Resource exhaustion from duplicate processes
- • Data corruption from concurrent writes
- • Race conditions in output files
Root Cause
If a job takes longer than its scheduled interval, cron will start another instance while the first is still running. This leads to overlapping executions.
Solution
Use file locking (flock) or process checking (pgrep) to ensure only one instance runs. For critical jobs, use systemd or supervisord with proper mutex handling.
❌ Wrong
# Wrong - may start overlapping if script runs >5 min
*/5 * * * * /scripts/data_sync.sh
✅ Correct
# Correct - prevents overlapping
# Method 1: flock
*/5 * * * * /usr/bin/flock -w 0 /tmp/data_sync.lock -c /scripts/data_sync.sh
# Method 2: pid check in script
if [ -f /tmp/myscript.pid ]; then
pid=$(cat /tmp/myscript.pid)
if ps -p $pid > /dev/null; then
echo "Already running"
exit 1
fi
fi
echo $$ > /tmp/myscript.pid
trap "rm -f /tmp/myscript.pid" EXIT
Scheduling Resource-Intensive Tasks During Peak Hours
Symptoms
- • System performance degradation during business hours
- • Complaints about slow systems
- • Cron jobs competing with user activity
- • Load spikes at predictable times
Root Cause
Resource-heavy tasks (backups, batch processing, reports) scheduled during peak usage hours compete for CPU, memory, and I/O with active users.
Solution
Schedule resource-intensive jobs during off-peak hours (late night, early morning). Monitor system load and adjust schedules accordingly.
❌ Wrong
# Wrong - heavy backup during business day
0 10 * * * /scripts/heavy_backup.sh # 10 AM - prime time
0 14 * * * /scripts/data_processing.sh # 2 PM - also busy
✅ Correct
# Correct - off-peak scheduling
0 2 * * * /scripts/heavy_backup.sh # 2 AM - minimal activity
0 3 * * 0 /scripts/weekly_report.sh # Sunday 3 AM - weekend
0 6 * * 1 /scripts/monthly_cleanup.sh # Monday 6 AM - before work
# Check system load before running
*/30 * * * * /usr/bin/bash -c '[[ $(cat /proc/loadavg | awk '{print $1}'`) < 2.0 ]] && /scripts/light_task.sh'
Forgetting to Test New Cron Jobs
Symptoms
- • Jobs fail silently in production
- • Syntax errors discovered after deployment
- • Unexpected behavior in cron environment
- • Emergency fixes required at inconvenient times
Root Cause
Cron expressions and scripts that work in a test environment may fail in production due to different paths, environment variables, permissions, or system configurations.
Solution
Always test cron jobs before deploying to production. Test the script manually, test the cron expression syntax, and monitor the first few executions.
❌ Wrong
# Wrong - untested in production
0 0 * * * /scripts/new_feature.sh # Added directly to prod
✅ Correct
# Correct - testing workflow
# 1. Test script manually
$ /scripts/new_feature.sh
# 2. Validate cron syntax
$ crontab -l | grep new_feature
# or use online validator
# 3. Test with a sooner time first
*/5 * * * * /scripts/new_feature.sh # Run every 5 min to test
# Check: tail -f /var/log/new_feature.log
# 4. Once verified, update to target schedule
0 0 * * * /scripts/new_feature.sh
Ignoring Cron Service Status
Symptoms
- • Cron jobs mysteriously stop running
- • No logs or error messages
- • Jobs work after reboot but fail later
- • Unreliable scheduling
Root Cause
The cron or crond service may be stopped, disabled, or malfunctioning. System updates or configuration changes can stop the service without notification.
Solution
Monitor the cron service status and set up alerts. Ensure the service is enabled to start on boot.
❌ Wrong
# Wrong - assume cron is always running
# No monitoring or checks
✅ Correct
# Correct - monitor cron service
# Check service status
$ systemctl status cron
$ systemctl status crond
# Enable on boot
$ sudo systemctl enable cron
$ sudo systemctl start cron
# Monitor with health check
*/15 * * * * /usr/bin/systemctl is-active cron || /usr/bin/systemctl restart cron
# Alert if cron fails
*/15 * * * * /usr/bin/systemctl is-active --quiet cron || echo "Cron stopped!" | mail -s "Alert" [email protected]