Five fields, decades of confusion
0 14 */10 * 1-5 looks more like a regex accident than a schedule. Yet strings like this power every recurring task on every Unix-like system since Bell Labs shipped the first cron daemon. The syntax is compact, the operator set is small, and it still trips up experienced engineers because of one quirk buried in the POSIX spec: how Day-of-Month and Day-of-Week interact.
This guide covers the 5-field architecture, the math behind step values, and that OR-behavior trap.
The 5-field POSIX layout
The cron daemon (cron / crond) wakes at the top of every minute and evaluates each crontab entry against the current system time. An expression has five space-separated fields, read left to right:
| Field | Description | Valid Range | Allowed Text Values |
|---|---|---|---|
| 1 | Minute | 0-59 | None |
| 2 | Hour | 0-23 | None |
| 3 | Day of Month | 1-31 | None |
| 4 | Month | 1-12 | JAN-DEC |
| 5 | Day of Week | 0-7 (0 & 7 are Sunday) | SUN-SAT |
Four operators build patterns on top of these fields:
*(Asterisk): Every valid value in the field.,(Comma): Union of individual values (e.g.,1,3,5).-(Hyphen): Inclusive range (e.g.,9-17= 9 AM through 5 PM)./(Slash): Step / arithmetic progression over a range.
Step values and their reset trap
Step values (/) are common, but they hide a structural trap.
If an asterisk is used as the base (e.g., */15), the step is applied relative to the absolute minimum valid value of that field (0). So, */15 in the minute field evaluates to 0, 15, 30, 45.
However, what happens when your step interval doesn't divide evenly into the maximum range? Take */7 in the hour field. The valid range is 0 to 23.
The evaluated hours are: 0, 7, 14, 21.
At the end of the day, the calculation hits the day boundary and resets to 0. This means the execution interval between the last run of the day (9:00 PM / 21:00) and the first run of the next day (Midnight / 00:00) is only three hours, completely violating the naive assumption of a consistent seven-hour interval.
Day-of-Month vs. Day-of-Week: the OR trap
The biggest source of logical confusion in standard cron: what happens when both the Day of Month (DOM) and Day of Week (DOW) are restricted.
Normally, a cron entry fires only when all fields match the current system time (logical AND).
The POSIX exception: if both DOM (field 3) and DOW (field 5) are restricted (neither contains an unadorned *), the two conditions combine as a logical OR (union).
Standard Matching: Run if (Minute) AND (Hour) AND (Month) AND (DOM)
Restricted Day Matching (The OR Exception): Run if (Minute) AND (Hour) AND (Month) AND (DOM OR DOW)
Example: 30 4 1,15 * 5.
This looks like "4:30 AM on the 1st and 15th, only if those days fall on a Friday."
It actually means: "4:30 AM on the 1st and 15th of the month, plus every Friday of the month."
The Vixie Cron Intersection Bug
The original Vixie cron parser adds another layer. With 0 14 */10 * 1-5, the parser inspects the first character of the DOM field. It sees an asterisk (*) at the start of */10 and decides the field is "unrestricted."
This forces the engine to evaluate the relationship as an intersection (logical AND). Result? It executes at 2:00 PM on every 10th day of the month only if that day falls on a weekday.
But if you write the logically equivalent expression 0 14 1,11,21,31 * 1-5, the leading character is a number. The system reverts to POSIX union behavior, running every single weekday, plus any weekend day that falls on the 1st, 11th, 21st, or 31st.
Essential Cron Cheatsheet
Exact POSIX patterns for the most-searched schedules:
- Every 5 minutes:
*/5 * * * * - Every 15 minutes:
*/15 * * * *(Executes at minute 0, 15, 30, and 45) - Every day at midnight:
0 0 * * * - Every Monday at midnight:
0 0 * * 1 - First day of the month:
0 0 1 * * - Every weekday at midnight:
0 0 * * 1-5
Predefined Shortcuts
Modern POSIX systems provide human-readable shortcuts that map to these standard patterns:
@yearly/@annually->0 0 1 1 *@monthly->0 0 1 * *@weekly->0 0 * * 0@daily/@midnight->0 0 * * *@hourly->0 * * * *
Want to verify a complex expression or translate between dialects? Use the Cron Expression Generator & Explainer to visualize schedules and catch these traps before they hit production.