Crontab Cheat Sheet: 50+ cron-expressies, syntax en moderne scheduler-gids
Een cron-expressie bestaat uit vijf velden (minuut, uur, dag-van-de-maand, maand, dag-van-de-week) gevolgd door een commando. Die grammatica stuurt Unix-scheduling al sinds 1979 aan, en draait nu ook achter Kubernetes CronJobs, GitHub Actions, AWS EventBridge en Vercel cron-triggers. Eén keer leren is genoeg.
Deze pagina is bedoeld voor developers die nu meteen een expressie nodig hebben voor een Linux-taak, een Kubernetes CronJob, een GitHub Actions-trigger, of voor het uitzoeken waarom een job van vijf minuten alleen elk uur draait. Scrol naar de tabel met snelle referentie voor kopieerklare expressies, spring naar Cron-syntax ontleed voor de veldregels, of open de Crontab generator — cron-uitdrukking bouwen & ontleden — een privacy-first crontab guru-alternatief dat draait in je browser — om expressies live te valideren.
Cron-expressies — tabel met snelle referentie
Dertig expressies die ~90% van de echte planningsbehoeften dekken. Elke regel is een geldige POSIX cron met vijf velden. Plak in crontab -e, in een Kubernetes schedule: of in een GitHub Actions cron:.
| Schema | Cron-expressie | In gewone taal |
|---|---|---|
| Elke minuut | * * * * * | elke minuut, de hele dag, elke dag |
| Elke 5 minuten | */5 * * * * | minuut 0, 5, 10, …, 55 |
| Elke 15 minuten | */15 * * * * | minuut 0, 15, 30, 45 |
| Elke 30 minuten | */30 * * * * | minuut 0 en 30 |
| Elk uur | 0 * * * * | bij het hele uur |
| Elke 2 uur | 0 */2 * * * | uur 0, 2, 4, …, 22 |
| Elke 6 uur | 0 */6 * * * | uur 0, 6, 12, 18 |
| Twee keer per dag (09:00 + 21:00) | 0 9,21 * * * | minuut 0 van uur 9 en 21 |
| Elke werkdag om 09:00 | 0 9 * * 1-5 | ma-vr 09:00 |
| Elk weekend om 09:00 | 0 9 * * 0,6 | za en zo 09:00 |
| Dagelijks om middernacht | 0 0 * * * | elke dag 00:00 |
| Dagelijks om 02:30 | 30 2 * * * | rustig batchvenster |
| Elke maandag om 09:00 | 0 9 * * 1 | maandagen 09:00 |
| Elke vrijdag om 17:00 | 0 17 * * 5 | vrijdagen 17:00 |
| Elke zondag om middernacht | 0 0 * * 0 | gelijk aan @weekly |
| Eerste van de maand om middernacht | 0 0 1 * * | dag 1 om 00:00 — gelijk aan @monthly |
| 15e van elke maand om twaalf uur | 0 12 15 * * | venster voor maandelijkse loonrun |
| Laatste-dag-check (wrapper) | 0 0 28-31 * * + script | vereist een datumcheck |
| Per kwartaal (1 jan/apr/jul/okt) | 0 0 1 JAN,APR,JUL,OCT * | eerste dag van elk kwartaal |
| Jaarlijks (1 jan) | 0 0 1 1 * of @yearly | nieuwjaar middernacht |
| Elke 5 min op werkdagen 9-17 | */5 9-17 * * 1-5 | polling tijdens kantooruren |
| Elke 30 min in het weekend | */30 * * * 0,6 | za/zo monitoring |
| Twee keer per uur, 15 en 45 | 15,45 * * * * | offset weg van de :00-stormloop |
| Eerste maandag (wrapper) | 0 9 1-7 * 1 + AND-check | wrapper nodig (zie onder) |
| Macro’s | @hourly @daily @weekly @monthly @yearly | niet-standaard, maar breed ondersteund |
| Alleen bij reboot | @reboot | niet-standaard, alleen vixie cron |
Plak een van deze in de Crontab generator — cron-uitdrukking bouwen & ontleden voor een voorbeeld van de volgende vijf uitvoeringen. Dat is de snelste check vóór een deploy.
Cron-syntax ontleed — de 5 velden
Een cron-expressie bestaat uit vijf velden gescheiden door witruimte, plus een commando. Elk veld bepaalt één deel van het schema. Dezelfde syntax komt terug bij elke scheduler in deze gids.
┌──────────── minuut (0 - 59)
│ ┌────────── uur (0 - 23)
│ │ ┌──────── dag-van-maand (1 - 31)
│ │ │ ┌────── maand (1 - 12 of JAN-DEC)
│ │ │ │ ┌──── dag-van-week (0 - 6 of SUN-SAT; 0 en 7 betekenen beide zondag)
│ │ │ │ │
* * * * * uit-te-voeren-commando
Geheugensteuntje: “My Hat Doesn’t Match Wendy’s” voor Minute, Hour, Day-of-month, Month, Weekday. Van links naar rechts, van kleinste eenheid naar grootste.
Toegestane waarden per veld
| Veld | Bereik | Aliassen | Opmerkingen |
|---|---|---|---|
| Minuut | 0-59 | geen | 0 betekent “op het hele uur” |
| Uur | 0-23 | geen | 24-uurs klok; 0 is middernacht, 12 is twaalf uur ‘s middags |
| Dag-van-maand | 1-31 | geen | ongeldige dagen voor een maand vuren stilzwijgend nooit (31 februari) |
| Maand | 1-12 | JAN, FEB, MAR, …, DEC | hoofdletter-ongevoelig |
| Dag-van-week | 0-7 | SUN, MON, TUE, …, SAT | 0 en 7 betekenen beide zondag |
Operatoren in detail
Vijf operatoren dekken elke standaard cron-expressie.
| Operator | Betekenis | Voorbeeld | Breidt uit naar |
|---|---|---|---|
* | elke waarde | * * * * * | elke minuut |
, | lijst | 0 9,12,17 * * * | 09:00, 12:00, 17:00 |
- | inclusief bereik | 0 9-17 * * * | elk uur van 09:00 tot 17:00 |
/ | stap | */15 * * * * | minuut 0, 15, 30, 45 |
| gemengd | gecombineerd | 0 9-12,14-17 * * * | ochtend + middag, sla lunch over |
De stap-operator verdient extra aandacht. */N is verankerd aan de laagste waarde van het veld, niet aan de huidige tijd. */15 betekent “minuut 0, 15, 30, 45 van elk uur”, niet “elke 15 minuten vanaf nu”. Sla op om 12:03 en de volgende uitvoering is om 12:15. Met een niet-wildcard als basis lees je 5/15 als “begin bij 5, daarna elke 15”: minuut 5, 20, 35, 50.
Benoemde maanden en weekdagen
Schrijf maanden en weekdagen als namen, hoofdletter-ongevoelig:
0 0 1 JAN,APR,JUL,OCT * # eerste van elk kwartaal
0 9 * * MON-FRI # werkdagen om 9 uur
0 17 * * FRI # vrijdag om 17 uur
Namen lezen prettiger in code review; numerieke vormen zijn iets beter overdraagbaar. Kies één stijl en houd die per project aan.
Niet-standaard macro’s: @reboot, @daily en consorten
De meeste cron-implementaties accepteren zes shortcut-macro’s:
| Macro | Breidt uit naar | Betekenis |
|---|---|---|
@yearly / @annually | 0 0 1 1 * | één keer per jaar, 1 jan om middernacht |
@monthly | 0 0 1 * * | eerste van elke maand om middernacht |
@weekly | 0 0 * * 0 | elke zondag om middernacht |
@daily / @midnight | 0 0 * * * | elke dag om middernacht |
@hourly | 0 * * * * | bij het hele uur |
@reboot | (speciaal) | één keer wanneer de cron-daemon start |
Deze macro’s zijn niet-standaard: vixie cron en cronie ondersteunen ze, maar Kubernetes CronJob, GitHub Actions en AWS EventBridge niet. Voor overdraagbare expressies schrijf je de vorm met vijf velden. @reboot werkt zelden in containers, omdat de cron-daemon daar vaak niet eens het init-proces is.
50+ kopieerklare cron-expressies (gegroepeerd per use case)
De tabel met snelle referentie dekt de gangbare gevallen. Hieronder volgen zes categorieën met meer cron job-voorbeelden.
Elke N minuten
* * * * * # elke minuut
*/2 * * * * # elke 2 minuten
*/5 * * * * # elke 5 minuten — het klassieke "cron expression every 5 minutes"
*/10 * * * * # elke 10 minuten
*/15 * * * * # elke 15 minuten
*/30 * * * * # elke 30 minuten
0,30 * * * * # expliciet minuut 0 en 30 (gelijk aan */30)
*/45 * * * * # LET OP: vuurt alleen bij 0 en 45, daarna wraps het
*/45 is een bekende valkuil: minuut loopt van 0-59, dus het landt op 0 en 45 en wraps daarna bij het volgende uur. Voor een echte cadans van 45 minuten draai je een langlopende worker.
Variaties per uur
0 * * * * # elk uur op :00
30 * * * * # elk uur op :30
0 */2 * * * # elke 2 uur, even uur
0 */6 * * * # elke 6 uur
0 */12 * * * # twee keer per dag, om 00:00 en 12:00
15 */2 * * * # elke 2 uur, met 15 min offset (vermijdt de :00-piek)
Dagelijks op specifieke tijden
0 0 * * * # middernacht (= @daily / @midnight)
30 2 * * * # 02:30 — rustig batchvenster
0 9 * * * # 09:00
45 23 * * * # 23:45 — afsluitingen aan het einde van de dag
0 9,12,17 * * * # drie keer per dag
0 9-17 * * * # elk uur van 09:00 tot en met 17:00
Weekschema’s
0 9 * * 1-5 # werkdagen om 9 uur
0 9 * * 0,6 # weekenden om 9 uur
0 18 * * 5 # vrijdag om 18 uur
0 0 * * 0 # zondag om middernacht (= @weekly)
0 9 * * MON,WED,FRI # ma/wo/vr om 9 uur
*/30 9-17 * * 1-5 # elke 30 min, kantooruren, werkdagen
Maandelijks en per kwartaal
0 0 1 * * # 1e van de maand om middernacht (= @monthly)
0 0 15 * * # 15e — loonvenster
0 0 1,15 * * # 1e en 15e — twee keer per maand
0 0 1 */3 * # per kwartaal: 1e jan, apr, jul, okt
0 0 1 JAN,APR,JUL,OCT * # idem, met maandnamen
0 0 28-31 * * # laatste paar dagen — combineer met een datumcheck-wrapper
Laatste-dag-van-de-maand kent geen native POSIX-expressie. Draai een wrapper die date -d tomorrow +%d = 01 controleert, of gebruik een scheduler met ingebouwde ondersteuning (Quartz heeft L; Kubernetes niet).
Jaarlijks en macro-shortcuts
0 0 1 1 * # 1 jan om middernacht (= @yearly / @annually)
0 0 25 12 * # Kerstmis om middernacht
@yearly # = 0 0 1 1 *
@monthly # = 0 0 1 * *
@weekly # = 0 0 * * 0
@daily # = 0 0 * * *
@hourly # = 0 * * * *
@reboot # speciaal: één keer bij start van de daemon (alleen vixie cron)
Al deze expressies plak je in de Crontab generator — cron-uitdrukking bouwen & ontleden voor een voorbeeld van de volgende vijf uitvoeringen, de goedkoopste smoke test vóór een deploy.
Cron vs systemd timers vs cloud-schedulers — beslismatrix
Cron is de standaardkeuze, niet altijd de beste keuze. Hieronder een vergelijking van de zeven meest gebruikte schedulers, handig bij keuzes als cron versus systemd timer, Kubernetes CronJob versus Vercel cron job, of een migratie van crontab naar managed cloud.
| Feature | vixie cron | systemd timer | K8s CronJob | GHA schedule | AWS EventBridge | Vercel Cron | Cloudflare Workers |
|---|---|---|---|---|---|---|---|
| Veldsyntax | 5-veld POSIX | OnCalendar-spec | 5-veld POSIX + timeZone | 5-veld POSIX | 6-veld Quartz met ? | 5-veld POSIX | 5-veld POSIX |
| Minimaal interval | 1 minuut | 1 seconde | 1 minuut | best-effort, ≥15 min aanbevolen | 1 minuut | 1 minuut (Pro plan) | 1 minuut |
| Expliciete timezone | CRON_TZ= | Persistent=true | spec.timeZone (1.27+) | alleen UTC | ScheduleExpressionTimezone | alleen UTC | alleen UTC |
| Inhalen gemiste runs | nee (gebruik anacron) | ja (Persistent=true) | ja (startingDeadlineSeconds) | nee | ja | nee | nee |
| Retry / backoff | nee | gedeeltelijk | ja (backoffLimit) | retry bij falen | ja | nee | ja |
| Concurrency-control | nee (gebruik flock) | gedeeltelijk | ja (concurrencyPolicy) | nee | nee | nee | nee |
@reboot-ondersteuning | ja | ja (via OnBootSec=) | nee | nee | nee | nee | nee |
systemd timers — wanneer verkies je ze boven cron
Op systemd-gebaseerde Linux zijn timers een serieus alternatief. Ze bieden leesbare kalendersyntax, journal-integratie en inhalen van gemiste runs. Een timer met bijbehorende service:
# daily-report.timer
[Unit]
Description=Run daily report at 9 AM
[Timer]
OnCalendar=*-*-* 09:00:00
Persistent=true
Unit=daily-report.service
[Install]
WantedBy=timers.target
# daily-report.service
[Unit]
Description=Daily report job
[Service]
Type=oneshot
ExecStart=/usr/local/bin/daily-report.sh
User=reporter
Activeer met systemctl enable --now daily-report.timer. De winst zit in Persistent=true: stond de machine om 9 uur uit, dan vuurt de timer zodra hij weer opstart. Vixie cron heeft hier geen equivalent voor, behalve met anacron. Voor service-hardening, zie onze aanbevolen aanpak voor security.
Kubernetes CronJob
Kubernetes pakt het POSIX-schema in met primitieven voor concurrency, geschiedenis en expliciete timezone.
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-report
spec:
schedule: "0 2 * * *"
timeZone: "America/New_York" # Kubernetes 1.27+
concurrencyPolicy: Forbid # nooit twee tegelijk
startingDeadlineSeconds: 300 # overslaan bij vertraging >5 min
jobTemplate:
spec:
backoffLimit: 2
template:
spec:
restartPolicy: OnFailure
containers:
- name: reporter
image: reporter:1.4.0
command: ["/usr/local/bin/report.sh"]
concurrencyPolicy: Forbid is jouw flock-equivalent. Zonder dat stapelt een langlopende job zich op zijn opvolger. Zie de veldreferentie-sectie voor alle knoppen.
Aandachtspunten van GitHub Actions schedule
GitHub Actions accepteert standaard POSIX cron met vijf velden:
on:
schedule:
- cron: '0 9 * * 1-5' # werkdagen om 9 uur UTC
Best-effort: bij hoge belasting op de GitHub-runners kunnen jobs minuten te laat vuren of helemaal overgeslagen worden. Vermijd intervallen korter dan vijftien minuten. Geen timezone-instelling, altijd UTC.
AWS EventBridge — zes velden in Quartz-stijl
AWS EventBridge gebruikt een Quartz-achtige cron met zes velden en een verplichte ? in een van de twee dag-slots:
cron(0 9 * * ? *)
Veldvolgorde: Minutes Hours Day-of-month Month Day-of-week Year. Een van de dag-velden moet ? zijn als de ander beperkt is (de manier van Quartz om de POSIX-OR-dubbelzinnigheid op te lossen). Een directe kopie uit Linux crontab faalt op validatie.
Vercel Cron, Cloudflare Workers, Render Cron Jobs
De nieuwere serverless-platforms standaardiseren op POSIX met vijf velden. Een Vercel cron job woont in vercel.json als { "crons": [{ "path": "/api/cron/nightly", "schedule": "0 2 * * *" }] }. Cloudflare Workers Cron Triggers gebruiken wrangler.toml:
[triggers]
crons = ["*/15 * * * *", "0 9 * * 1-5"]
Render gebruikt render.yaml. Alle drie draaien op UTC zonder timezone-override per schema. Ontwerp vanaf het begin in UTC.
7 cron-debugvallen (en hoe je ze betrapt)
De meeste meldingen van “mijn cron job draait niet” hebben een van zeven oorzaken. Loop ze af voordat je de scheduler de schuld geeft.
Val 1: PATH is minimaal
Cron start jobs met een minimale $PATH, typisch /usr/bin:/bin. Jouw interactieve shell heeft /usr/local/bin, ~/.cargo/bin en een tiental .bashrc-regels. Niets daarvan bestaat in cron. Dit is de meest voorkomende oorzaak bij cron debugging path environment.
Symptoom: node: command not found. Fix: zet PATH bovenaan de crontab, of gebruik absolute paden.
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin
*/15 * * * * /usr/local/bin/poll-api.sh
0 9 * * * /home/deploy/.cargo/bin/my-rust-cli
Val 2: stdout en stderr verdwijnen geruisloos
Standaard gaat de cron-output naar een mail-spool die niemand leest. De job faalt geruisloos. Stuur beide streams door:
*/15 * * * * /usr/local/bin/job.sh >> /var/log/job.log 2>&1
Voor JSON-output pipe je door jq; voor het extraheren van logregels zie onze regex cheat sheet. Voor systemd timers vangt journalctl -u your-timer.service de output op.
Val 3: Timezone drift tussen dev en prod
Je schreef 0 9 * * * op je laptop in New York en verwachtte 9 uur Eastern. De server draait UTC. De cron vuurt om 9:00 UTC, dus 04:00 Eastern, voor iemand het doorheeft. Fix: zet servers op UTC en schrijf schema’s in UTC, of pin de timezone expliciet.
CRON_TZ=America/New_York
0 9 * * * /usr/local/bin/morning-report.sh
CRON_TZ werkt in vixie cron 3.0+; Kubernetes 1.27+ heeft spec.timeZone; AWS EventBridge heeft ScheduleExpressionTimezone; GitHub Actions blijft altijd UTC. Voor UTC, zomertijd en epoch-rekenwerk zie onze Unix timestamp-gids.
Val 4: Niet-geëscapete % in commando’s
Cron behandelt een niet-geëscapete % als een newline; de rest van de regel wordt aan het commando gevoerd als stdin. date +"%Y-%m-%d" breekt dus. Escape elke % als \%, of verplaats de logica naar een script:
0 0 * * * echo "Run at $(date +"\%Y-\%m-\%d")" >> /tmp/log
Val 5: Overlappende uitvoeringen
Een */5 * * * *-job die af en toe zeven minuten kost, start zijn volgende instantie voordat de vorige klaar is. Twee kopieën vechten om dezelfde row, lock-bestand en API-quota. Serialiseer met flock:
*/5 * * * * flock -n /tmp/job.lock /usr/local/bin/job.sh
-n stopt meteen als de lock vastligt. Voor Kubernetes zet je concurrencyPolicy: Forbid. Permissies op het lock-bestand doen ertoe; zie aanbevolen aanpak voor security.
Val 6: @reboot in containers
@reboot draait één keer wanneer de cron-daemon start. In een VM komt dat overeen met boot. In een container is de cron-daemon meestal niet PID 1 en draait soms helemaal niet. Gebruik @reboot niet in containers; zet run-eenmalig-bij-boot-logica in je entrypoint of in een init-container.
Val 7: POSIX OR-semantiek tussen dag-van-maand en dag-van-week
De duurste cron-val. POSIX-regel: als zowel dag-van-maand als dag-van-week beperkt zijn (geen van beide is *), vuurt het schema wanneer een van beide matcht.
0 0 1 * 5 lijkt op “middernacht op de 1e, alleen op vrijdagen”, maar vuurt op de 1e EN elke vrijdag: zes tot tien extra uitvoeringen per maand.
# FOUT: lijkt op "1e van de maand, alleen als het vrijdag is"
0 0 1 * 5
# GOED: kies één beperking
0 0 1 * * # elke 1e van de maand
0 0 * * 5 # elke vrijdag
# AND-semantiek vereist een wrapper
0 0 1-7 * 5 [ "$(date +\%u)" = "5" ] && /script # alleen eerste vrijdag
Plak verdachte expressies in de Crontab generator — cron-uitdrukking bouwen & ontleden; het voorbeeld van de volgende uitvoering maakt de OR-val direct zichtbaar.
Moderne schedulers — wanneer cron NIET de juiste keuze is
Cron past bij “draai dit commando ongeveer op deze tijd, in een vaste cadans”. Voor de volgende problemen kies je iets anders:
- Workflows met afhankelijkheden (draai A, daarna B als A geslaagd is): Airflow, Prefect, Dagster.
- Retry, exponentiële backoff, dead-letter queues: Temporal, AWS Step Functions, Sidekiq.
- Intervallen onder de minuut: langlopende worker die tussen iteraties slaapt.
- Timing op de seconde: speciale daemon; managed schedulers garanderen geen exacte timing.
- Event-driven werk: webhooks, message queues, change-data-capture streams.
Cron verdwijnt niet uit dat plaatje. Airflow, Step Functions en Sidekiq accepteren allemaal cron-expressies voor het ingangspunt van hun workflows. De grammatica met vijf velden blijft herbruikbaar.
Kubernetes CronJob — veldreferentie
De beslismatrix hierboven toonde een minimale CronJob. Hieronder de volledige veldreferentie voor kubernetes cronjob syntax.
| Veld | Default | Wat het doet |
|---|---|---|
schedule | verplicht | POSIX cron-expressie met 5 velden |
timeZone | controller-TZ | expliciete timezone (1.27+); gebruik IANA-namen |
concurrencyPolicy | Allow | Forbid slaat nieuwe runs over zolang vorige actief is; Replace annuleert die |
startingDeadlineSeconds | ongebonden | sla over als de vertraging groter is dan dit |
successfulJobsHistoryLimit | 3 | aantal geslaagde Jobs om te bewaren |
failedJobsHistoryLimit | 1 | aantal mislukte Jobs om te bewaren |
suspend | false | pauzeren zonder verwijderen |
backoffLimit | 6 | Pod-retries voordat de Job als Failed wordt gemarkeerd |
activeDeadlineSeconds | niet gezet | harde limiet op Pod-runtime |
ttlSecondsAfterFinished | niet gezet | Job automatisch verwijderen na zoveel seconden |
Twee veelvoorkomende valkuilen: timeZone vergeten zorgt dat het schema de host-timezone van de kube-controller-manager volgt (onvoorspelbaar op managed Kubernetes); op een schema van één minuut stapelen drie Job-objecten per minuut op bij de default successfulJobsHistoryLimit: 3, tenzij ttlSecondsAfterFinished is gezet.
Cron-equivalenten per platform
macOS launchd. Apple adviseert launchd boven cron. Een launchd-job is een .plist in ~/Library/LaunchAgents/:
<plist version="1.0"><dict>
<key>Label</key><string>com.example.daily</string>
<key>ProgramArguments</key><array><string>/usr/local/bin/daily.sh</string></array>
<key>StartCalendarInterval</key>
<dict><key>Hour</key><integer>9</integer><key>Minute</key><integer>0</integer></dict>
</dict></plist>
Laden met launchctl load ~/Library/LaunchAgents/com.example.daily.plist. Anders dan cron haalt launchd gemiste runs in na sleep of wake.
Windows Task Scheduler gebruikt schtasks:
schtasks /create /tn "DailyReport" /tr "C:\scripts\report.bat" /sc DAILY /st 09:00
schtasks /create /tn "EveryFifteen" /tr "C:\scripts\poll.bat" /sc MINUTE /mo 15
Op WSL werkt native Linux cron, maar het stopt zodra de sessie eindigt. Gebruik Task Scheduler om altijd-aan WSL-jobs te starten.
Cron in Docker-containers. De meeste slim-images (alpine, debian-slim, distroless) leveren geen cron-daemon mee. Installeer cronie of busybox-cron en draai ze als PID 1 met tini of s6-overlay. In de praktijk is een Kubernetes CronJob bijna altijd een betere keuze.
Geavanceerde tips en patronen
Laatste dag van de maand
Cron heeft geen ingebouwde “laatste dag”-operator. Draai elke dag in het venster 28-31 en kijk of morgen de 1e is:
0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && /usr/local/bin/eom.sh
N-de weekdag van de maand
“Eerste maandag” gebruikt hetzelfde wrapper-patroon: beperk tot dag 1-7 en check daarna de weekdag.
0 9 1-7 * * [ "$(date +\%u)" = "1" ] && /usr/local/bin/first-monday.sh
Voor “laatste vrijdag” gebruik je dag 25-31 plus de check op dag-van-week.
Willekeurige offset om load te spreiden
Als veel machines dezelfde cron draaien, levert 0 0 * * * een thundering herd op om middernacht UTC. Strooi een willekeurige vertraging in:
RANDOM_DELAY=10 # cronie / anacron, in minuten
0 0 * * * /usr/local/bin/job.sh
0 0 * * * sleep $((RANDOM \% 600)); /usr/local/bin/job.sh # overdraagbaar
Heartbeat-monitoring
Cron faalt geruisloos. Het dead-man’s-switch-patroon werkt zo: de job pingt een monitoring-service na elke geslaagde uitvoering, en de service waarschuwt als een verwachte ping uitblijft. Healthchecks.io, Cronitor en Dead Man’s Snitch bieden gratis tiers.
*/15 * * * * /usr/local/bin/job.sh && curl -fsS --retry 3 https://hc-ping.com/your-uuid
Voor monitoring-logica die zich vertakt op responscodes (200 gezond, 429 rate-limited, 503 degraded) zie onze HTTP-statuscodes cheat sheet.
Idempotentie is een eigenschap van de job, niet van de scheduler
Cron biedt geen retry, geen inhalen van gemiste runs, geen concurrency-control. De betrouwbaarste fix is de job zelf veilig maken om vaker te draaien. In plaats van “stuur het rapport van vandaag om 9 uur”, ontwerp je het als “stuur het rapport van vandaag als het nog niet verstuurd is”. Gemiste runs, duplicaten en handmatige inhaalslagen komen dan allemaal uit op dezelfde eindtoestand.
FAQ
Is */5 * * * * echt elke 5 minuten?
Bijna — */5 * * * * is verankerd aan minuut 0, niet “elke 5 minuten vanaf nu”. Het vuurt op minuut 0, 5, 10, …, 55 van elk uur. De stap */N is relatief aan de laagste waarde van het veld, niet aan de huidige tijd. Sla op om 12:03 en de volgende uitvoering is om 12:05, niet om 12:08.
Wat betekent 0 0 * * * in cron?
0 0 * * * betekent elke dag om middernacht (00:00) in de lokale timezone van de server. Velden: minuut 0, uur 0, willekeurige dag-van-maand, willekeurige maand, willekeurige dag-van-week. Gelijkwaardig aan de macro’s @daily of @midnight. Om de timezone vast te pinnen, zet je CRON_TZ=America/New_York bovenaan de crontab.
Hoe draai ik een cron job elke 30 seconden?
Dat kan niet met standaard POSIX cron; de minimale granulariteit is één minuut. Er zijn drie workarounds: twee gestaggerde jobs op * * * * * met sleep 30 && op één ervan; een systemd timer met OnCalendar=*:*:0/30; of een langlopende worker die tussen iteraties slaapt. De laatste is meestal de juiste keuze.
Welke timezone gebruikt cron standaard?
De lokale system-timezone van de server (/etc/timezone of de TZ-environmentvariabele). Een 9 uur-cron op een UTC-server vuurt om 4 uur in US East. Fix: zet CRON_TZ= bovenaan de crontab, of zet servers op UTC en ontwerp schema’s in UTC. GitHub Actions blijft altijd UTC; Kubernetes 1.27+ ondersteunt spec.timeZone.
Waarom draait mijn cron job niet?
Als je cron job niet draait, controleer dan in deze volgorde: draait de cron-daemon (systemctl status cron); is $PATH gezet in de crontab; wordt stderr gevangen (>> log 2>&1); is de crontab van de gebruiker geladen (crontab -l); is % geëscapet in commando’s; is de timezone wat je verwacht. De meeste “draait niet”-meldingen zijn punt twee of drie.
Is de syntax van Kubernetes CronJob hetzelfde als die van Linux cron?
Voor het schedule-veld wel: beide gebruiken POSIX cron met vijf velden. Kubernetes voegt spec.timeZone (1.27+) toe, concurrencyPolicy voor overlap-control, startingDeadlineSeconds voor inhalen van gemiste runs, en suspend: true om te pauzeren. Linux cron heeft hier niets van; daar grijp je naar flock en anacron.
Wat is het verschil tussen @reboot en @daily?
@daily is een macro voor 0 0 * * *, elke dag om middernacht volgens een vast schema. @reboot draait één keer wanneer de cron-daemon start, zonder terugkerend schema. @reboot wordt ondersteund door vixie cron en cronie, maar niet door Kubernetes CronJob, GitHub Actions of AWS EventBridge. In containers vuurt @reboot zelden.
Wat is het verschil tussen cron en crontab?
cron is de achtergrond-daemon die geplande taken uitvoert; crontab is het bestand dat deze taken opsomt (en het crontab-commando om dat bestand te bewerken). De daemon leest periodiek de crontab van elke gebruiker en voert de commando’s uit waarvan de uitvoeringstijd overeenkomt met de cron-expressie. Kortom: cron is de motor, crontab is het recept.