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
Method 1: Online Generator (Recommended)
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.
Related Tools
- Crontab Generator — Build and validate cron expressions visually
- Timestamp Converter — Convert between Unix timestamps and dates for debugging schedules
- Chmod Calculator — Set correct file permissions for cron scripts
- Hash Generator — Generate checksums for verifying backup integrity
- Diff Checker — Compare crontab files before and after changes