ToolBoxOnline
Developer

Cron Parser How to Read Crontab Schedules Without the Manual — and Why 0 0 * * 0 Is Not the Same as @weekly

You found a cron expression in a server config. Does it run at midnight every day, or midnight on Sundays? Here's how to decode cron syntax without the reference card.

cron parsercrontabcron expressionschedulingserver administration

You SSH into a production server and check the crontab: 30 2 * * 1 /usr/bin/backup.sh. You know this runs a backup script. But when? 2:30 AM every day? 2:30 AM on Mondays? 2:30 AM on the 1st of every month? You could dig through the cron man page. Or you could paste the expression into a cron parser and see "At 02:30 AM, every Monday" plus the next ten execution times.

Cron syntax is deceptively simple — five fields, each with specific rules. But the special characters and overlapping day-of-month/day-of-week behavior create edge cases that trip up even experienced developers. Here is how to read any cron expression in seconds.

The Five Fields, Explained in Plain English

A cron expression is five space-separated fields: minute (0-59), hour (0-23), day of month (1-31), month (1-12), day of week (0-7) — where 0 and 7 both mean Sunday. Each field can be a specific number, a wildcard (* means "every"), a range (1-5 means "1 through 5"), a list (1,3,5), or a step value (*/15 means "every 15").

The most common expressions: */5 * * * * = every 5 minutes. 0 * * * * = every hour at the top of the hour. 0 9 * * 1-5 = 9:00 AM, Monday through Friday. 0 0 1 * * = midnight on the 1st of every month. 0 0 * * 0 = midnight every Sunday.

The day-of-month vs day-of-week trap: When both day-of-month and day-of-week are specified (not *), cron runs when either condition matches. 0 0 13 * 5 runs at midnight on every Friday AND on the 13th of every month — not just "Friday the 13th." This is the most common cron scheduling bug. If you want "Friday the 13th," you need logic inside the script, not in the cron expression.

Step Values: The Most Misunderstood Feature

*/5 in the minute field means "every 5 minutes" — specifically, at minutes 0, 5, 10, 15, 20, ... 55. It does NOT mean "every 5 minutes starting from whenever the system booted." Cron always starts counting from the beginning of the range. */7 means minutes 0, 7, 14, 21, 28, 35, 42, 49, 56 — an uneven pattern that most people do not intend. Use step values that divide evenly into the range (2, 3, 4, 5, 6, 10, 12, 15, 20, 30) unless you have a specific reason for an uneven pattern.

You can also combine ranges with steps: 1-30/10 in the minute field means minutes 1, 11, 21. This is useful for offsetting jobs — running at 1, 11, 21, 31, 41, 51 minutes past the hour instead of the more common 0, 10, 20, 30, 40, 50. Offsetting reduces load spikes when hundreds of cron jobs all fire at minute 0.

Using a Cron Parser as a Safety Check

Before you save a crontab, paste the expression into a cron parser. The human-readable description tells you what the expression actually does — not what you intended it to do. The next-execution list shows you exactly when the job will fire in the next few hours or days. If the times look wrong, the expression is wrong.

This 5-second check catches the most common mistakes: confusing day-of-month with day-of-week, using step values that produce unexpected patterns, forgetting that cron uses the server's timezone (not UTC necessarily), and accidentally scheduling jobs for times that do not exist (2:30 AM during daylight saving spring-forward).

Parse your cron expressions at free cron parser — paste, read, verify, save. Five seconds that prevents a 3 AM production incident.

Tools mentioned in this article

شارك هذه الأداة