DevOps

Understanding Cron Expressions for Scheduled Tasks

Master cron scheduling: reading and writing cron expressions, common patterns, and avoiding scheduling pitfalls.

HandyUtils January 4, 2026 5 min read

Cron is the time-based job scheduler in Unix-like systems. Whether you're scheduling backups, sending reports, or running maintenance tasks, understanding cron expressions is essential.

What is Cron?

Cron runs scheduled commands at specified times. The schedule is defined using a cron expression—a string of five (or six) fields representing when to run.

A cron job entry looks like:

30 4 * * * /path/to/script.sh

This runs script.sh at 4:30 AM every day.

Cron Expression Format

The standard cron expression has five fields:

┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 6) (Sunday = 0)
│ │ │ │ │
* * * * * command

Each field accepts:

  • A specific value: 5
  • A range: 1-5
  • A list: 1,3,5
  • A step: */15 (every 15)
  • An asterisk: * (any value)

Minutes, Hours, Days, Months, Weekdays

Minutes (0-59)

0 * * * *    # At minute 0 (top of every hour)
30 * * * *   # At minute 30
*/15 * * * * # Every 15 minutes (0, 15, 30, 45)

Hours (0-23)

0 9 * * *    # At 9:00 AM
0 0 * * *    # At midnight (0:00)
0 */2 * * *  # Every 2 hours
0 9-17 * * * # Every hour from 9 AM to 5 PM

Day of Month (1-31)

0 0 1 * *    # First day of every month
0 0 15 * *   # 15th of every month
0 0 1,15 * * # 1st and 15th of every month

Month (1-12 or JAN-DEC)

0 0 1 1 *    # January 1st
0 0 1 */3 *  # First day of every quarter
0 0 1 6,12 * # June 1st and December 1st

Day of Week (0-6 or SUN-SAT)

0 0 * * 0    # Every Sunday
0 0 * * 1-5  # Monday through Friday
0 0 * * 6,0  # Weekends (Saturday and Sunday)

Special Characters

Asterisk (*) - Any Value

* * * * *   # Every minute of every hour of every day
0 * * * *   # Every hour (at minute 0)

Slash (/) - Step Values

*/5 * * * *   # Every 5 minutes
0 */3 * * *   # Every 3 hours
0 0 */2 * *   # Every 2 days

Dash (-) - Ranges

0 9-17 * * *  # Every hour from 9 to 17 (9 AM - 5 PM)
0 0 * * 1-5   # Monday through Friday

Comma (,) - Lists

0 0,12 * * *     # Midnight and noon
0 0 1,15 * *     # 1st and 15th
0 0 * * 0,3,6    # Sunday, Wednesday, Saturday

Common Cron Patterns

Every Hour

0 * * * *

Runs at minute 0 of every hour (1:00, 2:00, 3:00...).

Daily at Midnight

0 0 * * *

Every Monday at 9 AM

0 9 * * 1

First of Every Month at Midnight

0 0 1 * *

Every Weekday at 8:30 AM

30 8 * * 1-5

Every 15 Minutes

*/15 * * * *

Twice Daily (9 AM and 6 PM)

0 9,18 * * *

Every Sunday at 3 AM

0 3 * * 0

Last Day of Month

Cron doesn't support "last day" directly. Workarounds:

# Run on days 28-31, but check if it's the last day
0 0 28-31 * * [ "$(date +\%d -d tomorrow)" = "01" ] && /script.sh

Cron vs Cron-like (6 vs 5 Fields)

Some systems (like Quartz, Spring) use 6 fields, adding seconds:

┌───────────── second (0 - 59)
│ ┌───────────── minute (0 - 59)
│ │ ┌───────────── hour (0 - 23)
│ │ │ ┌───────────── day of month (1 - 31)
│ │ │ │ ┌───────────── month (1 - 12)
│ │ │ │ │ ┌───────────── day of week (0 - 6)
│ │ │ │ │ │
* * * * * * command

Spring and Quartz may also support:

  • ? for "no specific value" in day fields
  • L for "last" (last day of month, last Friday)
  • W for weekday nearest to given date
  • # for "nth weekday" (e.g., 2#1 = first Monday)

Always check which cron flavor your system uses!

Timezone Considerations

Cron times are in the system's local timezone by default.

Problems This Causes

  • DST transitions: Jobs may run twice or skip during daylight saving changes
  • Server relocation: Moving servers to different timezones affects schedules
  • Distributed systems: Servers in different timezones run at different actual times

Solutions

  1. Use UTC where possible:

    CRON_TZ=UTC
    0 0 * * * /script.sh  # Runs at midnight UTC
    
  2. Document the timezone clearly in comments

  3. Avoid scheduling during DST transitions (2-3 AM)

Testing Cron Expressions

Before deploying, verify your expression:

Manual Verification

Walk through the expression field by field:

30 4 1 * *
│  │ │ │ └─ Any day of week
│  │ │ └─── Any month
│  │ └───── 1st day of month
│  └─────── 4:00 (hour)
└────────── 30 minutes

= "At 4:30 AM on the 1st of every month"

Use Testing Tools

Online cron expression testers show:

  • Human-readable explanation
  • Next N scheduled runs
  • Validation errors

Common Mistakes

1. Forgetting Day of Week is 0-6

0 0 * * 7   # WRONG - some systems don't accept 7
0 0 * * 0   # RIGHT - Sunday is 0

2. Day of Month AND Day of Week

Most crons run if EITHER matches:

0 0 15 * 5  # Runs on the 15th AND every Friday

This probably isn't what you intended!

3. Running Too Frequently

* * * * *   # Every minute - probably too often!

Consider: Do you really need this frequency? What about overlap if the job takes >1 minute?

4. No Error Handling

Cron jobs can fail silently. Always:

  • Log output and errors
  • Set up monitoring
  • Handle failures gracefully
0 * * * * /script.sh >> /var/log/script.log 2>&1

5. Missing PATH

Cron uses a minimal environment:

# Set PATH explicitly
PATH=/usr/local/bin:/usr/bin:/bin
0 * * * * my-command

Or use full paths:

0 * * * * /usr/local/bin/my-command

Advanced Tips

Multiple Schedules

Run at multiple times with separate lines:

0 9 * * *   /script.sh  # 9 AM
0 17 * * *  /script.sh  # 5 PM

Predefined Schedules

Many systems support shortcuts:

Shortcut Equivalent
@yearly 0 0 1 1 *
@monthly 0 0 1 * *
@weekly 0 0 * * 0
@daily 0 0 * * *
@hourly 0 * * * *
@reboot Run once at startup

Lock to Prevent Overlap

Use flock to prevent concurrent runs:

* * * * * /usr/bin/flock -n /tmp/script.lock /path/to/script.sh

Summary

Cron expressions are powerful once you understand them:

  • 5 fields: minute, hour, day, month, weekday
  • Special characters: * (any), / (step), - (range), , (list)
  • Watch for gotchas: timezones, DST, day-of-month vs day-of-week
  • Test before deploying: Use tools to verify your expression
  • Monitor your jobs: Log output and handle failures

Ready to test a cron expression? Try our Cron Expression Tool!

Related Topics
cron scheduling automation unix linux jobs
Share this article

Continue Reading

Time
Timezone Conversions for Global Teams

Working across timezones: understanding UTC, handling daylight saving, and tools for scheduling international meetings.

Time
Unix Timestamps: The Developer's Time Format

Understanding Unix timestamps: what they are, why developers use them, timezone handling, and the Y2K38 problem.

Security
JWT Tokens Decoded: Structure, Security, and Best Practices

Understanding JSON Web Tokens: the three parts of a JWT, how verification works, and security considerations for token-based authentication.