Cron every other day: 0 0 */2 * * and the month reset
0 0 */2 * * runs on days 1, 3, 5 and so on, because the day of month field starts at 1. It resets every month, so a 31 day month ends with runs on two consecutive days.
At a glance
- Expression
- 0 0 */2 * *
- Fires
- 16 times in a 31 day month, 15 in a 30 day month, 14 in a 28 day February. About 186 times a year.
- Restricted fields
- Day of month stepped by 2, minute and hour pinned. Month and day of week are open.
- Equivalent macro
- None.
- Days matched
- 1, 3, 5, 7 ... up to 31. Always the odd numbered days.
- Month boundary
- 31 January and 1 February are consecutive runs, one day apart rather than two.
In detail
The day of month field starts at 1, not 0, so a step of 2 walks 1, 3, 5 and lands on odd days only. That is different from the minute field, where the same step gives even values, and it is the single most surprising thing about day stepping. There is no way to get even days from a plain step; 2-30/2 is the explicit form for that.
The step restarts at the beginning of every month, which is what breaks the every other day promise. A 31 day month ends with a run on the 31st, and the next month begins with a run on the 1st, so those two runs are one day apart. It happens after January, March, May, July, August, October and December, which is seven times a year.
The gap can also stretch. A 30 day month ends on the 29th and the next run is the 1st, which is two days later and correct, but February in a common year ends on the 27th and the next run is 1 March, a two day gap that lands differently again in a leap year. The interval is never reliably 48 hours.
If the job genuinely needs a 48 hour cycle rather than an odd numbered day, cron is not going to give it to you. Schedule daily and guard on the parity of the epoch day count, the same technique that makes a fortnightly schedule work, and the month boundary stops mattering entirely.
Examples
0 0 */2 * *0 0 2-30/2 * *Days 2, 4, 6 through 30. Fifteen runs in any month of 30 days or more.
0 0 * * * [ $(( $(date +\%s) / 86400 \% 2 )) -eq 0 ] && /opt/app/bin/job.shDaily schedule, guarded on the parity of the epoch day number.
Things that catch people out
- */2 gives odd days here and even minutes in the minute field. The difference is entirely down to whether the field starts at 0 or 1.
- Seven times a year the job runs on two consecutive days. Anything that assumes at least 48 hours between runs will be wrong on those days.
- Adding a day of week restriction to this expression switches to the OR rule, so 0 0 */2 * 1 fires on all odd days and on every Monday.
Try it: Cron Expression Parser
Paste any five or six field expression to get a plain English description, a per field breakdown and the next run times in your local time.
Cron Expression Parser
LOCAL · Browser-OnlyParse cron expressions and see the next scheduled run times
Supports 5-field (minute hour day month weekday), 6-field (with seconds), named values (JAN, MON), and @macros (@daily, @hourly, ...)
Use the dropdowns below to build your cron expression visually, or type a custom value in each field.
Human-Readable Description
Every 5 minutes
Field Breakdown
| Field | Allowed | Value | Meaning |
|---|---|---|---|
| Minute | 0-59 | */5 | every 5 minute(s) |
| Hour | 0-23 | * | every hour |
| Day of Month | 1-31 | * | every day of month |
| Month | 1-12 | * | every month |
| Day of Week | 0-7 | * | every day of week |
Related cron expressions
All cron expressions →Cron every 3 days: 0 0 */3 * * and what happens monthly
0 0 */3 * * runs on days 1, 4, 7 and so on, 11 times in a 31 day month. The step restarts monthly, so the real gap varies from one to four days.
Cron every 15 days: 0 0 */15 * * gives days 1, 16 and 31
0 0 */15 * * matches days 1, 16 and 31, so 31 day months get three runs and the gap from the 31st to the 1st is a single day.
The cron day of month field: 1 to 31 and missing dates
The day of month field runs 1 to 31, and a date that does not exist in a given month simply never matches. Steps start at 1, giving odd days.
Cron step values: what */n really does
*/n walks a field from its minimum in increments of n. Because it starts at the field minimum, */2 gives even minutes and odd days of the month.
Cron on the first day of the month: 0 0 1 * *
0 0 1 * * runs at midnight on the 1st of every month, twelve times a year, and is exactly what the @monthly macro expands to.
Cron on the 1st and 15th: 0 0 1,15 * *
0 0 1,15 * * runs on the first and fifteenth of every month, 24 times a year. The gaps run from 13 to 17 days, so it is not a fortnight.
Tools for this
- Cron Expression Parser Free online cron expression parser - parse cron expressions and see the next scheduled run times
- Crontab Generator Free online crontab generator - build cron expressions visually with an intuitive interface