Un’espressione cron è il modo più conciso per dire a un computer “esegui questa cosa su questa pianificazione”. Cinque campi, tutti numeri e caratteri speciali, nessuna ambiguità una volta imparata la sintassi. Il problema: ci sono circa quindici pattern comuni che hai davvero bisogno, e il resto del tempo passi a fissare un prompt crontab -e cercando di ricordare se la domenica è 0 o 7.
Questo post è il cheatsheet che avrei voluto avere cinque anni fa. Ogni pattern comune, con un’espressione da copiare-incollare, una spiegazione e una nota sul trucco che frega la gente.
I cinque campi
* * * * *
│ │ │ │ │
│ │ │ │ └── giorno della settimana (0-6, Domenica=0)
│ │ │ └──── mese (1-12)
│ │ └────── giorno del mese (1-31)
│ └──────── ora (0-23)
└────────── minuto (0-59)
Ogni campo può essere:
- Un valore specifico:
5 - Un wildcard:
*(ogni valore) - Un intervallo:
1-5 - Un passo:
*/15(ogni 15) - Una lista:
1,15,30 - Un intervallo con passo:
1-30/5(ogni 5 tra 1 e 30)
Ecco tutto. Il resto è combinare questi primitivi.
I pattern
Ogni minuto
* * * * *
Caso d’uso: un job che dovrebbe essere sempre in esecuzione e il pianificatore lo sta solo riavviando. Raramente è quello che vuoi.
Ogni N minuti
*/5 * * * * # ogni 5 minuti
*/15 * * * * # ogni 15 minuti
*/30 * * * * # ogni 30 minuti
*/5 significa “a partire da 0, ogni 5 minuti”. Quindi 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55.
Trucco: la prima esecuzione di */5 è al minuto 0, non nel momento in cui hai salvato il crontab. Se lo salvi alle 12:03, la prima esecuzione è alle 12:05, non alle 12:08.
Ogni ora sull’ora
0 * * * *
Trucco: questo è “minuto 0 di ogni ora”, ovvero 1:00, 2:00, 3:00, ecc. Se vuoi “ogni ora, 30 minuti dopo”, usa 30 * * * *.
Ogni giorno a mezzanotte
0 0 * * *
Trucco: il fuso orario del server. cron usa il fuso orario di sistema. Se il tuo server è in UTC e vuoi mezzanotte nell’Est degli Stati Uniti, devi convertire. La soluzione più pulita: configura il fuso orario di sistema come desiderato, o imposta la variabile d’ambiente CRON_TZ (supportata dalla maggior parte delle implementazioni cron moderne).
Ogni giorno a un orario specifico
0 9 * * * # 9:00
30 14 * * * # 14:30
0 0 * * * # mezzanotte
15 3 * * * # 3:15
Ogni giorno lavorativo alle 9
0 9 * * 1-5
1-5 è il giorno della settimana, da lunedì a venerdì.
Trucco: 0 e 7 significano entrambi domenica. La specifica POSIX accetta entrambi. La maggior parte delle implementazioni è indulgente se usi accidentalmente 7. Non fare affidamento su questo.
Ogni lunedì
0 0 * * 1
Mezzanotte ogni lunedì.
Due volte a settimana (lunedì e giovedì)
0 9 * * 1,4
9:00 di lunedì e giovedì.
Primo giorno di ogni mese
0 0 1 * *
Mezzanotte il 1°.
Ultimo giorno del mese
0 0 L * *
L è un’estensione Vixie cron / Quartz. Lo standard cron non ce l’hai. Se usi lo standard cron, sei bloccato con approssimazioni per “ultimo giorno” come 0 0 28-31 * * (che si esegue il 28, 29, 30 e 31, e il 28 di febbraio).
Ogni trimestre
0 0 1 */3 *
Mezzanotte il 1° di gennaio, aprile, luglio, ottobre.
Ogni domenica a mezzogiorno
0 12 * * 0
Ogni 6 ore
0 */6 * * *
0:00, 6:00, 12:00, 18:00.
Ogni minuto tra le 9 e le 17, giorni lavorativi
* 9-17 * * 1-5
Un job che si esegue ogni minuto dalle 9:00:00 alle 17:59:59, da lunedì a venerdì. Probabilmente troppo aggressivo — ma possibile.
Alle 2:30 del primo giorno di ogni mese
30 2 1 * *
Alle 23 dell’ultimo venerdì del mese
0 23 * * 5#5
5#5 è “5° venerdì del mese” (sintassi Quartz). # e L sono estensioni non standard — lo standard cron non ha un’espressione per “ultimo venerdì del mese”. Se hai bisogno di questo nello standard cron, hai bisogno di uno script wrapper che controlli la data.
Ogni 30 secondi
Lo standard cron non scende sotto 1 minuto. Per una pianificazione sotto il minuto:
- systemd timer:
OnUnitActiveSec=30s - In Kubernetes CronJob: non possibile (minimo 1 minuto). Usa un Job regolare con
sleep 30in un ciclo. - In un’app Node.js:
setInterval(fn, 30_000)all’interno del processo.
Ora legale
cron gestisce l’ora legale o eseguendo il job due volte (primavera) o saltandolo (autunno), a seconda dell’implementazione. Se il tuo job è sensibile al tempo (una facturazione, un report), pianificalo ben al di fuori della finestra 1-3 AM per evitare sorprese con l’ora legale.
Lo scheduler Quartz gestisce questo con il flag DST. Lo standard cron no.
Il limite della granularità di 1 minuto
cron è fondamentalmente uno strumento con risoluzione di 1 minuto. Se hai bisogno di pianificazione sotto il minuto, la risposta è “usa uno strumento diverso”. Per Kubernetes in particolare:
apiVersion: batch/v1
kind: CronJob
metadata:
name: every-30-seconds
spec:
schedule: "* * * * *"
startingDeadlineSeconds: 10
jobTemplate:
spec:
template:
spec:
containers:
- name: worker
image: myworker:latest
command: ["/bin/sh", "-c", "for i in 1 2; do do_work; sleep 30; done"]
Questo esegue il job ogni 30 secondi lanciando due sub-job al minuto. Grezzo, ma funziona.
E Quarkus, EventBridge, Kubernetes CronJob?
Diversi scheduler usano sintassi cron leggermente diverse. La forma a cinque campi è la più comune. Alcune altre:
- Quartz: sei campi (con secondi), e il wildcard
?per “nessun valore specifico”. - AWS EventBridge: sei campi, supporta le estensioni
Le#. - Kubernetes CronJob: cinque campi, nessun supporto per
Lo#. - Spring
@Scheduled: sei campi (con secondi), supporto per?eL. - GitHub Actions: cinque campi, nessuna estensione.
Se stai usando uno strumento che non corrisponde allo standard, consulta la documentazione. La maggior parte dei pattern in questo cheatsheet si trasferisce direttamente. Le estensioni non standard (L, #, W) non lo fanno.
Generare espressioni cron senza memorizzare la sintassi
Se non vuoi memorizzare la sintassi, il generatore cron su DevSpeedTools ti permette di cliccare attraverso i cinque campi e mostra le prossime cinque esecuzioni pianificate. È il modo più veloce per verificare “0 9 * * 1-5 significa davvero 9:00 nei giorni lavorativi?” — la risposta è sì, ma vedere le date delle prossime esecuzioni rende il pattern concreto.
Per espressioni occasionali, crontab.guru è il riferimento standard. Il generatore cron fa lo stesso lavoro ed è completamente lato client, quindi le espressioni che incolli non lasciano mai il tuo browser.
In breve
Le espressioni cron sono una piccola DSL con alcune regole. Impara i cinque campi, impara * (qualsiasi), - (intervallo), / (passo) e , (lista), e puoi esprimere il 95% delle pianificazioni di cui avrai mai bisogno. L’altro 5% necessita di estensioni specifiche per lo scheduler o uno strumento diverso. In caso di dubbio, genera e visualizza l’espressione con uno strumento che mostra le prossime esecuzioni — molto più veloce del debug mentale.