← Back to Blog
Automation DevOps 14 min read

Cron Expressions: Complete Developer Guide

Learn cron expression syntax, scheduling patterns, best practices, and implementation guidelines for task automation and job scheduling.

What are Cron Expressions?

Cron expressions are strings used to schedule tasks to run periodically at fixed times, dates, or intervals. Originally developed for Unix systems, cron expressions are now used across many platforms and scheduling systems.

// Basic cron expression format
* * * * * command_to_execute
│ │ │ │ └── Day of week (0-7, where 0 and 7 = Sunday)
│ │ │ └──── Month (1-12)
│ │ └────── Day of month (1-31)
│ └──────── Hour (0-23)
└────────── Minute (0-59)

Cron expressions provide a powerful way to automate repetitive tasks like backups, data processing, report generation, and system maintenance.

Cron Expression Syntax

Field Definitions

Field Allowed Values Special Characters
Minute 0-59 * , - /
Hour 0-23 * , - /
Day of Month 1-31 * , - / ? L W
Month 1-12 or JAN-DEC * , - /
Day of Week 0-7 or SUN-SAT (0/7 = Sunday) * , - / ? L #

Special Characters

Basic Characters

  • * (asterisk): Any value
  • , (comma): Value list separator
  • - (hyphen): Range of values
  • / (slash): Step values

Advanced Characters

  • ? (question): No specific value (day of month/week)
  • L (last): Last day of month/week
  • W (weekday): Nearest weekday
  • # (hash): Nth day of month

Common Cron Patterns

Basic Scheduling

Expression Description Example
0 * * * * Every hour at minute 0 Hourly tasks
0 0 * * * Daily at midnight Daily backups
0 0 * * 0 Weekly on Sunday Weekly reports
0 0 1 * * Monthly on 1st day Monthly billing
*/15 * * * * Every 15 minutes Monitoring checks
0 9-17 * * 1-5 Hourly on weekdays 9AM-5PM Business hours tasks

Advanced Patterns

// Complex cron examples // Every 10 minutes during business hours on weekdays */10 9-17 * * 1-5 // At 30 minutes past the hour every 6 hours 30 */6 * * * // At 5:30 PM on the last day of every month 30 17 L * * // At 9:00 AM on the 15th day of every month 0 9 15 * * // Every Monday at 8:00 AM 0 8 * * 1 // Every day at 1:30 AM and 1:30 PM 30 1,13 * * * // Every 5 minutes from 9 AM to 5 PM on weekdays */5 9-17 * * 1-5 // First Monday of every month at 10:00 AM 0 10 * * 1#1

Implementation Examples

1. Linux/Unix crontab

# Edit crontab crontab -e # Example crontab entries # Backup database daily at 2:30 AM 30 2 * * * /usr/bin/mysqldump -u root -pPASSWORD database > /backups/db-$(date +\%Y\%m\%d).sql # Clean temp files every Sunday at 3:00 AM 0 3 * * 0 rm -rf /tmp/* # Monitor disk space every hour 0 * * * * /usr/local/bin/check-disk-space.sh # Sync logs every 15 minutes */15 * * * * rsync -avz /var/log/ remote-server:/backups/logs/ # Send daily report at 6:00 PM 0 18 * * * /usr/local/bin/send-daily-report.sh

2. Node.js with node-cron

const cron = require('node-cron'); // Run every minute cron.schedule('* * * * *', () => { console.log('Running every minute'); }); // Run daily at midnight cron.schedule('0 0 * * *', () => { console.log('Running daily backup'); performBackup(); }); // Run every 30 minutes during business hours cron.schedule('*/30 9-17 * * 1-5', () => { console.log('Checking for new emails'); checkEmails(); }); // Run on specific days cron.schedule('0 8 * * 1,3,5', () => { console.log('Monday, Wednesday, Friday morning task'); generateReports(); }); // Complex: First day of month at 9 AM cron.schedule('0 9 1 * *', () => { console.log('Monthly billing process'); processBilling(); });

3. Python with schedule

import schedule import time def job(): print("I'm working...") # Schedule examples schedule.every(10).minutes.do(job) schedule.every().hour.do(job) schedule.every().day.at("10:30").do(job) schedule.every().monday.do(job) schedule.every().wednesday.at("13:15").do(job) schedule.every().minute.at(":17").do(job) # Cron-style scheduling with python-crontab from crontab import CronTab cron = CronTab(user=True) job = cron.new(command='python /path/to/script.py') job.setall('0 0 * * *') # Daily at midnight cron.write()

Best Practices

Scheduling Best Practices:
  • Stagger execution times: Avoid running all jobs at the same time (e.g., midnight)
  • Consider timezones: Always specify timezone in cron configuration
  • Log job execution: Log start, end, and any errors for debugging
  • Implement job locking: Prevent overlapping job execution
  • Monitor job health: Set up alerts for failed jobs

1. Error Handling and Monitoring

// Example: Robust cron job with error handling const cron = require('node-cron'); const logger = require('./logger'); const { sendAlert } = require('./alerts'); cron.schedule('0 2 * * *', async () => { const jobId = `backup-${Date.now()}`; try { logger.info(`Starting backup job: ${jobId}`); // Perform backup await performBackup(); logger.info(`Backup job completed: ${jobId}`); } catch (error) { logger.error(`Backup job failed: ${jobId}`, { error: error.message }); // Send alert await sendAlert({ type: 'cron_failure', job: 'daily_backup', error: error.message, timestamp: new Date().toISOString() }); // Optionally retry await retryBackup(); } });

2. Job Locking (Prevent Overlaps)

// Using file-based locking const fs = require('fs'); const path = require('path'); function withLock(jobName, fn) { const lockFile = path.join('/tmp', `${jobName}.lock`); // Check if lock exists if (fs.existsSync(lockFile)) { const lockTime = fs.statSync(lockFile).mtime; const age = Date.now() - lockTime.getTime(); // If lock is older than 1 hour, assume stale and remove if (age > 60 * 60 * 1000) { fs.unlinkSync(lockFile); } else { console.log(`Job ${jobName} is already running`); return; } } // Create lock file fs.writeFileSync(lockFile, process.pid.toString()); try { // Execute job return fn(); } finally { // Remove lock file fs.unlinkSync(lockFile); } } // Usage cron.schedule('*/5 * * * *', () => { withLock('data-sync', () => { syncData(); }); });

Common Pitfalls and Solutions

Common Issues:
  • Timezone confusion: Cron uses system timezone
  • Day of week vs day of month: Use ? for one when specifying the other
  • February 30th: Cron will skip invalid dates
  • Environment variables: Cron jobs run with minimal environment
  • Permission issues: Cron runs as user who owns crontab

1. Environment Variables

# Bad: PATH may not include needed binaries * * * * * some-command # Good: Set PATH in crontab PATH=/usr/local/bin:/usr/bin:/bin # Better: Source environment or use full paths * * * * * /usr/local/bin/my-script.sh # Best: Create wrapper script that sets environment * * * * * /path/to/wrapper.sh

2. Logging and Output

# Bad: No logging, errors go to email (may be ignored) * * * * * /path/to/script.sh # Good: Redirect output to log file * * * * * /path/to/script.sh >> /var/log/script.log 2>&1 # Better: Separate stdout and stderr * * * * * /path/to/script.sh >> /var/log/script.log 2>> /var/log/script.error.log # Best: Use logger command for syslog * * * * * /path/to/script.sh 2>&1 | logger -t myscript

Tools and Resources

DailyTools.uk Cron Tool

Use our Cron Expression Parser Tool to:

  • Parse and validate cron expressions
  • Get human-readable explanations
  • Test scheduling patterns
  • Generate cron expressions from natural language

External Resources

Conclusion

Cron expressions are a powerful tool for automating repetitive tasks, but they require careful implementation to avoid common pitfalls. Key takeaways:

Essential Practices:
  • Always validate cron expressions before deployment
  • Implement proper logging and error handling
  • Use job locking to prevent overlapping execution
  • Set up monitoring and alerts for failed jobs
  • Consider timezone implications for global systems
  • Test cron expressions thoroughly in staging environments

For complex scheduling needs, consider using more advanced job schedulers like Airflow, Celery, or Quartz that offer features like dependency management, retries, and distributed execution.

Remember that while cron is reliable for simple scheduling, it's not designed for complex workflows or high-availability systems. For production-critical jobs, implement redundancy and failover mechanisms.