Vai al contenuto
Allin

Come scrivere un'espressione cron: cinque campi e la regola OR di cui nessuno parla

Pubblicato il 21/05/2026 · 9 min di lettura · Strumenti per sviluppatori

Daniel Okonkwo

Daniel OkonkwoSviluppatore front-end e redattore Tech presso Allin

Performance web · Formati di file

Verificato su 2 fonti

Vedi il profilo
In breve

Un'espressione cron è fatta di cinque campi separati da spazi, letti da sinistra a destra: minuto (0-59), ora (0-23), giorno del mese (1-31), mese (1-12 o nomi di tre lettere) e giorno della settimana (0-6 in POSIX con 0 come domenica, esteso a 0-7 da quasi tutte le implementazioni così che anche 7 sia domenica). Un asterisco indica tutti i valori dell'intervallo di quel campo. Un trattino forma un intervallo inclusivo: 8-11 nel campo dell'ora è 8, 9, 10 e 11. Una virgola forma un elenco, ed elenchi e intervalli si mescolano: 1-3,7-9. Una barra aggiunge un passo, ed è qui che si sbaglia la prima volta — un passo percorre un intervallo, non fissa una cadenza: */15 nel campo dei minuti è 0, 15, 30 e 45, e */40 è 0 e 40 e poi nulla finché l'ora successiva non riparte con l'intervallo. La seconda trappola, più grave, è che giorno del mese e giorno della settimana si combinano con OR e non con AND. Se entrambi sono ristretti, il lavoro parte quando uno qualsiasi dei due corrisponde. Quindi 0 0 1 * 1 non significa il primo lunedì del mese: scatta a mezzanotte del giorno 1 di ogni mese E a mezzanotte di ogni lunedì. Per fissare un lavoro a un preciso giorno della settimana, lascia il giorno del mese come asterisco, e viceversa. Tutto il resto che incontrerai — @daily, un sesto campo dei secondi, il carattere ?, L, W e # — è fuori dallo standard e dipende interamente dal cron che stai eseguendo.

Minuto, ora, giorno del mese, mese, giorno della settimana. Le trappole: un passo è un'andatura dentro un intervallo e non una cadenza, e i due campi del giorno si combinano con OR — quindi 0 0 1 * 1 scatta il giorno 1 e ogni lunedì.

Cinque campi, e un passo non è una cadenza

Leggi i campi da sinistra a destra e la notazione sta in testa. L'asterisco rappresenta l'intero intervallo del suo campo. Il trattino forma un intervallo inclusivo: 8-11 nel campo dell'ora sono quattro ore, non tre. La virgola forma un elenco, ed elenchi e intervalli si combinano liberamente nello stesso campo: 1-3,7-9 è un insieme legale di sei valori. I nomi possono sostituire i numeri nei campi mese e giorno della settimana, con tre lettere, benché il cron Vixie classico non accetti intervalli né elenchi costruiti con nomi — 1-3 viene interpretato dove JAN-MAR può fallire, buona ragione per restare ai numeri in tutto ciò che deve essere portabile.

La barra è il punto in cui il modello mentale si rompe. Un passo percorre un intervallo, non è una cadenza di ripetizione, e l'intervallo riparte all'inizio di ogni unità superiore. Nel campo dei minuti, */15 percorre 0, 15, 30, 45, poi l'ora cambia e riparte da 0 — il che risulta essere esattamente ogni quindici minuti, quindi nessuno nota la differenza. Scrivi */40 e l'illusione crolla: percorre 0 e 40, poi l'ora cambia e riparte da 0, dando intervalli di quaranta minuti e poi di venti. Lo stesso vale per un intervallo limitato: 0-23/2 nel campo dell'ora sono le ore pari, e 1-9/2 sono 1, 3, 5, 7 e 9. Se ti serve davvero una cadenza che non divide la sua unità, cron non può esprimerla in una riga: servono due voci o una guardia dentro il comando.

I due campi del giorno si combinano con OR, non con AND

Questa è la regola che quasi tutte le spiegazioni sbagliano, e non è una stranezza di una singola implementazione: è scritta nella specifica. POSIX stabilisce che, se il giorno del mese è dato come elemento o elenco e anche il giorno della settimana lo è, allora vale qualunque giorno che corrisponda al giorno del mese oppure al giorno della settimana. Il manuale crontab(5) dice lo stesso in parole più semplici e dà l'esempio canonico: 30 4 1,15 * 5 parte alle 4:30 del mattino il giorno 1 e il 15 di ogni mese, più ogni venerdì. Non il 1 o il 15 quando cadono di venerdì. Entrambi gli insiemi, uniti.

Le regole pratiche che ne derivano sono brevi. Se esattamente uno dei due campi del giorno è un asterisco, comanda l'altro e non c'è ambiguità — è il caso da scrivere quasi sempre. Se entrambi sono asterischi, ogni giorno corrisponde, ed è altrettanto univoco. Solo quando entrambi sono ristretti entra in gioco l'unione, e il risultato non è quasi mai quello voluto: 0 0 1 * 1 scatta circa cinque volte al mese invece di una. Non esiste una sintassi cron per l'intersezione, quindi se ti serve davvero il primo lunedì del mese il trucco standard è pianificare l'unione e restringerla dentro il comando — farlo partire su 0 0 1-7 * 1 e aprire lo script con un test che il giorno della settimana sia lunedì, oppure su 0 0 * * 1 con un test che il giorno del mese sia 7 o meno. I cron in stile Quartz aggiungono un operatore # per questo, ma nel cron di sistema non c'è.

Tutto ciò che va oltre i cinque campi dipende dall'implementazione

POSIX definisce cinque campi, l'asterisco, gli intervalli, gli elenchi e nient'altro. Ogni comodità che hai visto oltre a questo è un'estensione, e le estensioni variano. Il passo con la barra è un'estensione Vixie oggi quasi universale ma tuttora fuori dallo standard. Le stringhe abbreviate — @yearly e il suo sinonimo @annually, @monthly, @weekly, @daily e il suo sinonimo @midnight, @hourly, e @reboot — vengono dalla stessa stirpe, e @reboot in particolare non ha significato fisso fra i sistemi, perché che cosa conti come riavvio dipende dal servizio. Un sesto campo per i secondi è comune negli scheduler applicativi come Quartz, Spring e diverse librerie Node, e assente dal cron di sistema: un'espressione copiata dalla documentazione di un framework dentro una crontab risulterà spostata di un campo e pianificherà tutt'altro anziché fallire rumorosamente.

Il punto interrogativo appartiene alla stessa famiglia. In Quartz significa nessun valore specifico ed esiste proprio per risolvere l'ambiguità fra giorno del mese e giorno della settimana dichiarando irrilevante un campo; il cron di sistema non lo accetta affatto. Gli operatori L, W e # per ultimo giorno del mese, giorno feriale più vicino ed ennesimo giorno della settimana sono anch'essi solo di Quartz. Due fatti d'ambiente pesano più di tutta questa sintassi: il servizio esegue i lavori nel fuso orario per cui è configurato, quindi un'espressione corretta in un'installazione può scattare un'ora prima o dopo in un'altra, e attorno a un cambio dell'ora un lavoro pianificato nell'ora saltata può non partire affatto mentre uno nell'ora ripetuta può partire due volte. E cron è un innesco, non un esecutore di lavori — nessun tentativo ripetuto, nessun controllo di concorrenza, nessuna memoria che l'esecuzione precedente sia fallita. Se due invocazioni non devono sovrapporsi, prendi tu stesso un lock dentro il comando.

I cinque campi, in ordine, con l'errore che ciascuno invita
PosizioneCampoValori ammessiL'errore che invita
Minuto0-59Scrivere * qui quando si intendeva 0 — un'espressione come * 3 * * * parte sessanta volte, ogni minuto dell'ora delle 3 del mattino
Ora0-23Ragionare con l'orologio a 12 ore: non esistono il 24 né il pm, mezzanotte è 0 e le 23 sono 23
Giorno del mese1-31Usare 31 aspettandosi dodici esecuzioni all'anno: i mesi più corti semplicemente non corrispondono mai, quindi il lavoro salta in silenzio febbraio, aprile, giugno, settembre e novembre
Mese1-12, oppure JAN fino a DECDare per scontato che i nomi funzionino ovunque: il cron Vixie classico accetta i nomi di tre lettere ma rifiuta intervalli o elenchi di essi, quindi JAN-MAR può non essere interpretato dove 1-3 lo è
Giorno della settimana0-6 in POSIX con 0 come domenica; 0-7 in quasi tutte le implementazioni, dove anche 7 è domenicaRestringere questo campo e il giorno del mese insieme: i due sono in OR, quindi il lavoro scatta su entrambi gli insiemi di giorni e non sulla loro intersezione
Generatore di espressione cronCostruisci una pianificazione cron campo per campo — minuto, ora, giorno del mese, mese, giorno della settimana — e vedi l'espressione e la descrizione in chiaro aggiornarsi dal vivo. I preset coprono i casi comuni e la sintassi (*, */5, 1-5, 1,15) è spiegata.Prova lo strumento

Domande frequenti

Che cosa significa esattamente */15?
Nel campo dei minuti seleziona i valori 0, 15, 30 e 45 — un passo di quindici lungo l'intervallo da 0 a 59, partendo dal primo valore dell'intervallo. Non è un timer che scatta quindici minuti dopo l'ultima esecuzione, e non sopravvive a una divisione non esatta: */40 nel campo dei minuti seleziona solo 0 e 40, quindi gli scarti sono di quaranta minuti e poi di venti quando l'ora successiva riparte con l'intervallo. Se vuoi una cadenza misurata dall'ultima esecuzione e non dall'inizio dell'ora, cron è lo strumento sbagliato: un timer systemd con OnUnitActiveSec, o un ciclo dentro un processo di lunga durata, è quello giusto.
Come eseguo un lavoro ogni 90 minuti?
Non in una sola riga, perché 90 non divide 60 e un passo resta confinato a un unico campo. Lo schema però si ripete ogni tre ore, quindi due voci lo coprono esattamente: 0 */3 * * * dà le 00:00, 03:00, 06:00 e così via, e 30 1-23/3 * * * dà le 01:30, 04:30, 07:30 e così via. Insieme producono un'esecuzione ogni novanta minuti, e la sequenza si chiude in modo pulito a mezzanotte perché ventiquattro ore sono esattamente sedici intervalli da novanta minuti. Lo stesso trucco a due voci vale per qualsiasi cadenza che divida un numero intero di ore; ciò che non lo fa, come ogni 50 minuti, non è esprimibile in cron affatto.
Perché il mio lavoro notturno è partito due volte, o per niente?
La causa abituale è un cambio dell'ora. Cron confronta l'orologio da parete: quando l'orologio avanza, un'ora che non è mai esistita non viene mai soddisfatta e un lavoro pianificato lì dentro semplicemente non parte; quando l'orologio arretra, un'ora si verifica due volte e un lavoro pianificato lì dentro può scattare due volte. Le implementazioni differiscono nello sforzo di compensare, ed è per questo che la stessa crontab si comporta diversamente su due distribuzioni. Le correzioni affidabili sono pianificare i lavori delicati fuori dalla finestra di transizione, far girare il servizio in un fuso senza cambi d'ora, oppure rendere il comando stesso sicuro da eseguire due volte. Quest'ultima conviene comunque: l'idempotenza ti protegge anche da tentativi ripetuti, esecuzioni sovrapposte e rilanci manuali.

Articoli che potrebbero interessarti

Tutte le guide
SpiegazioneCome funzionano i permessi dei file Unix: leggere 755 senza tirare a indovinareLettura 4, scrittura 2, esecuzione 1, e ciascuna delle tre cifre descrive un soggetto diverso. Ciò che quasi tutte le spiegazioni sbagliano è cosa fa il bit di esecuzione su una directory: concede l'attraversamento, non il diritto di eseguire qualcosa.GuidaCodici di stato HTTP spiegati: quelli che davvero si confondono301 contro 308, 302 contro 307, 401 contro 403, 404 contro 410 — più che cosa promette davvero Retry-After su un 429 o un 503. Le coppie in cui scegliere il codice sbagliato cambia il comportamento, non solo le parole.SpiegazioneCos'è un'espressione cron?Un'espressione cron pianifica l'esecuzione automatica di un'attività a orari fissati. Ecco a cosa serve, i suoi cinque campi, come leggerla, e i tranelli comuni.TutorialCome scrivere un robots.txt: direttive, corrispondenza e ciò che non può nascondereQuattro direttive, due caratteri jolly, un file nella radice dell'host. È un'istruzione di scansione e nulla più: non toglie una pagina dai risultati, non limita l'accesso e pubblica ogni percorso che vi elenchi.SpiegazioneChe cosa consente davvero una percentuale di disponibilitàTre nove suonano come una promessa, finché non li dividi in minuti. Che cosa compra il 99,9 % all'anno, al mese, alla settimana e al giorno; perché la finestra di misura conta molto più del nove in più; e i due mesi diversi che questo strumento usa per lo stesso identificatore.SpiegazioneL'ora dorata e l'ora blu sono angoli, non oreL'ora dorata va da +6° a −4° di altezza del sole e l'ora blu da −4° a −6°, ed è per questo che dura quaranta minuti all'equatore, oltre un'ora alle medie latitudini, e sopra i 72,6° a giugno non si verifica affatto. Le soglie di questa calcolatrice, verificate sulla sua stessa uscita.

Strumenti correlati

Fonti

Hai notato un errore in questo articolo?