Come leggere un'espressione cron
Un'espressione cron è fatta di cinque valori separati da spazi, letti da sinistra a destra come minuto, ora, giorno del mese, mese, giorno della settimana. Il job viene eseguito quando l'ora corrente corrisponde a ogni campo.
30 4 * * 1
│ │ │ │ │
│ │ │ │ └── day of week (1 = Monday)
│ │ │ └──── month (any)
│ │ └────── day of month (any)
│ └──────── hour (4am)
└─────────── minute (30)
Quella si legge «alle 04:30 di ogni lunedì».
I cinque campi
| # | Campo | Valori ammessi | Note |
|---|---|---|---|
| 1 | Minuto | da 0 a 59 | |
| 2 | Ora | da 0 a 23 | Orologio a 24 ore, 0 è la mezzanotte |
| 3 | Giorno del mese | da 1 a 31 | |
| 4 | Mese | da 1 a 12, oppure da JAN a DEC | |
| 5 | Giorno della settimana | da 0 a 6, oppure da SUN a SAT | 0 è domenica, e la maggior parte delle implementazioni di cron accetta anche 7 |
Alcuni schedulatori usano una forma diversa. Quartz, usato da parecchio software Java, mette i secondi per primi e aggiunge un anno facoltativo, e numera i giorni della settimana da 1 a 7 partendo da domenica. Se un'espressione ha sei o sette campi, controlla per quale sistema è stata scritta prima di fidarti della tua lettura.
Gli operatori
Sono quattro, e si combinano all'interno di un singolo campo.
| Simbolo | Nome | Esempio | Significato |
|---|---|---|---|
* | Qualsiasi | * * * * * | Ogni minuto di ogni giorno |
, | Elenco | 0 9,13,17 * * * | Alle 09:00, alle 13:00 e alle 17:00 |
- | Intervallo | 0 9-17 * * * | Ogni ora dalle 09:00 alle 17:00 comprese |
/ | Passo | */15 * * * * | Ai minuti :00, :15, :30 e :45 |
Un passo si applica sempre a un intervallo. */15 nel campo dei minuti significa «partendo da 0, prendi un valore ogni 15 fino a 59». Puoi applicare un passo anche a un intervallo esplicito: 5-30/10 dà 5, 15 e 25, poi si ferma perché 35 è oltre la fine.
I passi non significano «ogni 15 minuti a partire da adesso»; selezionano valori fissi sul quadrante. */40 scatta a :00 e a :40, poi aspetta solo 20 minuti per lo :00 dell'ora successiva, perché il conteggio riparte a ogni ora. Gli elenchi possono contenere intervalli e passi, quindi 0 0-6/2,12,18-23 * * * è un campo delle ore valido.
Nomi e scorciatoie
I campi del mese e del giorno della settimana accettano nomi di tre lettere, e le maiuscole non contano, quindi JAN, jan e Jan sono la stessa cosa. La documentazione classica di crontab dice che intervalli ed elenchi di nomi non sono ammessi, anche se molte implementazioni moderne accettano MON-FRI. Se non sei sicuro di che cosa esegua il tuo job, usa i numeri: 1-5 è inequivocabile ovunque.
Diverse scorciatoie sostituiscono l'intera espressione a cinque campi:
| Scorciatoia | Equivalente | Quando viene eseguita |
|---|---|---|
@yearly oppure @annually | 0 0 1 1 * | A mezzanotte del 1° gennaio |
@monthly | 0 0 1 * * | A mezzanotte del primo giorno del mese |
@weekly | 0 0 * * 0 | A mezzanotte di domenica |
@daily oppure @midnight | 0 0 * * * | A mezzanotte, ogni giorno |
@hourly | 0 * * * * | Allo scoccare di ogni ora |
Esiste anche @reboot, ma non è una pianificazione: esegue il job una volta sola, quando parte cron stesso.
La trappola del giorno del mese e del giorno della settimana
Questa è quella che morde. Quando sia il campo del giorno del mese sia quello del giorno della settimana sono ristretti, cioè nessuno dei due è *, cron esegue il job quando corrisponde uno qualsiasi dei due, non quando corrispondono entrambi.
0 0 13 * 5
Potresti leggerla come «mezzanotte di venerdì 13». In realtà significa «mezzanotte del 13 di ogni mese, e anche mezzanotte di ogni venerdì»: più di sessanta esecuzioni all'anno invece di una o due.
Il comportamento AND che ti aspettavi vale solo quando uno dei due campi è *. Quindi 0 0 * * 5 è ogni venerdì e 0 0 13 * * è ogni giorno 13, entrambi perfettamente normali. È vincolarli entrambi che fa scattare l'OR.
Non esiste un modo standard di esprimere «venerdì 13» in cinque campi. L'espediente abituale è pianificare per ogni giorno 13 e far controllare al job il giorno della settimana prima di fare qualsiasi cosa.
Una sottigliezza collegata: alcune implementazioni decidono se un campo è ristretto controllando se inizia letteralmente con *. Con quelle, 0-6 nel campo del giorno della settimana conta come ristretto anche se copre tutti i giorni, e attiva in silenzio il comportamento OR. Usa * quando intendi «qualsiasi».
Errori che vale la pena cercare
* */2 * * *viene eseguito ogni minuto in un'ora su due: 720 esecuzioni al giorno. Volevi0 */2 * * *, che ne fa 12.- Un campo dei minuti mancante sposta tutto di una posizione a sinistra e di solito viene comunque interpretato, dandoti una pianificazione valida a un orario completamente sbagliato.
0 0 31 * *salta in silenzio i mesi che non hanno il giorno 31.- Cron usa il fuso orario del sistema o dell'utente, a meno che lo schedulatore non ti permetta di indicarne uno. Quando gli orologi si spostano per l'ora legale, un job che cade nell'ora saltata può non essere eseguito affatto e uno che cade nell'ora ripetuta può essere eseguito due volte, a seconda dell'implementazione. I job che devono girare una volta al giorno stanno più al sicuro se pianificati lontano dalle ore piccole in cui cade lo spostamento.
Nel dubbio, rileggi l'espressione come una frase, poi controlla le prossime volte in cui scatterebbe davvero. Se quelle date non sono quelle che hai descritto, è sbagliata l'espressione, non la tua lettura.