155 30/03/2026 07/04/2026 10 min

Introduzione

Quando un sito cresce, la manutenzione manuale smette di essere sostenibile. Backup, pulizia cache, controllo errori, rotazione dei log e task periodici devono diventare affidabili, tracciabili e facili da verificare. Il punto non è solo “farli partire”, ma farli girare bene, con orari corretti, permessi giusti, log leggibili e una strategia di rollback se qualcosa va storto.

In questa guida vediamo come configurare cron job, creare script di manutenzione robusti e gestire la rotazione dei log su un server Linux tipico per hosting, VPS o web server con applicazioni PHP, WordPress, CMS o script personalizzati.

1. Prima di tutto: cosa automatizzare davvero

Non tutto merita un cron. La regola pratica è semplice: automatizza solo ciò che è ripetitivo, misurabile e reversibile. Esempi utili:

  • backup database e file;
  • pulizia file temporanei e cache;
  • sync o export periodici;
  • controllo spazio disco;
  • invio report di salute del sistema;
  • rotazione di log applicativi personalizzati;
  • task di WordPress o CMS che non conviene lasciare al traffico web.

Evita invece cron che modificano dati critici senza controllo, o task che possono sovrapporsi tra loro. Un cron mal progettato può generare più danni di un problema non automatizzato.

2. Dove si configura il cron

Su Linux, i cron possono essere configurati in più modi:

  • crontab dell’utente, con accesso semplice e limitato;
  • /etc/crontab, gestito a livello di sistema;
  • /etc/cron.d/, utile per job separati e ordinati;
  • pannello di controllo, come cPanel, Plesk o FastPanel, se vuoi evitare la CLI.

Per ambienti hosting, spesso è più comodo creare i job dal pannello. Per esempio, in cPanel trovi la sezione Cron Jobs; in Plesk puoi usare Scheduled Tasks; in FastPanel c’è la parte dedicata alle attività pianificate. La CLI resta utile quando vuoi versione, ordine e automazione via file.

3. Cron job: sintassi base e approccio corretto

La sintassi di cron è composta da cinque campi temporali e dal comando da eseguire:

* * * * * comando

Ordine dei campi:

  • minuto;
  • ora;
  • giorno del mese;
  • mese;
  • giorno della settimana.

Alcuni esempi pratici:

  • 0 3 * * * /usr/local/bin/backup.sh esegue il backup ogni notte alle 03:00;
  • */15 * * * * /usr/local/bin/cleanup-cache.sh esegue ogni 15 minuti;
  • 30 2 * * 1 /usr/local/bin/report-weekly.sh esegue ogni lunedì alle 02:30.

Il dettaglio più importante è il percorso assoluto del comando. Cron non usa il tuo ambiente interattivo completo, quindi non dare per scontato che php, bash o altri binari siano risolti nel PATH.

4. Il primo errore da evitare: script senza ambiente controllato

Molti cron falliscono non per il codice, ma perché lo script dipende da variabili d’ambiente, directory corrente o permessi non coerenti. La soluzione è scrivere script espliciti, con percorsi assoluti, log, controllo degli errori e uscita pulita.

Un buon script di manutenzione deve fare almeno questo:

  • verificare i prerequisiti;
  • scrivere log con timestamp;
  • uscire con codice di ritorno corretto;
  • evitare esecuzioni sovrapposte;
  • gestire i fallimenti in modo leggibile.

5. Esempio di script di manutenzione sicuro

Supponiamo di voler creare uno script che svuota una cache applicativa e registra il risultato. Salvalo ad esempio in /usr/local/bin/maintenance-cache.sh.

#!/usr/bin/env bash
set -u
set -o pipefail

PATH=/usr/sbin:/usr/bin:/sbin:/bin
LOG_FILE="/var/log/maintenance-cache.log"
CACHE_DIR="/var/www/example.com/storage/cache"
LOCK_FILE="/var/lock/maintenance-cache.lock"

exec >>"$LOG_FILE" 2>&1

echo "[$(date '+%F %T')] Avvio manutenzione cache"

if [ ! -d "$CACHE_DIR" ]; then
  echo "[$(date '+%F %T')] ERRORE: directory cache non trovata: $CACHE_DIR"
  exit 1
fi

if [ -e "$LOCK_FILE" ]; then
  echo "[$(date '+%F %T')] ERRORE: lock presente, possibile esecuzione concorrente"
  exit 1
fi

touch "$LOCK_FILE"
trap 'rm -f "$LOCK_FILE"' EXIT

find "$CACHE_DIR" -type f -mtime +2 -delete

echo "[$(date '+%F %T')] Fine manutenzione cache"
exit 0

Questo script fa alcune cose corrette:

  • usa set -u e pipefail per ridurre errori silenziosi;
  • forza un PATH noto;
  • scrive su un log dedicato;
  • usa un lock file per evitare doppie esecuzioni;
  • controlla che la directory esista prima di agire.

Se vuoi una soluzione ancora più robusta, puoi usare flock al posto del lock manuale. È spesso la scelta migliore per evitare collisioni.

6. Variante con flock: migliore per evitare sovrapposizioni

Un esempio più pulito:

#!/usr/bin/env bash
set -u
set -o pipefail

PATH=/usr/sbin:/usr/bin:/sbin:/bin
LOG_FILE="/var/log/maintenance-cache.log"
CACHE_DIR="/var/www/example.com/storage/cache"
LOCK_FILE="/var/lock/maintenance-cache.lock"

exec >>"$LOG_FILE" 2>&1

echo "[$(date '+%F %T')] Avvio manutenzione cache"

flock -n 9 || { echo "[$(date '+%F %T')] ERRORE: script già in esecuzione"; exit 1; }

if [ ! -d "$CACHE_DIR" ]; then
  echo "[$(date '+%F %T')] ERRORE: directory cache non trovata: $CACHE_DIR"
  exit 1
fi

find "$CACHE_DIR" -type f -mtime +2 -delete

echo "[$(date '+%F %T')] Fine manutenzione cache"
exit 0

Per far funzionare flock, lo script va lanciato con un file descriptor dedicato. Un esempio completo nel cron è questo:

0 4 * * * /usr/bin/flock -n /var/lock/maintenance-cache.lock /usr/local/bin/maintenance-cache.sh

Se il job è già attivo, il secondo avvio non si sovrappone. È un comportamento sano e prevedibile.

7. Come aggiungere il cron in modo corretto

Se usi la riga di comando, il metodo più comune è modificare il crontab dell’utente dedicato.

crontab -e

Inserisci una riga come questa:

0 4 * * * /usr/local/bin/maintenance-cache.sh

Se invece vuoi creare un file dedicato in /etc/cron.d/, il formato include anche l’utente:

0 4 * * * www-data /usr/local/bin/maintenance-cache.sh

Questo approccio è utile in ambienti server con più servizi e più script, perché separa bene i task e li rende più facili da mantenere.

Verifica immediata del cron

Per controllare che il job sia stato registrato:

crontab -l

Esito atteso: la riga del job deve comparire esattamente come configurata. Se non compare, il cron non è stato salvato nel profilo giusto.

8. Testare uno script prima di affidarlo al cron

Non lanciare mai un cron “alla cieca”. Prima esegui lo script manualmente come utente corretto e osserva output, errori e permessi.

/usr/local/bin/maintenance-cache.sh

Controlla poi il log:

tail -n 50 /var/log/maintenance-cache.log

Esito atteso: una sequenza pulita di avvio e fine, senza errori di permesso, path mancanti o directory non trovate.

Se lo script tocca file web, verifica anche il proprietario e i permessi della directory coinvolta. Un cron che gira con l’utente sbagliato può funzionare “a metà” e creare problemi difficili da vedere subito.

9. Log: perché non basta scrivere tutto nello stesso file

Molti ambienti finiscono con un unico file di log enorme, ingestibile e inutile. La rotazione serve a mantenere i log consultabili, evitare saturazione disco e separare i problemi per periodo. Il tool standard in Linux è logrotate.

Con logrotate puoi:

  • ruotare i file per dimensione o per tempo;
  • comprimere i log vecchi;
  • mantenere un numero fisso di copie;
  • eseguire script dopo la rotazione;
  • impostare permessi e ownership coerenti.

10. Esempio di configurazione logrotate

Supponiamo di voler ruotare /var/log/maintenance-cache.log. Crea un file dedicato in /etc/logrotate.d/maintenance-cache.

/var/log/maintenance-cache.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 root adm
}

Spiegazione pratica:

  • daily: rotazione giornaliera;
  • rotate 14: conserva 14 copie;
  • compress: comprime le copie vecchie;
  • delaycompress: non comprime subito l’ultima ruotata;
  • missingok: non fallisce se il file non esiste;
  • notifempty: non ruota file vuoti;
  • create: ricrea il file con permessi specifici.

Se il tuo processo scrive con un utente diverso da root, adatta ownership e permessi. L’obiettivo è evitare che il job successivo perda la capacità di scrivere nel log dopo la rotazione.

Backup prima della modifica

Prima di cambiare una regola logrotate già attiva, fai sempre una copia del file:

cp /etc/logrotate.d/maintenance-cache /etc/logrotate.d/maintenance-cache.bak

È un backup semplice, ma spesso basta per tornare indietro in pochi secondi.

Verifica della configurazione logrotate

Controlla la sintassi con una simulazione:

logrotate -d /etc/logrotate.conf

Esito atteso: nessun errore di sintassi o di path. Se vuoi forzare una prova su un file specifico, usa la modalità verbosa e controllata:

logrotate -v -f /etc/logrotate.d/maintenance-cache

Attenzione: il comando con -f forza la rotazione, quindi va usato solo se sai cosa stai facendo e preferibilmente su log non critici.

11. Rotazione dei log applicativi PHP e WordPress

In ambienti WordPress o PHP personalizzati, spesso hai log applicativi generati dal codice, ad esempio error log o file di debug. Qui il rischio è doppio: se il log cresce troppo, occupa spazio; se la rotazione è fatta male, il sito perde la traccia degli errori.

Consigli pratici:

  • separa i log applicativi da quelli di sistema;
  • usa un file per sito o per servizio;
  • non scrivere log nel web root;
  • non lasciare log accessibili via browser;
  • imposta rotazione e retention coerenti con il volume reale.

Per WordPress, il debug log standard può essere configurato nel file wp-config.php, ma è bene non lasciarlo attivo in modo permanente. In produzione, tienilo solo quando serve un’indagine e poi disattivalo.

12. Esempio di cron per backup e pulizia

Un caso molto comune è il backup giornaliero con rimozione dei backup troppo vecchi. Ecco un esempio semplice:

#!/usr/bin/env bash
set -u
set -o pipefail

PATH=/usr/sbin:/usr/bin:/sbin:/bin
BACKUP_DIR="/backup/site"
DATE="$(date +%F)"
LOG_FILE="/var/log/backup-site.log"

exec >>"$LOG_FILE" 2>&1

echo "[$(date '+%F %T')] Avvio backup"
mkdir -p "$BACKUP_DIR"

mysqldump --single-transaction --routines --events dbname > "$BACKUP_DIR/db-$DATE.sql"
tar -czf "$BACKUP_DIR/files-$DATE.tar.gz" /var/www/example.com
find "$BACKUP_DIR" -type f -mtime +7 -delete

echo "[$(date '+%F %T')] Fine backup"

Questo esempio mostra il principio corretto: backup, compressione, retention e log. In un ambiente reale dovresti aggiungere controllo errori per ciascun passo, magari con notifiche email se il dump fallisce.

13. Notifiche e monitoraggio

Un cron senza monitoraggio è solo una scommessa. Al minimo, configura una notifica quando il job fallisce. Puoi farlo in diversi modi:

  • reindirizzare output e errori a un log dedicato;
  • usare MAILTO nel crontab;
  • integrare notifiche via email o webhook;
  • monitorare la presenza del file di log e la sua crescita;
  • controllare lo spazio su disco e gli exit code.

Esempio di intestazione nel crontab:

MAILTO=admin@example.com

Se il comando produce output, cron lo invia all’indirizzo indicato. Se il job è silenzioso ma vuoi comunque traccia, scrivi sempre tu su un log applicativo.

14. Problemi tipici e come leggerli

Le cause più comuni dei cron guasti sono sempre le stesse:

  • percorso errato del comando;
  • permessi insufficienti;
  • variabili d’ambiente mancanti;
  • script senza permessi di esecuzione;
  • lock file bloccato;
  • log non scrivibile;
  • rotazione log che cambia ownership in modo inatteso.

Verifiche rapide utili:

ls -l /usr/local/bin/maintenance-cache.sh
bash -n /usr/local/bin/maintenance-cache.sh
journalctl -u cron -n 50

Esito atteso: script eseguibile, sintassi shell corretta, nessun errore cron recente. Su alcuni sistemi il servizio può chiamarsi crond invece di cron.

15. Strategia pratica consigliata

Se devi mettere ordine in un server già attivo, procedi così:

  1. identifica i task davvero necessari;
  2. scrivi uno script per ogni attività omogenea;
  3. usa percorsi assoluti e log dedicati;
  4. aggiungi lock per evitare doppie esecuzioni;
  5. configura la rotazione dei log;
  6. testa ogni script manualmente;
  7. attiva il cron solo dopo la verifica;
  8. controlla i log nelle prime 24 ore.

Questo approccio riduce errori e rende ogni intervento più facile da capire. Quando un task fallisce, sai dove guardare e non devi inseguire decine di file sparsi.

16. Esempio di checklist finale

  • Lo script gira a mano senza errori e con exit code 0.
  • Il cron è registrato nell’utente o nel file giusto.
  • I log vengono scritti in una posizione non pubblica.
  • logrotate ruota i file senza rompere i permessi.
  • Esiste un backup del file di configurazione prima di ogni modifica.

Conclusione operativa

La manutenzione automatica funziona davvero quando è semplice da leggere, facile da testare e sicura da fermare. Cron, script e logrotate non sono tre mondi separati: lavorano insieme. Il cron avvia, lo script esegue con disciplina, logrotate mantiene tutto sostenibile nel tempo.

Se costruisci ogni pezzo con percorsi assoluti, log chiari, lock contro le sovrapposizioni e una rotazione ben definita, ottieni un sistema molto più affidabile di qualsiasi automazione improvvisata.