Cron Expression Examples

Sixty ready-to-copy schedules, from every minute to the last weekday of the quarter

Most of the time you need one working line, such as the one that runs your backup at 3 AM on the first Sunday of the month, more than an understanding of cron from first principles. This page collects sixty schedules we have needed in practice, grouped by how often they fire, with notes on how each one behaves. Every expression is standard five-field Unix cron unless the table says otherwise, and you can paste any of them into the Explainer to see its next run times.

Every N minutes

Step values in the minute field (*/n) cover almost every sub-hourly schedule. A step divides the whole 0-59 range, so the runs are evenly spaced only when n divides 60.

Sub-hourly schedules
ExpressionRunsNotes
* * * * *Every minute1,440 runs a day, the fastest schedule standard cron supports.
*/2 * * * *Every 2 minutesFires on even minutes: :00, :02, :04…
*/5 * * * *Every 5 minutesThe most common polling interval.
*/10 * * * *Every 10 minutes:00, :10, :20, :30, :40, :50.
*/15 * * * *Every 15 minutesFour runs an hour, on the quarter.
*/30 * * * *Every 30 minutesEquivalent to 0,30 * * * *.
*/7 * * * *Every 7 minutes, resetting each hour:00, :07…:56, then :00 again. The gap at the hour boundary is 4 minutes because 7 does not divide 60.
7 * * * *At 7 minutes past every hourMoving off :00 avoids the traffic spike created by all the other jobs that run on the hour.
0,15,30,45 * * * *Every 15 minutesAn explicit list; identical to */15 but clearer to some readers.
*/5 * * * 1-5Every 5 minutes, Monday to FridayNo runs on Saturday or Sunday.
Watch the step boundary

A step always counts from the start of its field's range and does not track when the previous run happened. */7 means "every 7th minute of each hour" rather than "every 7 minutes forever", so the gap between 23:56 and 00:00 is four minutes instead of seven. For a true fixed interval that does not divide an hour, use a scheduler that supports intervals.

Hourly and every N hours

Put a fixed value in the minute field and a step or range in the hour field. Leaving the minute as * is nearly always a mistake: * */2 * * * runs sixty times in each of those hours, not once.

Hourly schedules
ExpressionRunsNotes
0 * * * *Every hour, on the hour24 runs a day.
30 * * * *Every hour at half pastUseful for staggering against hourly jobs on :00.
0 */2 * * *Every 2 hours00:00, 02:00, 04:00…22:00.
0 */3 * * *Every 3 hoursEight runs a day starting at midnight.
0 */4 * * *Every 4 hours00:00, 04:00, 08:00, 12:00, 16:00, 20:00.
0 */6 * * *Every 6 hoursFour runs a day.
0 */12 * * *Twice a dayMidnight and noon.
0 9-17 * * *Hourly from 09:00 to 17:00Nine runs, because the range includes both ends.
0 8-18/2 * * *Every 2 hours between 08:00 and 18:0008:00, 10:00, 12:00, 14:00, 16:00, 18:00. A step applied to a range.
15,45 * * * *Twice an hour, at :15 and :45A list in the minute field.

Daily at a fixed time

Cron uses 24-hour time and has no AM/PM and no seconds field. 0 18 * * * is 6 PM, and it fires at 18:00:00 in the server's time zone, whatever that is set to.

Once-a-day schedules
ExpressionRunsNotes
0 0 * * *Every day at midnightThe classic nightly job. Equivalent to @daily.
30 2 * * *Every day at 02:30A common backup window, but see the DST warning below.
0 3 * * *Every day at 03:00Safely past the daylight saving transition hour in most zones.
0 6 * * *Every day at 06:00Morning report generation.
0 12 * * *Every day at noon
0 18 * * *Every day at 18:006 PM in 24-hour time.
0 23 * * *Every day at 23:00End-of-day rollup before the date changes.
0 0,12 * * *Twice daily, midnight and noonA list is clearer than */12 when the two times are not evenly spaced.
Avoid the 01:00-03:00 window

In zones that observe daylight saving, a daily job scheduled between roughly 01:00 and 03:00 will be skipped on the spring-forward day, or run twice on the fall-back day, depending on your cron implementation. Scheduling at 0 3 * * * or later avoids the problem. The time zones and DST guide describes what each implementation does.

Weekdays, weekends and business hours

Day of week is the fifth field, numbered 0 (Sunday) through 6 (Saturday). Most implementations also accept 7 for Sunday and three-letter names such as MON.

Weekday and weekend schedules
ExpressionRunsNotes
0 9 * * 1-5Weekdays at 09:00Monday through Friday.
0 9 * * MON-FRIWeekdays at 09:00Identical, using names. Names are case-insensitive but less portable than numbers.
0 18 * * 1-5Weekdays at 18:00End-of-workday jobs.
0 0 * * 6,0Weekends at midnightSaturday and Sunday.
0 2 * * 6Saturdays at 02:00Weekly maintenance while nobody is working.
*/15 9-17 * * 1-5Every 15 minutes, 09:00-17:59, weekdays36 runs per weekday. The 17 covers the whole 17:00 hour, so the last run is 17:45.
0 9-17 * * 1-5Hourly during business hours, weekdaysNine runs a day, 45 a week.
*/30 8-18 * * 1-5Every half hour, 08:00-18:59, weekdaysExtend the hour range by one if you want coverage through the end of the day.

Weekly

A weekly schedule is a daily schedule with the day-of-week field restricted and the day-of-month field left as *. Restricting both is the most common cron mistake, and the last section explains why.

Weekly schedules
ExpressionRunsNotes
0 0 * * 0Every Sunday at midnightEquivalent to @weekly.
0 0 * * 1Every Monday at midnightStart-of-week reset.
0 4 * * 0Every Sunday at 04:00Weekly full backup.
0 8 * * 1Every Monday at 08:00Weekly summary email before the day starts.
0 17 * * 5Every Friday at 17:00End-of-week report.
0 12 * * 1,3,5Monday, Wednesday and Friday at noonA list in the day-of-week field.

Monthly

Day of month is the third field, 1 to 31. Standard cron has no "last day of month" token, which is why the workarounds below exist.

Monthly schedules
ExpressionRunsNotes
0 0 1 * *Midnight on the 1st of every monthEquivalent to @monthly.
0 3 1 * *03:00 on the 1stMonthly billing or archival run.
0 0 15 * *Midnight on the 15thMid-month.
0 0 1,15 * *1st and 15thTwice-monthly payroll pattern.
0 0 28 * *The 28th of every monthThe last day that exists in every month, February included.
0 0 1 */3 *The 1st of every third monthJanuary, April, July, October.
0 9 1-7 * 1Not "the first Monday"This runs on days 1-7 and on every Monday, because of OR logic. See below for the correct form.
0 0 L * *Last day of the monthQuartz and some extended dialects only. Standard Unix cron rejects L.

Running on the last day of the month in standard cron

Because Unix cron has no L, the portable trick is to run daily and let the command decide whether today is the last day:

0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && /usr/local/bin/month-end.sh

The schedule limits cron to the four candidate days, and the shell test lets exactly one of them through. The \% is escaped on purpose: inside a crontab, an unescaped % is turned into a newline and everything after it is fed to the command on standard input.

Running on the first Monday of the month

The same approach works here: restrict day of month to the first week, leave day of week as *, then guard in the shell so only the Monday qualifies:

0 9 1-7 * * [ "$(date +\%u)" = "1" ] && /usr/local/bin/first-monday.sh

Only days 1-7 are candidates, and date +%u returns 1 only on Monday, so exactly one day a month qualifies. In Quartz you would write this directly as 0 0 9 ? * MON#1.

Quarterly and yearly

Low-frequency schedules
ExpressionRunsNotes
0 0 1 1,4,7,10 *The 1st of each quarterCalendar quarters: January, April, July and October.
0 0 1 2,5,8,11 *Quarters offset by one monthFor fiscal years starting in February.
0 0 1 */6 *Twice a yearJanuary and July.
0 0 1 1 *Midnight on 1 JanuaryEquivalent to @yearly or @annually.
0 0 31 12 *Midnight on 31 DecemberYear-end close.
0 2 1 JAN,APR,JUL,OCT *Quarterly at 02:00Month names, where supported.

Special strings

Most cron implementations accept a handful of shorthand strings in place of all five fields. They are easy to read and work across Vixie cron, cronie and systemd's cron compatibility, but not in every scheduler. Kubernetes CronJobs accept them, while AWS EventBridge does not.

Cron shorthand strings
StringEquivalentMeaning
@yearly0 0 1 1 *Once a year at midnight, 1 January. @annually is a synonym.
@monthly0 0 1 * *Midnight on the first of the month.
@weekly0 0 * * 0Midnight on Sunday.
@daily0 0 * * *Midnight every day. @midnight is a synonym.
@hourly0 * * * *The top of every hour.
@rebootNoneOnce, when the cron daemon starts after a boot. It has no time-based equivalent and is not supported everywhere.

Five examples that do not mean what they look like

These are the expressions that pass review and then behave unexpectedly in production. Each one is syntactically valid, which is why reading the computed run times matters more than reading the syntax.

1. 0 0 13 * 5: not Friday the 13th

When day of month and day of week are both restricted, standard cron runs when either matches. This fires on the 13th of every month and on every Friday, about five times a month (the 13th plus every Friday) instead of once or twice a year. To get only Friday the 13th, schedule 0 0 13 * * and guard on [ "$(date +\%u)" = "5" ] in the command.

2. * */2 * * *: not every two hours

The minute field is *, so this runs every minute of every second hour: 60 runs at 00:00-00:59, then 60 more at 02:00-02:59, and so on, for 720 runs a day. The intended expression is 0 */2 * * *.

3. 0 9-17 * * *: ends at 17:00, not 17:59

This one is correct as written, but the neighbouring case trips people up: */15 9-17 * * * runs through 17:45, because the hour range 9-17 includes the whole of the 17:00 hour. If you want coverage to stop at 17:00 exactly, the minute restriction has to do that work.

4. 0 0 31 * *: silently skips five months

February, April, June, September and November have no 31st, so a job scheduled on the 31st runs seven times a year instead of twelve. Use 28 if you want it every month, or the last-day-of-month pattern above.

5. */90 * * * *: invalid or truncated

A step larger than the field's range has no useful meaning. Depending on the implementation, cron either rejects the line outright or clamps it to something you did not intend. Cron cannot express "every 90 minutes" directly. The closest approximations are 0 */2 * * * or two separate lines such as 0 0,3,6,9,12,15,18,21 * * * plus 30 1,4,7,10,13,16,19,22 * * *.

One page per schedule

Every schedule above also has a dedicated page with live next-run times, usage notes and the trap specific to it. Browse them in the schedule reference.

Build your own

If none of these is quite right, compose the schedule field by field in the visual builder and read the next five run times before you commit it. That is the fastest way to catch a wrong schedule while it is still cheap to fix. To decode an expression you inherited from someone else's config file, paste it into the Explainer.