Skip to main content

Cloudsoft Zone Build, deploy and scale with practical guides to PHP, Node.js, React, DevOps and AI automation. Explore the guides

Cloudsoft Zone
ResourcesResource guide

Cron syntax cheat sheet: crontab, GitHub Actions, Kubernetes

Cron syntax with tested expressions, the day-of-week trap, and how time zones and limits differ in crontab, GitHub Actions, Kubernetes and Laravel in 2026.

Cloudsoft Zone

7 min read

A chrome twin-bell mechanical alarm clock on a wooden table in front of a window and a log wall
Photograph: Santeri Viinamäki / CC BY-SA 4.0, via Wikimedia Commons
In this article

Five fields separated by spaces decide when your backups run, your invoices go out and your caches clear. Cron syntax looks simple, but the same expression can behave differently in a Linux crontab, GitHub Actions, Kubernetes and a framework scheduler, mainly because of time zones and one surprising rule about days.

This cheat sheet gives you the syntax, a table of tested expressions, the differences between the platforms developers use most in October 2026, and a short checklist for running scheduled jobs safely. Every expression in the tables was evaluated with a cron parser on 9 October 2026, and the platform rules come from each project's own documentation.

The ornate face of the Prague astronomical clock, with Roman numerals, a golden sun hand and zodiac ring, flanked by carved figures
The Prague astronomical clock tracks several cycles at once. Cron's day-of-month and day-of-week fields interact in a similarly surprising way.

The five fields

Text
┌───────────── minute        (0-59)
│ ┌─────────── hour          (0-23)
│ │ ┌───────── day of month  (1-31)
│ │ │ ┌─────── month         (1-12 or jan-dec)
│ │ │ │ ┌───── day of week   (0-7 or sun-sat; 0 and 7 are Sunday)
│ │ │ │ │
* * * * *  command
SymbolMeaningExample
*Every value* * * * * runs every minute
,A list0 9,17 * * * runs at 09:00 and 17:00
-A range30 9 * * 1-5 runs at 09:30 on weekdays
/A step*/15 * * * * runs every 15 minutes
NamesFirst three letters, case-insensitive5 4 * * sun runs at 04:05 on Sundays

The cronie crontab(5) manual (the cron used by Fedora and Red Hat-family systems) notes that steps only work within their own field: */35 in the minute field runs at minutes 0 and 35 of every hour, not every 35 minutes. Kubernetes documents day-of-week as 0-6; use 0 rather than 7 for Sunday if your schedule might move between systems.

Tested expressions you can copy

Next run times below were calculated from 10:00 UTC on Friday 9 October 2026.

ExpressionMeaningNext runs
*/15 * * * *Every 15 minutes10:15, 10:30, 10:45, 11:00
0 */6 * * *Every six hours, on the hour12:00, 18:00, 00:00, 06:00
0 2 * * *Daily at 02:0010 Oct 02:00, 11 Oct 02:00 ...
30 9 * * 1-5Weekdays at 09:30Mon 12 Oct, Tue 13 Oct ...
0 22 * * 1-5Weekdays at 22:00Fri 9 Oct, Mon 12 Oct ...
0 0 * * 0Sundays at midnight11 Oct, 18 Oct, 25 Oct ...
0 3 1,15 * *1st and 15th at 03:0015 Oct, 1 Nov, 15 Nov ...
0 0 1 * *First day of each month1 Nov, 1 Dec, 1 Jan ...

Shortcut strings

MacroEquivalentNotes
@hourly0 * * * *
@daily / @midnight0 0 * * *@midnight is listed by Kubernetes; check before using elsewhere
@weekly0 0 * * 0
@monthly0 0 1 * *
@yearly / @annually0 0 1 1 *
@rebootAt daemon start-upCrontab only; no meaning in GitHub Actions or Kubernetes

The day-of-month and day-of-week trap

If both day fields are restricted, cron runs the job when either matches, not when both do. The cronie manual states this explicitly. So 0 9 1-7 * 1 does not mean "the first Monday of the month". It means "days 1 to 7, and also every Monday". Our parser confirmed it: from 9 October 2026, the next runs were Monday 12, Monday 19 and Monday 26 October, then Sunday 1 November.

To run on the first Monday, schedule 0 9 * * 1 and check the date inside the job:

Shell
# crontab: run on Mondays, continue only if the day of month is 1-7
0 9 * * 1  [ "$(date +\%d)" -le 07 ] && /usr/local/bin/monthly-report

Note the backslash before %. In a crontab, an unescaped % is turned into a newline and the rest of the line is passed to the command as standard input, a classic source of jobs that "run but do nothing".

An early twentieth-century dial time recorder with a clock face, a large ring of numbered holes and a pointer arm, on a wooden cabinet
A dial time recorder from around 1900 at the IBM history museum in Sindelfingen. Recording when work happened is as old as scheduling it.

How each platform differs

PlatformDefault time zoneSetting a time zoneOther rules
Linux crontab (cronie)The system's local timeCRON_TZ=Asia/Kolkata line in the crontabSHELL defaults to /bin/sh; set MAILTO or output is mailed to the owner
GitHub Actions scheduleUTCtimezone: key with an IANA nameMinimum interval 5 minutes; runs on the default branch; may be delayed under load
Kubernetes CronJobkube-controller-manager's local time.spec.timeZone (stable since v1.27)CRON_TZ or TZ inside the schedule is rejected
Laravel schedulerApplication time zone->timezone() or schedule_timezoneOne crontab entry runs schedule:run every minute

Linux crontab

Shell
crontab -e   # edit your crontab
crontab -l   # list it

# Example crontab
MAILTO=ops@example.com
CRON_TZ=Asia/Kolkata
15 2 * * *  /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

Cron runs with a minimal environment, so use absolute paths for commands and files. CRON_TZ is supported by cronie; other cron implementations differ, so check man 5 crontab on your server.

GitHub Actions

GitHub's workflow syntax uses POSIX cron, defaults to UTC, and now accepts an optional IANA time zone:

YAML
on:
  schedule:
    - cron: '30 5 * * 1-5'
      timezone: "America/New_York"

Three rules from GitHub's documentation matter in practice. The shortest interval is once every 5 minutes. Scheduled runs can be delayed during high load, and the start of every hour is a busy time, so pick an odd minute such as 17. And in a public repository, scheduled workflows are disabled automatically after 60 days without repository activity. For time zones with daylight saving time, GitHub says runs in a skipped hour move to the next valid time (a 02:30 run becomes 03:00).

Kubernetes CronJob

YAML
apiVersion: batch/v1
kind: CronJob
metadata:
  name: nightly-report
spec:
  schedule: "15 2 * * *"
  timeZone: "Etc/UTC"
  concurrencyPolicy: Forbid      # skip a run if the previous one is still going
  startingDeadlineSeconds: 200   # give up if it cannot start within 200 s
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: report
              image: registry.example.com/report:1.4.2

concurrencyPolicy accepts Allow (the default), Forbid and Replace. Without timeZone, schedules follow the controller manager's local time, which on managed clusters you may not control.

Laravel's scheduler

Laravel keeps schedules in code (routes/console.php) and needs one cron entry on the server:

Shell
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

Its documentation lists helpers such as ->withoutOverlapping() and ->onOneServer(), and php artisan schedule:list shows the next run of every task. Laravel's own advice on time zones is worth repeating for every platform: when daylight saving time changes, a task may run twice or not at all, so avoid time zone scheduling when possible.

Free tools for writing and checking expressions

  • crontab.guru by Cronitor translates an expression into plain English as you type. Why this resource: the fastest way to sanity-check a schedule in a code review.
  • man 5 crontab on the actual server. Why: it documents the cron implementation you really run, including which extensions it supports.
  • A parser in your test suite. For Node.js, the cron-parser package can list upcoming run times. Why: a unit test catches the day-of-week trap before production does.
JavaScript
// npm install cron-parser   (we used v5.10.2)
import { CronExpressionParser } from 'cron-parser';

const it = CronExpressionParser.parse('0 9 1-7 * 1', {
  currentDate: new Date('2026-10-09T10:00:00Z'),
  tz: 'UTC',
});
console.log(it.take(4).map((d) => d.toISOString()));
// Mondays 12, 19, 26 Oct and Sunday 1 Nov: day fields are OR-ed

A checklist for scheduled jobs

  1. Write the time zone down next to every schedule, and prefer UTC for anything that must run exactly once.
  2. Avoid 01:00 to 03:00 local time in zones with daylight saving time.
  3. Prevent overlaps: concurrencyPolicy: Forbid, Laravel's withoutOverlapping(), or flock -n /tmp/job.lock command on Linux.
  4. Make jobs idempotent, so a duplicate or retried run does no harm.
  5. Log output and alert on failure; a silent cron job is the one that stopped weeks ago.
  6. Spread load: do not schedule everything at 0 * * * *.

Frequently asked questions

  • What does */5 * * * * mean?

    Every five minutes: at minutes 0, 5, 10 and so on, of every hour, every day.

  • Why does my first-Monday schedule run every Monday?

    When both day-of-month and day-of-week are restricted, cron runs when either matches. Schedule every Monday and check the date inside the job instead.

  • Which time zone do GitHub Actions schedules use?

    UTC by default. GitHub's workflow syntax now accepts an optional timezone key with an IANA name, such as America/New_York.

  • What is the shortest interval for a GitHub Actions schedule?

    Once every 5 minutes, and runs may be delayed during high load, especially at the start of each hour.

  • Can I put CRON_TZ in a Kubernetes CronJob schedule?

    No. Kubernetes rejects CRON_TZ or TZ in .spec.schedule; use the .spec.timeZone field, stable since v1.27.

  • Why does my cron command with % fail?

    In a crontab, an unescaped % becomes a newline and the rest is sent to standard input. Escape it as \%, for example in date +\%F.

Advertise on CloudSoftZone

Your next customer could start right here.

Introduce your tool, product or business to readers exploring technology.

Advertise with us

Explore placements and request a private quote

Sources

  1. crontab(5) manual page (cronie) — man7.org / cronie
  2. Events that trigger workflows: schedule — GitHub Docs
  3. Workflow syntax: on.schedule — GitHub Docs
  4. CronJob — Kubernetes
  5. Laravel 13.x: Task Scheduling — Laravel
  6. crontab guru — Cronitor

Written with substantial AI assistance. Facts checked against cited sources. Editorial policy.

Comments

No comments yet. Be the first to join the conversation.

Leave a comment

Every comment is read by a moderator before it appears. Your email address is never published; it is used only to contact you about this comment.

Never published. Used only to contact you about this comment.

Loading the security check…

Comments are moderated before publication.