AI-TOL
📚 Complete Guide 🕐 15 min read 📊 Intermediate ✓ Updated 2026-02-08

Complete Guide to Cron Expressions - Master Cron Job Scheduling 2026

Master cron expressions with this comprehensive guide. Learn complete syntax, 10 real-world examples, debugging tips, and 2026 best practices. Perfect for developers and DevOps engineers.

Learn by doing

Practice with the Cron Expression Generator while reading - free, no registration required

Open Cron Expression Generator →

Cron is one of the most powerful and widely used scheduling tools in Unix/Linux systems. Whether you're automating backups, generating reports, or running periodic maintenance tasks, understanding cron expressions is essential for any developer or system administrator.

This comprehensive guide will take you from beginner to expert in cron job scheduling. You'll learn the complete syntax, discover time-saving shortcuts, avoid common pitfalls, and master advanced techniques that most developers never learn.

By the end of this guide, you'll be able to create complex scheduling patterns with confidence, troubleshoot issues like a pro, and follow industry-standard best practices for production environments.

Understanding Cron Syntax

A cron expression is a string of 5 or 6 fields separated by spaces. Each field represents a unit of time, and the combination determines when the scheduled task will run.

Basic Format

The standard cron format consists of 5 fields: minute, hour, day of month, month, and day of week. This format is used by most Unix/Linux systems in their crontab files.

Extended Format

Some systems support a 6-field format that includes seconds as the first field. This is commonly used in Kubernetes CronJobs and modern schedulers like AWS EventBridge.

The 5 Cron Fields

Each field in a cron expression has a specific range and meaning. Understanding these fields is fundamental to writing accurate cron expressions.

Field Format

                  * * * * *
│ │ │ │ │
│ │ │ │ └─ Day of week (0-7, 0 and 7 = Sunday)
│ │ │ └───── Month (1-12)
│ │ └───────── Day of month (1-31)
│ └──────────── Hour (0-23)
└─────────────── Minute (0-59)
                

Special Characters

Cron expressions use special characters to define flexible scheduling patterns. Mastering these characters allows you to create complex schedules with minimal effort.

Asterisk (*)

The asterisk means "every" or "all values" in that field. For example, * in the hour field means "every hour".

Slash (/)

The slash is used to define steps or intervals. */5 means "every 5 units". Combined with *, it creates repeating patterns.

Comma (,)

The comma separates multiple values. 1,3,5 means "at 1, 3, and 5". Useful for specifying specific times.

Hyphen (-)

The hyphen defines a range. 1-5 means "from 1 through 5 inclusive". Can be combined with other characters.

Question Mark (?)

Used only in the day of week field in some cron implementations. It means "no specific value" and is typically used with day of month.

Predefined Expressions

Cron includes special keywords that replace complex numeric expressions. These shortcuts make common schedules more readable and easier to maintain.

Common Predefined Keywords

                  @yearly (or @annually)  = Run once a year at midnight January 1
                    = 0 0 1 1 *
@monthly              = Run once a month at midnight on first day
                    = 0 0 1 * *
@weekly              = Run once a week at midnight on Sunday
                    = 0 0 * * 0
@daily (or @midnight) = Run once a day at midnight
                    = 0 0 * * *
@hourly              = Run once an hour at the beginning of the hour
                    = 0 * * * *
@reboot              = Run once at startup (not time-based)
                

Real-World Examples

These examples demonstrate practical cron expressions used in production environments. Each example solves a specific scheduling challenge.

Database Backup - Daily at 2 AM

                  # crontab entry
0 2 * * * /usr/bin/pg_dump mydb > /backups/db_$(date +\%Y\%m\%d).sql
                

Log Cleanup - Weekly on Sunday

                  # crontab entry
0 3 * * 0 find /var/log/*.log -mtime +30 -delete
                

Report Generation - First Day of Month

                  # crontab entry
0 8 1 * * /usr/bin/python3 /scripts/generate_monthly_report.sh
                

Health Check - Every 5 Minutes

                  # crontab entry
*/5 * * * * curl -f http://localhost:8080/health || echo "Service down" | mail -s "Alert" [email protected]
                

Data Sync - Hourly

                  # crontab entry
0 * * * * /usr/bin/rsync -av /data/ backup@remote:/data
                

Cache Clear - Weekdays at 6 PM

                  # crontab entry
0 18 * * 1-5 /usr/bin/redis-cli FLUSHALL
                

Email Report - Every Friday at 4 PM

                  # crontab entry
0 16 * * 5 /usr/bin/sendemail "Weekly Report" < [email protected]
                

Temporary Task - Only in March

                  # crontab entry
0 12 * 3 * /scripts/maintenance_task.sh
                

Multiple Times - 6 AM, 2 PM, 8 PM

                  # crontab entry
0 6,14,20 * * * /scripts/check_status.sh
                

Complex Interval - Every 15 Minutes on Weekdays

                  # crontab entry
*/15 * * * 1-5 /scripts/business_hours_check.sh
                

Debugging Cron Jobs

When a cron job doesn't run as expected, systematic debugging saves hours of frustration. Follow this structured approach to identify and fix issues quickly.

Check Cron Syntax

Validate your cron expression using online tools or the crontab -l command. Even a single space or wrong character can prevent execution.

Verify File Permissions

Ensure the script is executable (chmod +x) and has proper read/write permissions. Cron jobs run with limited user privileges.

Check System Logs

Review /var/log/syslog or /var/log/cron for error messages. These logs often reveal permission issues, missing commands, or execution failures.

Test Environment Variables

Cron jobs run with a minimal environment. Always use full paths for commands and explicitly set required environment variables in the crontab or script.

Verify Timezone

Cron uses UTC by default. Convert your local time to UTC or set the TZ environment variable in your crontab file.

Cron Variants

Different systems implement cron differently. Understanding these variants helps you work across various platforms and tools.

Traditional Unix Cron

The original cron system uses the 5-field format and is configured via /etc/crontab files. It's reliable and available on all Unix/Linux systems.

Systemd Timers

Modern Linux distributions use systemd timers as an alternative to cron. They offer more precise scheduling, better logging, and dependency management between services.

Kubernetes CronJob

Kubernetes implements cron-like scheduling with additional features like concurrency policies, deadlines, and suspensions. Uses a 6-field format including seconds.

Quartz Scheduler

Popular in Java applications, Quartz offers cron-like expressions with additional features for enterprise scheduling, job persistence, and clustering.

2026 Best Practices

Follow these industry-standard practices to create reliable, maintainable, and secure cron jobs.

Always Use Absolute Paths

Specify full paths to scripts and commands to avoid issues with limited cron environment PATH.

Redirect Output to Logs

Always redirect both stdout and stderr to log files for troubleshooting: >> /var/log/job.log 2>&1

Set MAILTO Variable

Configure email notifications for cron job failures: [email protected] in your crontab file.

Use Lock Files

Prevent overlapping executions for long-running jobs with lock files using flock or similar mechanisms.

Add Comments

Document what each cron job does, why it runs at that time, and who to contact for issues. This helps future maintenance.

Test Before Deploying

Always test your script manually before scheduling it with cron. This catches syntax errors and logic issues early.

Quick Reference

Keep this handy reference nearby when working with cron expressions. It covers the most common patterns and their meanings.

Real-World Examples

Case Study 1: Automated Database Backup

Problem

A startup needed reliable daily backups of their PostgreSQL database, but the backup script failed randomly when run through cron.

Solution

The issue was that pg_dump required environment variables (PGPASSWORD, PGUSER) that weren't set in the cron environment. Fixed by adding environment variables in the crontab file and using absolute paths.


                  0 2 * * * /usr/bin/env PGPASSWORD=pass /usr/bin/pg_dump -U user mydb > /backups/db.sql 2>&1
                

Case Study 2: Server Health Monitoring

Problem

Health check script ran successfully manually but failed when scheduled with cron.

Solution

Discovered that the script used curl to check http://localhost:8080/health, but the service wasn't running when cron executed (3 AM UTC, before service startup). Fixed by adding service startup check and timeout handling.


                  */5 * * * * /usr/bin/curl -f --max-time 10 http://localhost:8080/health || echo "Service not running" | /usr/bin/logger -t health_check
                

Case Study 3: Log Rotation with Retention

Problem

Server disk filled up because old logs weren't being deleted despite having a cleanup job in cron.

Solution

The log cleanup job ran correctly but used wrong mtime parameters. Was using -mtime +30 (files older than 30 days) but the script created logs in a way that reset modification times. Fixed by using -ctime instead and adding log rotation in the application itself.


                  0 3 * * * find /var/log/app/*.log -ctime +30 -delete -print 2>&1 | tee -a /var/log/cleanup.log
                

Best Practices

Use Absolute Paths

Always specify complete paths to avoid PATH issues in cron's minimal environment

✓ Do: /usr/local/bin/python3 /scripts/task.sh

✗ Don't: python3 /scripts/task.sh

Redirect All Output

Capture both stdout and stderr to logs for debugging and auditing

✓ Do: /script.sh >> /var/log/script.log 2>&1

✗ Don't: /script.sh

Set Lock Files

Prevent overlapping executions that could cause data corruption

✓ Do: flock -n /tmp/script.lock -c "/script.sh"

✗ Don't: /script.sh & (allow overlaps)

Add Comments

Document purpose, owner, and last modified date for maintainability

✓ Do: # Daily database backup - Contact: [email protected] - Modified: 2026-02-08

✗ Don't: (no comments)

Test Timezone

Verify cron executes in the expected timezone

✓ Do: CRON_TZ=America/New_York 0 9 * * * /script.sh

✗ Don't: 0 9 * * * /script.sh (may use unexpected timezone)

Use Lock Files

Prevent cron from running if previous instance still active

✓ Do: */15 * * * * /usr/bin/flock -xn /tmp/myjob.lock -c "/path/to/job.sh"

✗ Don't: */15 * * * * /path/to/job.sh (runs even if previous still running)

Quick Checklist

Before Creating Cron Job

  • Test script manually to verify it works
  • Use absolute paths for all commands and files
  • Set appropriate file permissions (chmod +x)
  • Add shebang line (#!/bin/bash or #!/usr/bin/env python3)
  • Test with different user if needed

When Adding to Crontab

  • Validate cron expression syntax
  • Set MAILTO variable for error notifications
  • Add descriptive comments
  • Set correct timezone with CRON_TZ if needed
  • Add output redirection to log file
  • Use full paths in commands

After Deployment

  • Check logs for first execution
  • Verify output files are created
  • Monitor system resources usage
  • Test backup/restore procedures
  • Document job purpose and maintenance procedures
  • Set up monitoring/alerts for failures

Maintenance

  • Review cron logs weekly
  • Update scripts and dependencies
  • Rotate and archive log files
  • Test disaster recovery procedures
  • Update documentation when making changes

Frequently Asked Questions

What's the difference between */5 and 0/5 in cron?
*/5 means "every 5 units" (every 5 minutes), while 0/5 is invalid syntax. The */n format is the standard way to define intervals in cron expressions. Some systems support "step values" with /, but it always follows the asterisk or a range (e.g., 1-10/2 means every 2 starting from 1 through 10).
How do I run a cron job every 30 seconds?
Traditional cron doesn't support sub-minute intervals. The minimum granularity is 1 minute. For 30-second intervals, you have several options: 1) Use systemd timers with OnUnitSec=30sec, 2) Create two cron jobs (one at :00, one at :30), or 3) Use a modern scheduler like Kubernetes CronJob with seconds precision.
Why is my cron job one hour off?
This is almost always a timezone issue. Cron uses UTC by default, while your server might be configured for a different timezone. Solutions: 1) Convert your desired time to UTC, 2) Set CRON_TZ="Your/Timezone" in crontab, or 3) Change the system timezone (not recommended). Always check with `date` command first to see current server time.
Can I run a cron job as a specific user?
Yes! You can create user-specific crontabs with `crontab -e -u username` (as root), or edit /etc/crontab for system-wide jobs with User=username field. User-specific crontabs are stored in /var/spool/cron/crontabs/ and are generally preferred for security and isolation.
How do I schedule a job on the last day of every month?
This is tricky because months have different lengths. The most reliable solution is to schedule for the 31st and let cron handle months without 31 days: `0 2 31 * * command`. Alternatively, you can use a wrapper script that checks if tomorrow is the 1st of next month and only runs the main command if true.
What happens if my system is off during a scheduled cron time?
Traditional cron will skip the missed execution entirely - it won't run "catch up" when the system comes back online. If you need reliable execution regardless of downtime, consider using anacron or systemd timers with persistent state. For critical jobs, implement idempotency so you can safely run them more frequently or on-demand.
How can I see all scheduled cron jobs?
Use `crontab -l` to list current user's crontab. For system-wide crontab (located in /etc/crontab), use `sudo cat /etc/crontab`. To list all users' crontabs, check /var/spool/cron/crontabs/ or use `sudo crontab -u username -l` for specific users.
Is cron secure for production environments?
Cron is secure when configured correctly, but has risks: 1) Scripts run with elevated privileges in system crontab, 2) Cron jobs can expose sensitive data in logs, 3) Weak permissions on scripts can be exploited. Best practices: Use user-specific crontabs when possible, restrict script permissions, avoid passing passwords in command lines (use environment files), regularly audit scheduled jobs, and ensure logs don't contain sensitive data.
How do I temporarily disable a cron job without deleting it?
Comment out the line in crontab by adding # at the beginning: `# 0 2 * * * /script.sh`. Alternatively, rename the crontab file temporarily: `mv /etc/crontab /etc/crontab.disabled`. Remember to uncomment or restore it when you want to re-enable the job.
Can cron jobs run in parallel?
Yes, cron can run multiple jobs simultaneously. Each job is independent and executes in its own process. However, be careful with resource-intensive jobs running at the same time - you might overwhelm your server. For jobs that shouldn't overlap, use lock files (flock) or job management systems to prevent concurrent execution.

Further Reading

Master Cron Expression Generator Today

Put your knowledge into practice with our free, privacy-focused tools

Try Cron Expression Generator →