AI-TOL
🔧 Troubleshooting 🕐 10 min read 10 Common Mistakes

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

Open →

Top 10 Common Mistakes

🚨
Mistake #1 CRITICAL

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
                    
🚨
Mistake #2 CRITICAL

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
                    
⚠️
Mistake #3 HIGH

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
                    
⚠️
Mistake #4 HIGH

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
                    
🚨
Mistake #5 CRITICAL

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
                    
⚠️
Mistake #6 HIGH

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
                    
Mistake #7 MEDIUM

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
                    
Mistake #8 MEDIUM

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'
                    
Mistake #9 MEDIUM

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
                    
🚨
Mistake #10 CRITICAL

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]
                    

Still Having Trouble?

Try the interactive tool to test and debug

Open →