Standard Crontab Syntax Overview (5-Field Architecture)
The Unix crontab (cron table) daemon is a time-based job scheduler that executes background shell commands at specified intervals. In classic Linux and Unix operating systems (Ubuntu, Debian, CentOS, macOS, RHEL), a standard cron expression consists of exactly five space-delimited fields. Each field represents a temporal boundary (minute, hour, day of month, month, day of week) and defines precisely when a command should trigger.
The standard 5-field crontab structure is visually indexed as follows:
โโโโโโโโโโโโโโ minute (0 - 59)
โ โโโโโโโโโโโโ hour (0 - 23, military format)
โ โ โโโโโโโโโโ day of month (1 - 31)
โ โ โ โโโโโโโโ month (1 - 12 or JAN - DEC)
โ โ โ โ โโโโโโ day of week (0 - 7, 0 and 7 both represent Sunday)
โ โ โ โ โ
* * * * * command_to_executeTo understand how cron evaluates schedule expressions, consider the exact value boundaries and index positions of each field:
- Field 1: Minute (0 - 59) โ Specifies the exact minute within the hour that the task executes. For example, a value of
15means execution at 15 minutes past the hour. - Field 2: Hour (0 - 23) โ Uses 24-hour military time syntax.
0represents Midnight (12:00 AM),12represents Noon (12:00 PM), and23represents 11:00 PM. - Field 3: Day of Month (1 - 31) โ Specifies the numerical day of the calendar month. Values must align with calendar limits for the given month.
- Field 4: Month (1 - 12) โ Represents the calendar month, where
1is January and12is December. Short 3-letter uppercase names (JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC) are also permitted in modern Linux distributions. - Field 5: Day of Week (0 - 7) โ Represents the day of the week. In standard POSIX cron,
0and7both refer to Sunday,1is Monday,2is Tuesday,3is Wednesday,4is Thursday,5is Friday, and6is Saturday. Short 3-letter names (SUN, MON, TUE, WED, THU, FRI, SAT) are also supported.
Special Operators Reference Guide
Crontab expressions achieve powerful flexibility through four fundamental operators: Asterisk (Wildcard), Comma (List Separator), Hyphen (Range), and Slash (Step Values). Combining these operators allows developers to configure complex execution patterns without writing custom script logic.
1. The Asterisk (*) Operator โ Wildcard Match
The asterisk matches all valid values within a specific field. It acts as an unconditional wildcard. When placed in the minute field, the job runs every minute. When placed in the hour field, it runs every hour.
* * * * * /usr/bin/php /var/www/check_queue.phpTranslation: "Execute check_queue.php every minute of every hour, every day of the month, every month, every day of the week."
2. The Comma (,) Operator โ Multi-Value List Separator
The comma operator creates an explicit, non-sequential list of values for a single field. It allows you to trigger tasks at multiple distinct times without creating separate crontab entries.
0 8,12,17 * * * /usr/bin/node /app/sync_orders.jsTranslation: "Execute sync_orders.js at 8:00 AM, 12:00 PM (Noon), and 5:00 PM (17:00) every single day."
3. The Hyphen (-) Operator โ Inclusive Range Boundary
The hyphen operator defines an inclusive range of consecutive values. It reduces clutter when specifying contiguous time blocks, such as standard business working hours or consecutive weekdays.
0 9-17 * * 1-5 /usr/bin/bash /scripts/ping_monitors.shTranslation: "Execute ping_monitors.sh at the top of every hour between 9:00 AM and 5:00 PM, Monday through Friday."
4. The Slash (/) Operator โ Interval Step Values
The slash operator specifies increment step values across a field's valid range. Syntax */N in a field means "every N units". It can also be combined with ranges, such as 10-45/5 (every 5 minutes between minute 10 and minute 45).
*/15 * * * * /usr/bin/python3 /app/cleanup_temp.pyTranslation: "Execute cleanup_temp.py every 15 minutes (at minutes 0, 15, 30, and 45 past the hour)."
Non-Standard Operators (AWS EventBridge, Spring, & Quartz)
Enterprise cloud scheduling systemsโsuch as AWS EventBridge, Spring Framework @Scheduled, and Java Quartz Schedulerโextend standard Linux 5-field syntax to 6 fields (adding Seconds or Year fields) and introduce non-standard special characters to handle complex calendar logic.
| Operator | Name | Supported Systems | Technical Purpose & Example |
|---|---|---|---|
| ? | No Specific Value | AWS EventBridge, Quartz | Used when a condition is specified in Day-of-Month, but ignored in Day-of-Week (or vice versa). Prevents syntax conflicts in 6-field schedulers. Example: 0 12 * * ? * |
| L | Last Day | AWS, Quartz, Spring | Specifies the last day of the month or last weekday. L in Day-of-Month means the 28th, 30th, or 31st depending on leap years. 5L in Day-of-Week means "last Friday of the month". |
| W | Nearest Weekday | AWS EventBridge, Quartz | Specifies the closest business day (Mon-Fri) to a target calendar day. 15W means "nearest weekday to the 15th of the month". If the 15th is Saturday, it triggers Friday the 14th. |
| # | N-th Day of Month | Quartz Scheduler, AWS | Specifies the N-th occurrence of a weekday within the month. 2#1 means the 1st Monday of the month. 5#3 means the 3rd Friday of the month. |
Complete Cron Expression Cheat Sheet Table
Reference table of 30 production-grade cron expressions covering database maintenance, log rotation, automated billing, API polling, and system cleanup schedules:
| Use Case / Task Type | Cron Expression | Plain English Schedule Translation |
|---|---|---|
| Real-Time Queue Polling | * * * * * | Every minute, every day |
| Frequent API Health Check | */5 * * * * | Every 5 minutes |
| Cache Invalidation | */15 * * * * | Every 15 minutes |
| Database Connection Pool Flush | */30 * * * * | Every 30 minutes |
| Hourly Metrics Aggregation | 0 * * * * | Every hour at minute 0 |
| Off-Peak Hourly Sync | 30 * * * * | Every hour at minute 30 |
| Bi-Hourly Backup | 0 */2 * * * | Every 2 hours on the hour |
| Every 4 Hours Log Rotation | 0 */4 * * * | Every 4 hours at minute 0 |
| Every 6 Hours Sync | 0 */6 * * * | At 00:00, 06:00, 12:00, 18:00 daily |
| Daily Midnight Maintenance | 0 0 * * * | Daily at 12:00 AM (Midnight) |
| Nightly Database Dump | 0 2 * * * | Daily at 2:00 AM (Off-peak hours) |
| Early Morning Digest Email | 0 6 * * * | Daily at 6:00 AM |
| Business Morning Trigger | 0 9 * * 1-5 | Monday through Friday at 9:00 AM |
| Noon Status Report | 0 12 * * * | Daily at 12:00 PM (Noon) |
| Shift Start Notification | 30 8 * * 1-5 | Monday through Friday at 8:30 AM |
| Twice Daily Report | 0 9,17 * * * | Daily at 9:00 AM and 5:00 PM |
| Working Hours Polling | 0 9-17 * * 1-5 | Hourly 9 AM to 5 PM on weekdays |
| Weekend Only Cleanup | 0 0 * * 6,0 | Saturday and Sunday at Midnight |
| Sunday Night Audit | 0 23 * * 0 | Every Sunday at 11:00 PM |
| Weekly Monday Newsletter | 0 8 * * 1 | Every Monday at 8:00 AM |
| Bi-Weekly Sync (Mon/Thu) | 0 0 * * 1,4 | Every Monday and Thursday at Midnight |
| First Day of Month Billing | 0 0 1 * * | 1st day of every month at Midnight |
| Mid-Month Payroll Trigger | 0 0 15 * * | 15th day of every month at Midnight |
| End-of-Month Audit (Quartz) | 0 0 L * * | Last day of every month at Midnight |
| Quarterly Tax Estimate | 0 0 1 1,4,7,10 * | 1st of Jan, Apr, Jul, Oct at Midnight |
| Semi-Annual Security Scan | 0 0 1 1,7 * | 1st of January and July at Midnight |
| Annual New Year Reset | 0 0 1 1 * | January 1st at 12:00 AM (New Year) |
Crontab Environment Variables & Production Caveats
Over 80% of production cron job failures occur not because of incorrect cron expression syntax, but due to Linux environment isolation issues. Understanding how the cron daemon initializes execution contexts is essential for robust server administration.
1. Restricted Default PATH Environment Variable
When a standard Linux user opens a shell session (via SSH or terminal), shell startup scripts (~/.bashrc, ~/.zshrc, /etc/profile) set up a rich PATH variable containing paths like /usr/local/bin, ~/.nvm/versions/node, or custom virtualenv paths.
However, the cron daemon executes commands inside an extremely minimal shell environment where PATH is strictly defaulted to /usr/bin:/bin. As a result, binaries like node, docker, python3, or aws-cli located in /usr/local/bin will throw "Command Not Found" errors.
# BAD (Fails silently because 'node' is not in standard cron PATH):
0 2 * * * node /home/deploy/app/index.js
# GOOD (Specify absolute executable binary path):
0 2 * * * /usr/local/bin/node /home/deploy/app/index.js
# BETTER (Define PATH at the top of your crontab file):
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHELL=/bin/bash
0 2 * * * node /home/deploy/app/index.js2. Working Directory Discrepancies
By default, cron commands execute inside the user's home directory (/home/username or /root), NOT inside your application folder. If your script loads relative paths (such as .env files or config JSONs), execution will fail.
# Always explicit change directory before executing scripts:
0 3 * * * cd /var/www/my-application && /usr/bin/npm run DB:migrate3. Redirecting stdout and stderr (Logging)
Standard cron captures standard output (stdout) and error output (stderr) and attempts to send it via local mail daemon (postfix / sendmail). If mail is unconfigured, outputs vanish. Always redirect logs explicitly:
# Append both standard output AND errors to a dedicated log file:
0 4 * * * /usr/bin/python3 /app/backup.py >> /var/log/cron_backup.log 2>&1
# Silence output completely (discard output):
0 4 * * * /usr/bin/python3 /app/backup.py > /dev/null 2>&1Cloud & Serverless Execution (Vercel, AWS, Kubernetes)
Modern web development has largely shifted from self-managed Linux VPS servers to serverless cloud infrastructure. Here is how standard cron expressions map into modern serverless platforms:
- Vercel Cron Jobs: Configured in
vercel.json, Vercel triggers designated serverless API route endpoints over HTTPS on your specified cron schedule. - AWS EventBridge Rules: Uses 6-field schedule expressions (Minute, Hour, Day-of-month, Month, Day-of-week, Year) to invoke AWS Lambda functions, ECS tasks, or SNS topics.
- Kubernetes CronJobs: Defined via YAML manifests (
kind: CronJob), k8s spins up transient Pods on your specified schedule, runs the task container to completion, and cleans up resource pods automatically.
Frequently Asked Questions (FAQ)
How do I run a cron job every second?
Standard Unix cron has a 1-minute minimum resolution floor. To run jobs every few seconds, write a persistent background daemon (e.g. Node.js or Python loop using sleep()), or use 6-field schedulers like Quartz that support a Seconds field.
What is the difference between 5-field and 6-field cron syntax?
Standard Linux crontab uses 5 fields (Minute, Hour, Day of Month, Month, Day of Week). Cloud systems like AWS EventBridge and Quartz use 6 fields (adding Year or Seconds, and special characters like '?' and 'L').
Why do environment variables fail in crontab?
Cron runs in a minimal shell environment without loading ~/.bashrc or ~/.zshrc. Standard PATH is restricted to /usr/bin:/bin. You must explicitly define PATH at the top of crontab or use absolute binary paths.
How do I redirect cron stdout and stderr to a log file?
Use >> /var/log/myjob.log 2>&1 at the end of your crontab command line. To discard output completely, use > /dev/null 2>&1.
What happens if a cron job takes longer than its schedule interval?
Standard cron spawns parallel instances without checking if the previous instance finished. Use utility wrappers like flock or lockfiles to prevent overlapping execution and server memory exhaustion.