
Indice dei contenuti
Una delle caratteristiche più utili di un server Linux è la possibilità di automatizzare attività che altrimenti dovresti eseguire manualmente.
Backup notturni, pulizia dei file temporanei, aggiornamento di dati, generazione di report, invio di notifiche e manutenzione delle applicazioni sono soltanto alcuni esempi.
Lo strumento tradizionale per pianificare queste operazioni è cron.
La sua configurazione sembra semplice: scrivi un comando, scegli quando eseguirlo e il sistema si occupa del resto.
Ma chi amministra server da qualche tempo sa che i problemi più fastidiosi non derivano necessariamente dalla sintassi. Spesso uno script funziona perfettamente quando viene avviato manualmente e fallisce silenziosamente quando viene eseguito da cron. 😅
Vediamo quindi come utilizzare cron in modo affidabile, con esempi pratici e accorgimenti utili per applicazioni PHP, VPS e servizi self-hosted.
Che cos’è cron?
Cron è un sistema di pianificazione che permette di eseguire comandi e script a intervalli o orari prestabiliti.
Le attività pianificate vengono generalmente chiamate cron job.
Per esempio, puoi configurare un comando che venga eseguito ogni notte alle 2:30 oppure ogni quindici minuti.
È particolarmente utile per attività ripetitive che non richiedono un’interazione diretta con l’utente.
Su molte distribuzioni Linux, cron è disponibile attraverso un servizio di sistema, anche se implementazione e configurazione possono variare.
1. Come funziona la sintassi di crontab
Una riga tipica di crontab contiene cinque campi temporali seguiti dal comando da eseguire.
* * * * * comando
│ │ │ │ │
│ │ │ │ └── giorno della settimana
│ │ │ └──── mese
│ │ └────── giorno del mese
│ └──────── ora
└────────── minutoI campi permettono di specificare valori, intervalli, elenchi e passi.
Per esempio:
0 3 * * * /percorso/script.shQuesto job viene pianificato ogni giorno alle 3:00, secondo il fuso orario applicabile al servizio cron.
Un altro esempio:
*/15 * * * * /percorso/script.shIn questo caso, il comando viene eseguito ogni quindici minuti.
📌 Attenzione: i campi relativi al giorno del mese e al giorno della settimana possono avere una semantica particolare quando entrambi sono limitati. Per pianificazioni complesse è importante verificare il comportamento dell’implementazione utilizzata.
2. Come visualizzare e modificare i cron job
Per visualizzare i cron job dell’utente corrente:
crontab -lPer modificarli:
crontab -eIl sistema apre un editor di testo nel quale puoi aggiungere o modificare le attività pianificate.
Se vuoi consultare il crontab di un altro utente, e disponi dei permessi necessari, puoi utilizzare:
sudo crontab -u nomeutente -lRicorda che i cron job dell’utente corrente sono distinti da quelli dell’utente root e dalle pianificazioni di sistema.
Su Linux possono inoltre esistere attività definite in directory come /etc/cron.d e attraverso altri meccanismi di pianificazione.
3. Perché uno script funziona da terminale ma non da cron?
Questo è uno dei problemi più frequenti.
Quando esegui uno script manualmente, il comando eredita una serie di variabili e impostazioni dalla tua sessione.
Quando viene avviato da cron, l’ambiente può essere molto più limitato.
Potrebbero cambiare:
- variabile PATH;
- directory di lavoro;
- utente di esecuzione;
- variabili di ambiente;
- permessi disponibili;
- versione dell’interprete richiamato;
- accesso a file e directory.
Per questo è preferibile utilizzare percorsi assoluti.
Invece di:
php script.phppuoi utilizzare un comando simile:
/usr/bin/php /home/app/scripts/script.phpIl percorso di PHP è un esempio: devi verificarlo sul sistema reale.
Puoi individuarlo con:
command -v php💡 Su server che ospitano più versioni PHP, il binario utilizzato da cron potrebbe non coincidere con quello configurato per il sito web.
4. Gestire correttamente la directory di lavoro
Molti script utilizzano percorsi relativi per leggere file di configurazione o salvare risultati.
Se lo script viene eseguito da una directory diversa da quella prevista, potrebbe non trovare i file necessari.
Una soluzione consiste nel utilizzare percorsi assoluti all’interno dell’applicazione.
In PHP, per esempio:
$configPath = __DIR__ . '/config.php';La costante __DIR__ fa riferimento alla directory del file PHP corrente, evitando di dipendere dalla directory di lavoro del processo.
In alternativa, puoi modificare esplicitamente la directory prima di eseguire un comando.
cd /home/app && /usr/bin/php scripts/task.phpL’operatore && permette di eseguire il secondo comando soltanto se il primo termina correttamente.
5. Non eseguire tutto come root
Una scorciatoia piuttosto comune consiste nel configurare ogni attività pianificata nel crontab di root.
In questo modo molti problemi di permessi sembrano scomparire, ma si introduce un rischio significativo.
Se uno script contiene un errore o viene compromesso, potrebbe eseguire operazioni con privilegi molto elevati.
È generalmente preferibile utilizzare utenti dedicati con i soli permessi necessari.
Per esempio, uno script che aggiorna dati di un’applicazione web potrebbe non avere alcun bisogno di modificare configurazioni di sistema o accedere ai file di altri utenti.
🔐 Il principio del privilegio minimo è importante anche per le attività automatiche.
6. Evitare che due esecuzioni si sovrappongano
Immagina di pianificare uno script ogni cinque minuti.
Normalmente lo script termina in trenta secondi, ma un giorno il servizio esterno da cui recupera i dati diventa molto lento.
La prima esecuzione è ancora attiva quando cron ne avvia una seconda.
Se entrambe modificano gli stessi dati, potresti ottenere duplicazioni, conflitti o comportamenti difficili da diagnosticare.
Su Linux, uno strumento utile è flock, che permette di utilizzare lock a livello di filesystem.
Per esempio:
*/5 * * * * /usr/bin/flock -n /tmp/task.lock /usr/bin/php /home/app/task.phpCon -n, se il lock è già occupato, il comando non attende che venga liberato.
Questo esempio presuppone che il sistema disponga di flock e che il percorso del lock sia appropriato.
Per applicazioni particolarmente importanti, può essere preferibile utilizzare una directory dedicata e protetta, con permessi coerenti con l’utente che esegue lo script.
Il lock impedisce alcune sovrapposizioni, ma non sostituisce la progettazione di operazioni idempotenti e la gestione delle transazioni.
7. Registrare gli errori e l’output
Uno script che fallisce senza lasciare tracce è difficile da diagnosticare.
Puoi reindirizzare l’output standard e quello degli errori verso un file di log:
0 3 * * * /usr/bin/php /home/app/task.php >> /home/app/logs/task.log 2>&1In questo esempio:
>>aggiunge l’output al file senza sovrascriverlo;2>&1reindirizza anche lo standard error verso la stessa destinazione.
La directory dei log deve esistere ed essere scrivibile dall’utente che esegue il job.
È importante anche prevedere una politica di rotazione: un file di log che cresce senza limiti può occupare molto spazio sul disco.
📊 Per le attività critiche, oltre ai log conviene registrare l’esito e la durata dell’esecuzione, così da poter individuare errori e rallentamenti.
8. Cron e notifiche di errore
Limitarsi a registrare gli errori non è sempre sufficiente.
Se un backup notturno smette di funzionare, potresti accorgertene soltanto settimane dopo.
Una soluzione consiste nel configurare notifiche quando un’attività fallisce.
Puoi utilizzare:
- email amministrative;
- servizi di monitoraggio;
- webhook verso sistemi di notifica;
- controlli periodici sull’ultima esecuzione riuscita.
Un aspetto importante è distinguere tra il fatto che il processo sia stato avviato e il fatto che abbia completato correttamente il proprio lavoro.
Uno script potrebbe terminare con codice zero anche se non ha elaborato alcun dato, oppure potrebbe fallire senza propagare correttamente l’errore al sistema di monitoraggio.
Per questo conviene definire condizioni di successo verificabili.
9. Cron non garantisce automaticamente l’esecuzione dei job persi
Supponiamo che un server venga spento durante la notte per manutenzione.
Se un cron job era previsto proprio durante quel periodo, l’esecuzione potrebbe semplicemente non avvenire.
Cron tradizionale non offre necessariamente un meccanismo automatico per recuperare tutte le esecuzioni mancate.
Per attività che devono essere eseguite anche dopo periodi di spegnimento, puoi valutare strumenti differenti, come timer systemd con configurazioni appropriate.
Su alcuni sistemi esiste anche anacron, pensato per gestire determinate attività periodiche su macchine che non rimangono sempre accese.
Questo aspetto è particolarmente importante per piccoli server domestici e Raspberry Pi che potrebbero essere spenti o riavviati frequentemente.
10. Cron oppure systemd timer?
Cron è semplice, diffuso e perfettamente adeguato a moltissime attività.
I timer di systemd rappresentano però un’alternativa interessante sui sistemi che utilizzano questo gestore dei servizi.
Possono offrire funzionalità come:
- integrazione con i servizi systemd;
- logging attraverso journald;
- dipendenze e condizioni di esecuzione;
- gestione di timer monotoni e basati sul calendario;
- recupero di alcune esecuzioni mancate attraverso l’opzione Persistent, quando applicabile.
La documentazione di systemd.timer descrive le opzioni disponibili.
Non è necessario sostituire tutti i cron job con timer systemd.
Per uno script semplice che deve essere eseguito ogni notte, cron può essere più che sufficiente. Per attività che richiedono integrazione avanzata con i servizi e controllo del ciclo di vita, systemd può risultare più adatto.
11. Cron job e applicazioni PHP: alcuni accorgimenti utili
Quando utilizzi cron per elaborare dati in un’applicazione PHP, considera alcuni aspetti specifici.
Evita di esporre script amministrativi sul web
Uno script progettato per essere eseguito da CLI non dovrebbe essere necessariamente raggiungibile attraverso un URL pubblico.
È preferibile collocarlo fuori dalla directory pubblica o impedire l’accesso HTTP attraverso una configurazione adeguata.
Gestisci i timeout
Le attività eseguite da CLI possono avere limiti differenti rispetto alle richieste web.
Questo non significa che debbano poter funzionare indefinitamente: prevedi timeout per chiamate esterne e procedure per interrompere elaborazioni bloccate.
Usa transazioni quando necessario
Se uno script modifica più record correlati, valuta l’utilizzo di transazioni database per evitare stati parzialmente aggiornati.
Rendi le attività ripetibili
Se uno script viene avviato due volte o riprende dopo un errore, dovrebbe evitare duplicazioni e comportamenti inattesi.
🔄 Questa caratteristica è particolarmente importante per importazioni, sincronizzazioni e aggiornamenti periodici.
12. Una checklist prima di mettere un cron job in produzione
- ☐ Ho verificato il comando manualmente con l’utente corretto?
- ☐ Utilizzo percorsi assoluti?
- ☐ Lo script funziona senza dipendere da una sessione interattiva?
- ☐ I permessi sono limitati al necessario?
- ☐ Ho previsto la gestione delle esecuzioni sovrapposte?
- ☐ Lo script gestisce correttamente gli errori?
- ☐ L’output viene registrato?
- ☐ I log vengono ruotati?
- ☐ Ricevo notifiche per i fallimenti importanti?
- ☐ So che cosa accade se il server è spento durante l’orario previsto?
- ☐ Le operazioni sono ripetibili senza effetti indesiderati?
Conclusione: automatizzare è facile, automatizzare bene richiede metodo ⚙️
Cron è uno degli strumenti più semplici e utili disponibili su Linux.
Con poche righe puoi automatizzare operazioni che altrimenti richiederebbero interventi manuali quotidiani.
Ma una buona automazione non consiste soltanto nel pianificare un comando.
Bisogna considerare permessi, ambiente di esecuzione, sovrapposizioni, errori, logging e monitoraggio.
Uno script che funziona quando lo avvii manualmente è un buon inizio. Uno script che continua a funzionare autonomamente, segnala i problemi e non produce effetti indesiderati è un’automazione davvero affidabile. 🚀
