Cron Expression Complete Guide: Master Job Scheduling

Published: June 7, 2026 · 13 min read

Table of Contents

What is Cron and Why Use It?

Cron is a time-based job scheduler found in Unix-like operating systems including Linux, macOS, and BSD variants. It allows you to schedule scripts and commands to run automatically at specified intervals—hourly, daily, weekly, or monthly.

For developers and system administrators, cron is essential for automating repetitive tasks: database backups, log rotation, report generation, cache clearing, health checks, and more. Instead of manually running tasks, you define the schedule once and cron handles the rest.

The cron daemon (crond) runs continuously in the background, checking its configuration every minute to determine if any scheduled jobs need execution. This makes it highly reliable for mission-critical automation.

Key Benefits

Cron Expression Format

A standard cron expression consists of five fields separated by spaces, followed by the command to execute:

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

The Five Fields

FieldAllowed ValuesSpecial Characters
Minute0-59* , - /
Hour0-23* , - /
Day of Month1-31* , - / ? L W
Month1-12 or JAN-DEC* , - /
Day of Week0-6 or SUN-SAT* , - / ? L #

Field Values and Special Characters

Asterisk (*) — Every Value

The asterisk matches all possible values for that field:

* * * * *          # Every minute
0 * * * *          # Every hour (at minute 0)
* 12 * * *         # Every minute during hour 12
* * 1 * *          # Every minute on day 1
* * * * 0          # Every minute on Sundays

Comma (,) — Specific Values

List multiple values separated by commas:

0,30 * * * *       # At minutes 0 and 30 (every half hour)
9,12,18 * * *      # At hours 9, 12, and 18
0 9,12,18 * * *    # At 9:00, 12:00, and 18:00
* 9-17 * * 1-5     # Every minute, hours 9-17, weekdays

Hyphen (-) — Range of Values

Specify a range of consecutive values:

0 9-17 * * 1-5     # 9 AM to 5 PM, Monday to Friday
0 0 1-15 * *       # Midnight on 1st through 15th
30 4 * * 0,6       # 4:30 AM on weekends (Sat & Sun)

Slash (/) — Step Values

Use slash to specify increments:

*/15 * * * *       # Every 15 minutes
0 */2 * * *        # Every 2 hours
0 */6 * * *        # Every 6 hours
0 0 */3 * *         # Every 3 days at midnight
*/10 9-17 * * 1-5   # Every 10 min during business hours

Question Mark (?) — No Specific Value

Use ? when you don't care about a field (useful for day-of-month or day-of-week):

0 0 15 * ?          # 15th of every month (any day)
0 0 ? * MON         # First day of month (if Monday)

L — Last

L means "last" and works in day-of-month and day-of-week:

* * L * *           # Last day of every month
0 0 L * *           # Midnight on last day of month
0 0 L-1 * *          # Midnight day before last day
* * 5L * *           # Last Friday of every month

W — Weekday

W moves to the nearest weekday:

0 0 15W * *         # 15th of month, or nearest weekday
0 0 1W * *          # 1st of month, or nearest weekday

# — Nth Occurrence

Specify the nth occurrence of a day:

* * 3#4 * *         # Fourth Wednesday (3rd day, 4th occurrence)
0 0 1#1 * *         # First Monday of every month

Common Cron Examples

ExpressionMeaning
* * * * *Every minute
0 * * * *Every hour
0 0 * * *Daily at midnight
0 0 * * 0Weekly on Sunday at midnight
0 0 1 * *First day of every month
0 0 1,15 * *1st and 15th of every month
*/5 * * * *Every 5 minutes
0 */2 * * *Every 2 hours
0 9-17 * * 1-5Every hour, 9 AM to 5 PM, weekdays
0 6 * * 1-5Weekdays at 6:00 AM
30 4 * * *Daily at 4:30 AM
0 0 1,8,15,22 * *Every week on the 8th, 15th, and 22nd
0 0 * * 0Sunday at midnight
0 22 * * 1-5Weeknights at 10 PM
0 0 L * *Last day of month at midnight

Special Time Strings

Cron supports several shortcut strings that simplify common schedules:

@reboot     # Run once at startup
@yearly     # Run once a year (0 0 1 1 *)
@annually   # Same as @yearly
@monthly    # Run once a month (0 0 1 * *)
@weekly     # Run once a week (0 0 * * 0)
@daily      # Run once a day (0 0 * * *)
@midnight   # Same as @daily
@hourly     # Run once an hour (0 * * * *)

Using Special Strings

@hourly /usr/local/bin/cleanup.sh
@daily /usr/bin/backup-database.sh
@weekly /usr/bin/log-rotation.sh
@monthly /usr/bin/monthly-report.sh

Timezone Considerations

By default, cron runs in the system timezone defined in /etc/localtime or the TZ environment variable. This can cause confusion in distributed systems.

Setting Timezone in Crontab

# Set timezone for this crontab
CRON_TZ=America/New_York

0 9 * * * /scripts/daily-report.sh   # Runs at 9 AM New York time

Common Timezone Gotchas

Recommendation

Always use UTC for cron jobs in distributed systems. Store execution times in UTC, convert to local time only for display purposes.

Troubleshooting Cron Jobs

Common Issues

1. Command Not Found

Cron runs with a minimal PATH. Use absolute paths:

# Wrong (may fail)
* * * * * python script.py

# Correct (always works)
* * * * * /usr/bin/python /path/to/script.py

2. Environment Variables Missing

Set variables explicitly in your crontab:

# Set environment variables
PATH=/usr/local/bin:/usr/bin:/bin
PYTHONPATH=/home/user/python
DATABASE_URL=postgres://localhost/db

0 * * * * /home/user/scripts/check-health.sh

3. Working Directory Issues

Commands may fail if they expect to run from a specific directory:

# Use cd to set working directory
0 * * * * cd /project && ./deploy.sh

# Or use absolute paths throughout

4. Output/Error Not Visible

Redirect output to files for debugging:

# Redirect stdout and stderr to files
0 * * * * /scripts/job.sh >> /var/log/job.log 2>&1

# Email output (requires mail configured)
[email protected]
0 * * * * /scripts/job.sh

Debugging Commands

# List your crontab
crontab -l

# Edit crontab
crontab -e

# View system crontabs
cat /etc/crontab
ls -la /etc/cron.d/

# Check cron logs
grep CRON /var/log/syslog    # Debian/Ubuntu
grep CRON /var/log/cron       # CentOS/RHEL
tail -f /var/log/syslog | grep CRON

Advanced Patterns

Seconds in Extended Format

Standard cron doesn't support seconds. For extended support, use 6-field format:

# Quartz Scheduler format (with seconds)
0 30 9 * * ?         # 9:30:00 AM every day
0 0/15 * * * ?       # Every 15 minutes

# Cronicle and others support
*/10 * * * *         # Every 10 seconds (if supported)

Complex Business Schedules

# Every weekday at 6 PM (except holidays - requires external logic)
0 18 * * 1-5

# First Monday of each quarter
0 0 1-7 * 1

# Last Friday of month
0 0 L * 5

# Business hours: 9-5, every 15 min, weekdays
*/15 9-17 * * 1-5

Ranges with Lists

# Every 30 minutes, 8 AM to 6 PM, Monday through Friday
0,30 8-17 * * 1-5

# Simplified
*/30 8-17 * * 1-5

# Multiple specific times
0 6,12,18 * * *      # 6 AM, noon, 6 PM daily

Using Cron in Programming

Most programming languages have libraries for parsing and managing cron expressions:

JavaScript (node-cron)

const cron = require('node-cron');

cron.schedule('0 9 * * 1-5', () => {
  console.log('Running weekday morning task');
}, {
  scheduled: true,
  timezone: 'America/New_York'
});

Python (croniter)

from croniter import croniter
from datetime import datetime

cron = croniter('0 9 * * 1-5', datetime.now())
next_run = cron.get_next(datetime)
print(f'Next run: {next_run}')

Go (robfig/cron)

import "github.com/robfig/cron/v3"

c := cron.New()
c.AddFunc("0 9 * * 1-5", func() {
    fmt.Println("Weekday morning task")
})
c.Start()

Validate your cron expressions instantly with the JieBang Cron Parser tool.

Try Cron Parser Online →