158 29/03/2026 07/04/2026 7 min

Quando cron smette di lavorare, il problema quasi mai è solo cron

Quando un job pianificato non parte, la tentazione è quella di riavviare il servizio e sperare. Funziona raramente. In pratica, i casi più comuni sono cinque: il demone non è attivo, la sintassi della schedulazione è sbagliata, l’utente non ha i permessi giusti, l’ambiente è troppo povero rispetto a quello interattivo, oppure il comando fallisce ma non lascia traccia visibile. La cosa giusta da fare è separare il problema in tre livelli: cron esiste e gira, il job viene letto, il comando eseguito da cron funziona davvero.

Questa guida è pensata per un controllo rapido ma serio, adatto a server Linux in produzione, sia su Ubuntu/Debian sia su Alma/Rocky/CentOS. L’obiettivo non è spiegare cron in astratto, ma arrivare in pochi passaggi a capire dove si rompe la catena.

Diagnosi probabile

Le cause più frequenti sono queste:

  • Servizio cron fermo o disabilitato: il demone non è in esecuzione oppure non parte al boot.
  • File crontab o sintassi errati: un minuto, un asterisco o un carattere fuori posto basta per bloccare il job.
  • Ambiente differente da shell: in cron mancano PATH, variabili, alias, profilo utente e directory di lavoro attesa.
  • Permessi o ownership sbagliati: il job appartiene all’utente sbagliato, oppure `/etc/cron.*` o il crontab hanno permessi non accettati.
  • Output ignorato o errore silenzioso: il comando fallisce, ma nessuno legge mail locali, log o redirect di stderr.

Se il problema è comparso dopo una modifica, la causa più probabile è quasi sempre una tra: cambio di percorso del binario, script reso non eseguibile, variabile d’ambiente rimossa, oppure aggiornamento del sistema che ha alterato log o policy di esecuzione.

Verifiche immediate

  1. Controlla che cron sia attivo. Su sistemi con systemd, esegui:
    systemctl status cron

    su Debian/Ubuntu, oppure:

    systemctl status crond

    su Alma/Rocky/CentOS. L’esito atteso è active (running). Se risulta inactive o failed, il job non può partire.

  2. Verifica se il job viene letto. Controlla il crontab dell’utente interessato:
    crontab -l

    oppure, se il job è in root, usa sudo crontab -l. L’esito atteso è la presenza della riga corretta, senza duplicati e senza caratteri strani. Se il job è in /etc/crontab o in /etc/cron.d/, verifica anche il formato con colonna utente inclusa.

  3. Controlla i log di cron. Su Debian/Ubuntu cerca in:
    grep CRON /var/log/syslog | tail -n 20

    su Alma/Rocky/CentOS usa spesso:

    grep CRON /var/log/cron | tail -n 20

    L’esito atteso è vedere almeno la traccia del job o del tentativo di esecuzione. Se non appare nulla, il job potrebbe non essere letto oppure il servizio non sta loggando dove pensi.

  4. Prova il comando fuori da cron. Prendi il comando esatto del job e lancialo da shell con lo stesso utente. L’esito atteso è l’assenza di errori. Se fallisce in shell, cron non è il problema: cron sta solo rendendo visibile un errore già presente.

Soluzione consigliata passo-passo

  1. Stabilizza il servizio. Se cron non è attivo, riavvialo in modo controllato:
    sudo systemctl restart cron

    oppure

    sudo systemctl restart crond

    Subito dopo verifica lo stato con lo stesso comando di prima. L’esito atteso è active (running). Se il servizio non riparte, non forzare ulteriori modifiche prima di leggere il log del servizio con journalctl -u cron -xe oppure journalctl -u crond -xe.

  2. Rendi esplicito l’ambiente. Molti job falliscono perché in cron non esistono le stesse variabili della tua sessione. Nel crontab, usa percorsi assoluti per comandi, file e directory. Esempio di impostazione prudente:
    SHELL=/bin/bash
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

    Se lo script dipende da una directory precisa, entra sempre nella directory prima del comando. L’esito atteso è che il job non dipenda più dal contesto della shell interattiva.

  3. Isola il comando in uno script. Se il crontab contiene una riga lunga o complessa, spostala in uno script dedicato, ad esempio /usr/local/bin/job-backup.sh. Prima di modificarlo fai un backup:
    cp /usr/local/bin/job-backup.sh /usr/local/bin/job-backup.sh.bak

    Assicurati che lo script abbia permessi eseguibili:

    chmod 750 /usr/local/bin/job-backup.sh

    e proprietà coerente con l’utente che lo esegue. L’esito atteso è che il file sia leggibile ed eseguibile solo da chi deve usarlo.

  4. Aggiungi logging esplicito. Cron non deve essere usato alla cieca. Redirigi stdout e stderr in un file di log, ad esempio:
    /usr/local/bin/job-backup.sh >> /var/log/job-backup.log 2>&1

    In questo modo, se il job fallisce, hai una traccia concreta. L’esito atteso è la presenza di righe utili nel log dopo l’esecuzione pianificata.

  5. Verifica eventuali vincoli di sicurezza. Se il server usa SELinux, AppArmor o restrizioni del pannello hosting, il job può partire ma essere bloccato nell’accesso a file, rete o directory temporanee. Controlla prima i log di sistema e i contesti dei file, senza disattivare la protezione in modo permanente. L’esito atteso è la conferma che il blocco, se presente, sia di policy e non di sintassi.
  6. Controlla i cron di sistema. Oltre al crontab utente, verifica /etc/crontab e i file in /etc/cron.d/. Un job duplicato, una riga malformata o un file con line ending Windows possono creare confusione. Prima di toccare questi file fai un backup. L’esito atteso è una schedulazione pulita, senza duplicazioni o righe non parsabili.

Casi tipici e correzioni rapide

Se il job funziona da terminale ma non da cron, il problema è quasi sempre l’ambiente. In quel caso, sostituisci variabili implicite con percorsi assoluti, evita alias e usa shell script robusti. Se il job non parte a un minuto preciso, controlla il formato della pianificazione: cron non accetta errori di spaziatura, e una riga con campi spostati di una colonna può sembrare corretta ma non esserlo.

Se il job usa PHP, Python, Perl o Node, fai attenzione al binario richiamato. Su server con più versioni installate, php da shell può non coincidere con /usr/bin/php o con il PHP usato dal sito. In cron è meglio indicare il percorso completo del binario. Lo stesso vale per wget, curl, mysqldump e qualsiasi tool esterno.

Se il job scrive su email locale ma non ricevi nulla, non significa che sia riuscito. Potrebbe non esserci un MTA configurato, oppure il messaggio può essere finito nella coda locale. Meglio impostare un log su file e verificare direttamente l’output.

Controlli finali / rollback

  1. Conferma l’esecuzione reale. Dopo il minuto pianificato, verifica il log del job e i log di cron. L’esito atteso è una riga con data e ora coerenti con la schedulazione, segno che il comando è partito davvero.
  2. Controlla l’effetto del job. Non basta vedere che “cron ha eseguito”: verifica il file generato, il backup creato, la mail inviata o l’azione prevista. L’esito atteso è il risultato operativo corretto, non solo l’assenza di errori.
  3. Rollback sicuro. Se il job modificato crea problemi, ripristina il backup dello script o del crontab salvato prima della modifica. Ad esempio, per un file script:
    cp /usr/local/bin/job-backup.sh.bak /usr/local/bin/job-backup.sh

    e poi riesegui il controllo. Se hai cambiato il crontab, reinstalla la versione precedente con attenzione, senza cancellare altre righe utili.

  4. Condizione di chiusura. Considera risolto solo quando il servizio cron è attivo, il job è visibile nel crontab corretto, il comando funziona in shell e il log mostra l’esecuzione con esito coerente.
Principio pratico: quando cron non esegue, non cercare prima il servizio “magico”. Cerca invece la differenza tra shell interattiva e ambiente pianificato. Lì si nasconde la maggior parte dei guasti.

Assunzione operativa: i controlli sopra sono pensati per un server Linux con systemd e cron standard; se il tuo ambiente usa un pannello hosting o una distribuzione molto personalizzata, il punto di log può cambiare.