Cron syntax cheat sheet

The reference for reading and writing cron expressions — every field, every operator, common recipes, and the day-of-week trap that catches everyone.

5 min read

Cron syntax is compact, powerful, and easy to misread — one wrong asterisk and your "hourly" job runs every minute. This is the cheat sheet we keep pinned. Everything here works in standard Unix cron, GitHub Actions, Kubernetes CronJobs, and most cloud schedulers. When in doubt, paste your expression into the cron explainer to see the next five runs.

The five fields

┌───────────── minute       (0 - 59)
│ ┌─────────── hour         (0 - 23)
│ │ ┌───────── day of month (1 - 31)
│ │ │ ┌─────── month        (1 - 12 or JAN-DEC)
│ │ │ │ ┌───── day of week  (0 - 6 or SUN-SAT; 0 and 7 both = Sunday)
│ │ │ │ │
* * * * *  command

Field operators

  • * — every value.
  • , — list. 0,15,30,45 at minute 0, 15, 30, 45.
  • - — range. 1-5 Monday through Friday in the day-of-week field.
  • / — step. */15 every 15 units. 2-20/2 even numbers 2 to 20.

Common expressions

ExpressionMeaning
* * * * *Every minute.
*/5 * * * *Every 5 minutes.
0 * * * *Top of every hour.
0 */2 * * *Every 2 hours on the hour.
0 9 * * *Every day at 09:00.
0 9 * * 1-5Weekdays at 09:00.
0 9 * * 1Every Monday at 09:00.
0 0 1 * *Midnight on the 1st of every month.
0 0 1 1 *Midnight on January 1st.
30 3 * * 0Sundays at 03:30 — a classic weekly backup slot.
0 0 * * 6#1First Saturday of the month (non-standard, Quartz-style).

Named aliases

These are supported by Vixie cron, GitHub Actions, and most modern implementations:

AliasEquivalent
@yearly / @annually0 0 1 1 *
@monthly0 0 1 * *
@weekly0 0 * * 0
@daily / @midnight0 0 * * *
@hourly0 * * * *

The day-of-month / day-of-week trap

When both day-of-month and day-of-week are restricted (neither is *), most cron implementations run the job when either matches — not both. So 0 12 13 * 5 runs at noon every Friday and on the 13th of every month, not only on "Friday the 13th". Keep one of them as * unless you actually want the union.

Timezone gotchas

  • Most cron daemons run in the server's local timezone. GitHub Actions uses UTC. Kubernetes CronJobs default to UTC.
  • Daylight saving transitions can skip or double-fire a job scheduled during the shifted hour. Schedule critical jobs outside 01:00–03:00 local time, or run them in UTC.
  • Verify with the cron explainer — it prints the next five occurrences in UTC so you can spot off-by-one-hour mistakes.

Seconds precision (Quartz / Spring)

Some schedulers — Quartz, Spring's @Scheduled, AWS EventBridge — accept a sixth field for seconds at the front of the expression: 0 0 9 * * MON-FRI. Standard Unix cron does not; adding a sixth field there will error out.

Debugging a cron job that isn't running

  1. Confirm the expression with a parser — one misplaced space is enough to break it.
  2. Check the daemon's log (/var/log/cron, journalctl -u cron).
  3. Redirect stdout and stderr to a file: * * * * * /path/cmd >> /tmp/cmd.log 2>&1.
  4. Verify the executing user has the PATH and env vars your command needs — cron's PATH is minimal.
  5. For containers, remember that cron only fires while the container is running.

Cron isn't magic — it's a five-column table with a few operators. Once the fields click, reading a crontab is the same skill as reading a recipe.

Try the tools

Related reading