How to Create Cron Expressions (Crontab Guide with Examples)

Independently researched No sponsored picks Affiliate supported

Cron is the backbone of scheduled task automation on Unix systems. Whether you’re running database backups, sending email digests, or clearing temp files, cron expressions tell the system exactly when to execute. The syntax is compact but easy to get wrong — one misplaced asterisk and your job runs every minute instead of every month. Here’s how to write cron expressions correctly.

What Is a Cron Expression?

A cron expression is a string of five (or six) fields that defines a schedule. The standard crontab format uses five fields:

┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-7, where 0 and 7 = Sunday)
│ │ │ │ │
* * * * *  command_to_execute

Each field accepts:

  • A specific value: 5
  • A wildcard: * (every possible value)
  • A range: 1-5
  • A list: 1,3,5
  • A step: */10 (every 10th value)

How to Create a Cron Expression (Step by Step)

Step 1: Define Your Schedule in Plain English

Before writing any syntax, state what you want:

  • “Every day at 3:00 AM”
  • “Every Monday at 9:30 AM”
  • “Every 15 minutes during business hours”
  • “The first day of every month at midnight”

Step 2: Map It to the Five Fields

Work from left to right:

“Every day at 3:00 AM”

  • Minute: 0 (at the top of the hour)
  • Hour: 3 (3 AM)
  • Day of month: * (every day)
  • Month: * (every month)
  • Day of week: * (every day)

Result: 0 3 * * *

Step 3: Validate with a Crontab Generator

Paste your expression into our Crontab Generator to see the next 5-10 execution times. This instantly confirms whether your expression does what you intended.

Step 4: Install It

On Linux/macOS:

# Edit your user's crontab
crontab -e

# Add the line
0 3 * * * /path/to/your/script.sh

Cron Syntax Reference

Field Values

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 * , - / L #

Special Characters Explained

Character Meaning Example Result
* Every value * * * * * Every minute
, List of values 1,15 * * * * At minute 1 and 15
- Range 0 9-17 * * * Every hour from 9 AM to 5 PM
/ Step/interval */10 * * * * Every 10 minutes
L Last 0 0 L * * Last day of the month
W Nearest weekday 0 0 15W * * Nearest weekday to the 15th
# Nth weekday 0 0 * * 1#2 Second Monday of the month

Note: L, W, and # are supported by some cron implementations (like Quartz) but not standard crontab. Our Crontab Generator shows which features your target system supports.

20 Common Cron Schedule Examples

Here are the cron expressions developers need most often, organized by frequency:

Every N Minutes

Schedule Expression Notes
Every minute * * * * * Use sparingly — very resource-heavy
Every 5 minutes */5 * * * * Good for health checks
Every 10 minutes */10 * * * * Common for data syncs
Every 15 minutes */15 * * * * Standard monitoring interval
Every 30 minutes */30 * * * * Good for reports

Hourly

Schedule Expression Notes
Every hour (on the hour) 0 * * * * Not * * * * * — that’s every minute
Every 2 hours 0 */2 * * * At minute 0 of every 2nd hour
Every 6 hours 0 */6 * * * 00:00, 06:00, 12:00, 18:00

Daily

Schedule Expression Notes
Every day at midnight 0 0 * * * Most common for daily jobs
Every day at 3:00 AM 0 3 * * * Good for backups (low traffic)
Every day at 9:30 AM 30 9 * * * Business-hours trigger
Twice a day (9 AM and 6 PM) 0 9,18 * * * List syntax

Weekly

Schedule Expression Notes
Every Monday at 9 AM 0 9 * * 1 1 = Monday
Every Friday at 5 PM 0 17 * * 5 5 = Friday
Weekdays at 8 AM 0 8 * * 1-5 Monday through Friday
Weekends at noon 0 12 * * 0,6 Sunday and Saturday

Monthly and Beyond

Schedule Expression Notes
First of every month at midnight 0 0 1 * * Day 1
Last day of every month 0 0 L * * Quartz syntax (not all crons)
Every quarter (Jan, Apr, Jul, Oct) 0 0 1 1,4,7,10 * First day of each quarter
Every year on Jan 1 0 0 1 1 * Annual job

Predefined Schedules (Shortcuts)

Many cron implementations support shorthand:

Shorthand Equivalent Meaning
@yearly 0 0 1 1 * Once a year (Jan 1, midnight)
@monthly 0 0 1 * * Once a month (1st, midnight)
@weekly 0 0 * * 0 Once a week (Sunday, midnight)
@daily 0 0 * * * Once a day (midnight)
@hourly 0 * * * * Once an hour (top of hour)
@reboot N/A Once at system startup

Common Cron Pitfalls

Pitfall 1: Every Minute vs Every Hour

# WRONG: Runs every minute of every hour
* * * * * /path/to/backup.sh

# CORRECT: Runs once per hour at minute 0
0 * * * * /path/to/backup.sh

The * in the minute field means “every minute.” This is the most common cron mistake. Always set the minute field explicitly unless you truly want per-minute execution.

Pitfall 2: Day of Month + Day of Week Conflict

When both day-of-month and day-of-week are set, most cron implementations treat them as OR, not AND:

# Runs on the 15th AND every Monday (not "the 15th if it's a Monday")
0 0 15 * 1

This catches many people off guard. If you need “the 15th only if it’s a Monday,” use a script that checks the day inside the command.

Pitfall 3: Timezone Confusion

Cron uses the system timezone by default. If your server is in UTC but you want a job at 9 AM Eastern:

# UTC time for 9 AM ET (EST = UTC-5)
0 14 * * * /path/to/script.sh

# Or set timezone in crontab (if supported)
CRON_TZ=America/New_York
0 9 * * * /path/to/script.sh

Always verify your server’s timezone with date or timedatectl before writing cron schedules.

Pitfall 4: Missing PATH

Cron runs with a minimal environment. Commands that work in your terminal may fail in cron because /usr/local/bin isn’t in cron’s PATH:

# WRONG: "node" might not be found
* * * * * node /path/to/script.js

# CORRECT: Use absolute path
* * * * * /usr/local/bin/node /path/to/script.js

Pitfall 5: No Output Logging

By default, cron sends output to the user’s email (if configured). On most modern systems, this means output is silently discarded:

# Redirect output to a log file
0 3 * * * /path/to/backup.sh >> /var/log/backup.log 2>&1

Always redirect stdout and stderr so you can debug failures.

Pitfall 6: Overlapping Executions

If a cron job takes longer than the interval, the next execution starts while the previous one is still running:

# Runs every minute, but the job takes 3 minutes
# Result: 3 overlapping instances running simultaneously
*/1 * * * * /path/to/slow-job.sh

Fix: Use a lock file or flock:

*/1 * * * * flock -n /tmp/job.lock /path/to/slow-job.sh

How to Test Cron Expressions

Use our Crontab Generator to enter a cron expression and see the next scheduled execution times. This is the fastest way to verify your syntax before deploying.

Method 2: Dry Run in Terminal

Test your command manually first:

# Run the exact command cron will run
/usr/local/bin/python3 /path/to/script.py

# Check exit code
echo $?

Method 3: Short Interval Test

Set the cron to run every minute, verify it fires, then change to the real schedule:

# Temporary: run every minute to verify
* * * * * /path/to/script.sh >> /tmp/cron-test.log 2>&1

# Check after 2 minutes
cat /tmp/cron-test.log

Method 4: Check Cron Logs

# Linux (systemd)
journalctl -u cron --since "10 minutes ago"

# macOS
log show --predicate 'process == "cron"' --last 10m

# Traditional syslog
grep CRON /var/log/syslog

Cron in Different Environments

Environment Cron System Notes
Linux (systemd) Standard crontab Most common; use crontab -e
macOS launchd (preferred) / cron Apple recommends launchd over cron
Docker Not built-in Use supercronic or external scheduler
Kubernetes CronJob resource YAML-based, supports 5-field cron syntax
AWS EventBridge (CloudWatch) Uses 6-field cron (adds year) or rate expressions
GitHub Actions schedule trigger Standard 5-field cron in YAML
Vercel / Netlify Cron via config Limited intervals, platform-specific

AWS and Quartz-based systems use a 6-field format that adds a seconds field at the beginning or a year field at the end. Our Crontab Generator supports both standard and extended formats.

Frequently Asked Questions

What does */5 mean in a cron expression?

The / is a step operator. */5 in the minute field means “every 5th minute” — so the job runs at 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, and 55. You can use steps in any field: */2 in the hour field means every 2 hours.

How do I run a cron job every 90 seconds?

You can’t directly — cron’s minimum resolution is one minute. The workaround is to run a job every minute and add a 90-second sleep for alternate runs, but this is fragile. For sub-minute scheduling, use a dedicated scheduler like systemd timers or a process manager.

Can I run cron as a specific user?

Yes. Edit the user’s crontab with crontab -e (it runs as that user), or use the system crontab at /etc/crontab which has an extra user field:

0 3 * * * alice /path/to/script.sh

How do I list all my cron jobs?

crontab -l          # Current user's crontab
sudo crontab -l -u alice  # Another user's crontab

Also check /etc/cron.d/, /etc/cron.daily/, /etc/cron.hourly/, and /etc/cron.weekly/ for system cron jobs.

What happens if the server is off when a cron job is scheduled?

Standard cron does not run missed jobs. If the server was down at the scheduled time, the execution is simply skipped. Use anacron if you need missed jobs to run when the system comes back online.

How do I disable a cron job temporarily?

Comment it out with # in crontab -e:

# 0 3 * * * /path/to/backup.sh

Remove the # to re-enable it.

Why Trust FindPicked?

Our recommendations are based on extensive research, real user reviews, and spec-by-spec analysis. We never accept payment for placement. When you buy through our links, we may earn a commission — this supports our work at no extra cost to you.

Learn how we pick →