Cron every 5 minutes
*/5 * * * * does what you expect. But a step that does not divide 60 restarts every hour — so */45 fires 45 minutes apart, then 15.
By the Withuse team · Updated
The expression, and its equivalent
*/5 * * * * -> 00:05 | 00:10 | 00:15 | 00:20 0,5,10,15,20,25,30,35,40,45,50,55 * * * * -> 00:05 | 00:10 | 00:15 | 00:20
Identical results, computed with the parser on this site rather than asserted. The explicit list is worth knowing because a few restricted environments — some managed schedulers and older cron implementations — do not accept step syntax. Five divides sixty evenly, so the interval genuinely is five minutes, including across the hour boundary.
The trap: steps that do not divide 60
*/45 * * * * from 00:50 -> 01:00 | 01:45 | 02:00 | 02:45
└─45m─┘ └15m┘ └─45m─┘
*/7 * * * * from 00:50 -> 00:56 | 01:00 | 01:07 | 01:14
└─4m─┘The step divides the field's range, and the minute range restarts at the top of every hour. So */45 expands to minutes 0 and 45 — nothing else fits inside 0–59 — and the gap alternates between 45 and 15 minutes forever. */7 reaches 56 and then jumps to the next hour's 0 after only four minutes.
Only steps that divide 60 give a uniform interval: 5, 10, 15, 20 and 30. Everything else is uneven, and it will not announce itself — the job runs, just not on the rhythm you intended.
Intervals longer than an hour
No cron field spans more than an hour, so "every 90 minutes" has no direct expression. The options are to list the hours explicitly:
0 */6 * * * every 6 hours (6 divides 24 — uniform) 0 0,3,6,9,12,15,18,21 * * * every 3 hours, written out
The same divisibility rule applies to the hour field, where the range is 0–23: steps of 2, 3, 4, 6, 8 and 12 are uniform, and */5 hours is not. For a genuinely arbitrary period, a systemd timer with OnUnitActiveSec expresses it directly, or you schedule often and let the script decide whether enough time has elapsed.
Restricting to working hours
*/5 9-17 * * MON-FRI -> 09:00 | 09:05 | 09:10 | 09:15
Note that 9-17 covers the whole seventeenth hour, so the last run is 17:55 rather than 17:00. Use 9-16 to stop at the end of the sixteenth. And the schedule follows the server's timezone, so business hours need CRON_TZ or a correctly-set clock — details in cron day of week.
What breaks at this frequency
Cron starts a new instance whether or not the previous one has finished. A job that usually takes thirty seconds but occasionally takes six minutes will overlap itself, and under load the overlaps compound until something gives. Wrap it in a lock so a late run exits instead of piling up:
*/5 * * * * /usr/bin/flock -n /tmp/job.lock /path/to/job.sh >> /var/log/job.log 2>&1
The redirect matters too. A job running 288 times a day that emails its output is how people end up silencing the notification entirely — and then missing the failure that mattered. Send it to a log you can grep.
Frequently asked questions
How do I run a cron job every 5 minutes?
Write */5 * * * *, which fires at :00, :05, :10 and so on through :55 — we confirmed the sequence with a parser rather than assuming it. The equivalent explicit list, 0,5,10,15,20,25,30,35,40,45,50,55, produces exactly the same times and is worth knowing because some older or restricted implementations do not support step syntax. Five divides sixty evenly, so the interval is genuinely five minutes everywhere including across the hour boundary. That last part is not true of every step value, which is the trap covered below. Only steps that divide 60 — 5, 10, 15, 20 and 30 — stay uniform across the hour boundary, because they are the divisors of 60.
Why does */45 not run every 45 minutes?
Because the step divides the minute field's range, and that range restarts at the top of each hour. */45 expands to minutes 0 and 45 only, so the job fires at :00 and :45 — a 45-minute gap followed by a 15-minute one, repeating. We measured it: from 00:50 the next runs are 01:00, 01:45, 02:00, 02:45. Any step that does not divide 60 behaves this way. */7 is similar, producing 0, 7, 14 up to 56 and then jumping to the next hour's 0 after only four minutes. Steps of 5, 10, 15, 20 or 30 avoid it. The same divisibility rule applies to the hour field, whose range is 0-23, so a step of 5 hours is uneven for the same reason.
How do I run something every 90 minutes?
Not with a single step value, because cron has no field spanning more than an hour and the minute field resets hourly. The workable expressions are explicit: 0 0,3,6,9,12,15,18,21 * * * gives every three hours, and 0,30 approaches on alternating hours require listing them, as in 0 1,4,7,10,13,16,19,22 * * * paired with 30 on the others. For genuinely arbitrary intervals a systemd timer with OnUnitActiveSec expresses the period directly, or you schedule frequently and have the script decide whether enough time has passed since its last run, which also survives a missed slot rather than skipping the cycle, which a fixed schedule does not. The same divisibility limit applies to the hour field, so */5 hours is uneven for exactly the reason */45 minutes is.
Can I run a job every 5 minutes only during work hours?
Yes, by restricting the hour and day-of-week fields: */5 9-17 * * MON-FRI fires every five minutes from 09:00 through 17:55 on weekdays. We verified the first runs land at 09:00, 09:05, 09:10 and 09:15. Note that 9-17 includes the whole of the 17:00 hour, so the last run is 17:55 rather than 17:00 — use 9-16 if you want it to stop at the end of the sixteenth hour. Remember also that the schedule follows the server's timezone, so a job meant for local business hours needs CRON_TZ or a server on the right clock, and daylight saving will shift it twice a year otherwise, silently and without a log entry.
Is every 5 minutes too often?
It depends less on the interval than on whether the job can outlast it. Cron starts a new instance regardless of whether the previous one finished, so a task that occasionally takes six minutes will overlap itself, and under load the overlaps compound until something falls over. Guard against it with a lock — flock on Linux is the usual choice — so a late run simply exits instead of piling up. Also redirect output somewhere, because a job running 288 times a day generating mail is how people end up disabling the notification and then missing genuine failures. Send output to a log you can grep, and alert on the absence of a success line.
References
Check any expression's real run times with the cron parser, or read the field reference in crontab syntax. More tools at withuse.io/tools.