☁ Cloud e DevOps

Cron e systemd timer: automatizzare i lavori pianificati

Come pianificare backup, pulizie e report su Linux con cron e timer di systemd: sintassi, differenze, registri, lavori sovrapposti e notifiche di errore.

Ogni server ha compiti da svolgere a intervalli regolari: il backup notturno, la pulizia dei file temporanei, il rinnovo di un certificato, l'invio di un report settimanale. Su Linux gli strumenti per farlo sono due: il classico cron, presente da decenni, e i timer di systemd, più recenti e più ricchi. Entrambi funzionano bene, a patto di conoscere le loro trappole.

Cron: la sintassi

Cron legge le crontab, file in cui ogni riga descrive un lavoro con cinque campi temporali seguiti dal comando:

# minuto  ora  giorno-mese  mese  giorno-settimana  comando
30 2 * * *   /usr/local/bin/backup.sh
0 */6 * * *  /usr/local/bin/sincronizza.sh
15 8 * * 1   /usr/local/bin/report-settimanale.sh

La prima riga esegue il backup ogni giorno alle 2:30; la seconda ogni sei ore allo scoccare dell'ora; la terza ogni lunedì alle 8:15. Il comando crontab -e modifica la crontab dell'utente corrente, mentre i file in /etc/cron.d/ permettono di definire lavori di sistema indicando anche l'utente con cui eseguirli.

Le trappole di cron

L'ambiente è quasi vuoto

Il problema più comune è un lavoro che funziona lanciato a mano e fallisce da cron. La ragione è quasi sempre l'ambiente: cron esegue i comandi con un PATH minimo e senza le variabili che la tua shell carica all'accesso. La soluzione è usare percorsi assoluti per programmi e file, oppure definire le variabili necessarie all'inizio dello script.

L'output si perde

Per impostazione predefinita cron tenta di inviare per email l'output dei comandi. Su un server senza posta configurata, quell'output finisce nel nulla, compresi i messaggi di errore. È buona pratica reindirizzare l'output in un file di registro o, meglio, nel registro di sistema.

Il carattere percento

Nella crontab il simbolo % ha un significato speciale e va preceduto da una barra rovesciata. Un comando come date +%Y-%m-%d scritto direttamente nella crontab non fa ciò che ti aspetti. Spostare la logica in uno script elimina il problema.

Lavori persi a server spento

Se il server è spento all'ora prevista, cron non recupera il lavoro mancato. Su un portatile o su una macchina che si riavvia spesso, un backup notturno può saltare per giorni senza che nessuno se ne accorga.

I timer di systemd

Sulle distribuzioni che usano systemd si può pianificare un lavoro con due file: un servizio, che descrive cosa eseguire, e un timer, che descrive quando.

# /etc/systemd/system/backup.service
[Unit]
Description=Backup notturno

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Esegue il backup ogni notte

[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
RandomizedDelaySec=10min

[Install]
WantedBy=timers.target

Si attiva con systemctl enable --now backup.timer e si controlla con systemctl list-timers, che mostra l'ultima e la prossima esecuzione di ogni timer.

Cosa offrono in più

  • Persistent=true recupera i lavori persi: se il server era spento all'ora prevista, il lavoro parte appena si riaccende.
  • Registri integrati: tutto l'output finisce nel journal, consultabile con journalctl -u backup.service.
  • Nessuna sovrapposizione: se l'esecuzione precedente è ancora in corso, il timer non ne avvia una seconda dello stesso servizio.
  • Ritardo casuale: RandomizedDelaySec distribuisce l'avvio, utile quando molti server colpirebbero lo stesso servizio nello stesso istante.
  • Limiti di risorse: si possono limitare CPU e memoria del lavoro con le normali opzioni di systemd.
  • Dipendenze: un lavoro può partire solo dopo che la rete o un disco sono disponibili.

Confronto rapido

Aspetto cron systemd timer
Semplicità di scrittura Una riga Due file
Lavori persi a macchina spenta Non recuperati Recuperabili
Registri Da configurare Integrati nel journal
Esecuzioni sovrapposte Possibili Evitate per lo stesso servizio
Portabilità Quasi ovunque Solo sistemi con systemd

Buone pratiche per qualsiasi strumento

Script robusti

Inizia gli script di shell con set -euo pipefail, così che si fermino al primo errore invece di proseguire con dati incompleti. Uno script di backup che continua dopo un errore può sovrascrivere una copia valida con una vuota.

Evitare le sovrapposizioni con cron

Se usi cron per un lavoro che può durare più dell'intervallo, proteggilo con flock, che impedisce l'avvio di una seconda copia finché la prima non ha finito:

*/10 * * * * flock -n /tmp/sync.lock /usr/local/bin/sincronizza.sh

Sapere quando qualcosa non parte

Il silenzio è il nemico dei lavori pianificati: un backup che fallisce senza avvisare è peggio di nessun backup, perché dà una falsa sicurezza. Una tecnica efficace è il controllo inverso: al termine positivo, lo script contatta un servizio di monitoraggio. Se il segnale non arriva entro l'orario previsto, il servizio invia un avviso. Così si scoprono anche i lavori che non sono partiti affatto, non solo quelli falliti.

Attenzione al fuso orario

Gli orari si riferiscono al fuso del server. Con l'ora legale, un lavoro pianificato in un orario che salta o si ripete durante il cambio può non partire o partire due volte. Molti amministratori impostano i server in UTC per evitare sorprese.

In sintesi

  • Cron è semplice e universale; i timer di systemd offrono recupero dei lavori persi, registri e protezione dalle sovrapposizioni.
  • In cron usa percorsi assoluti, reindirizza l'output e sposta la logica in script.
  • Con systemd, Persistent=true e journalctl risolvono due dei problemi più comuni.
  • Scrivi script che si fermano al primo errore ed evita esecuzioni sovrapposte.
  • Usa un controllo inverso per sapere quando un lavoro fallisce o non parte affatto.
MM
Marco Marzaduri

Marco Marzaduri si occupa di cybersecurity, informatica forense e sviluppo web. Laureato in informatica e in psicologia, unisce l'analisi tecnica alla comprensione del fattore umano.

Leggi anche