Torna al blog

Cron vs timer di systemd: quale scegliere?

11 settembre 2026

Su una distro moderna usa un timer di systemd per tutto ciò che è tuo, e tieni cron per i job utente di una riga e per i server che non hai configurato tu. I timer loggano ogni esecuzione nel journal, possono recuperare le pianificazioni mancate mentre la macchina era spenta, e si appoggiano agli stessi unit file di tutto il resto del sistema. Cron vince sulla brevità — una riga di crontab -e batte due unit file — ed è ancora l’unico scheduler la cui esistenza è garantita sui container minimi e sui sistemi Unix esotici. Il prezzo: cron fallisce in silenzio. Se il tuo job sbaglia alle 3 di notte, cron invia una mail a una casella locale che nessuno legge, mentre un timer ti dà journalctl -u mytimer.service con l’output completo. Qui sotto: le differenze reali, come testare entrambi, perché un timer potrebbe non scattare, e una tabella decisionale.

Qual è la differenza tra cron e un timer di systemd?

Cron è un demone che legge una tabella di righe — cinque campi temporali e un comando — ed esegue ogni comando quando l’orologio coincide. Tutto qui il modello. Non ha il concetto di job come oggetto: niente unit, niente status, niente dipendenze, nessuna voce di log propria.

Un timer di systemd è un unit file (foo.timer) che fa scattare un altro unit file (foo.service) quando la sua pianificazione coincide. Il job è un oggetto di prima classe, con start, status, log e tracciamento dei fallimenti come qualsiasi altro servizio. La pianificazione è basata sul calendario (in stile cron) o monotona (OnBootSec=15min, che i cambiamenti dell’orologio di sistema non confondono).

Le conseguenze pratiche:

  • Logging: i timer loggano stdout/stderr nel journal per unit; cron al massimo invia una mail all’utente locale.
  • Run mancati: un timer con Persistent=true esegue una volta al boot se la sua pianificazione è stata persa; cron semplicemente salta.
  • Dipendenze: i timer possono aspettare network-online.target o mount point; cron ti costringe a scriverarti a mano la logica di retry nello script.
  • Sintassi: cron è una riga; un timer sono due file. È l’intero costo del cambio.

Quale sintassi è più semplice — crontab o OnCalendar?

I cinque campi di cron sono l’incumbent compatto: */15 * * * * è ogni 15 minuti, e la maggior parte degli admin li legge col sonno. OnCalendar= di systemd è più prolisso ma strettamente più espressivo, e systemd-analyze calendar ti dice le prossime esecuzioni prima che tu confermi — cron non ha un dry-run equivalente.

# Cron: ogni giorno alle 03:30
30 3 * * * /usr/local/bin/backup.sh

# systemd: la stessa pianificazione, verificabile prima di salvarla
systemd-analyze calendar "*-*-* 03:30:00"
# -> Next elapse: Fri 2026-09-11 03:30:00 ...

OnCalendar gestisce cose che cron non sa esprimere in modo pulito: Mon..Fri *-*-* 09..17:00:00 (giorni feriali, orario d’ufficio), oppure *:0/15 con RandomizedDelaySec=10m per evitare che mille macchine martellino un server nello stesso istante.

Come testo un timer di systemd senza aspettare?

Tre comandi rispondono a tutto. Elenchi cosa è pianificato e quando scatta la prossima volta, esegui il job a mano esattamente come farebbe il timer, poi leggi i suoi log:

systemctl list-timers --all                 # ogni timer, prossima + ultima esecuzione
sudo systemctl start backup.service         # lancia il job ora, stessa unit del timer
journalctl -u backup.service -f             # guarda il suo output in diretta

Nota la separazione: systemctl start backup.timer arma la pianificazione; il servizio è il job. Se list-timers mostra il tuo timer, systemctl status backup.service è verde e il journal mostra il tuo output, l’intera catena funziona.

Come eseguo un job cron a mano?

I job cron girano con un ambiente spogliato, ed è per questo che «funziona nella mia shell, fallisce in cron» è un genere di bug a sé. Per riprodurre cron fedelmente, esegui il comando attraverso sh con lo stesso ambiente che userebbe cron:

crontab -l                                  # confermi la riga esatta
env -i SHELL=/bin/sh PATH=/usr/bin:/bin sh -c '/usr/local/bin/backup.sh'
grep CRON /var/log/syslog | tail            # cron l'ha proprio eseguito? (Debian/Ubuntu)
journalctl -u cron -n 20                    # lo stesso, sulle distro systemd

Quella riga con env -i è il test manuale onesto: un ambiente nudo con il PATH predefinito di cron. La maggior parte dei fallimenti silenziosi di cron è un PATH scarno o un % non quotato nel comando (cron tratta % come un newline), e entrambi si vedono subito così.

Perché il mio timer di systemd non scatta?

Quattro cause coprono quasi tutti i casi, nell’ordine in cui verificarle:

  1. I nomi di servizio e timer non corrispondono. foo.timer fa scattare foo.service — un OnFailure con typo o un’unit rinominata significa che il timer «esegue» nel nulla. systemctl cat foo.timer mostra esattamente cosa punta.
  2. Il timer è stato modificato ma non ricaricato. Dopo aver cambiato un unit file: sudo systemctl daemon-reload && sudo systemctl restart foo.timer. Senza questo la nuova pianificazione non è attiva.
  3. Persistent=true con semantica di OnCalendar diversa da quella che ti aspetti — oppure stai guardando systemctl status foo.timer (mostra sempre attivo anche quando è inattivo) invece di list-timers.
  4. Il servizio che fa scattare fallisce all’istante, così il timer sembra morto. journalctl -u foo.service --since -1h mostrerà il crash che list-timers nasconde.

E quando vai a guardare i log, il journalctl cheat sheet copre i filtri (-u, --since, -f) che rendono tutto rapido.

Cron vs timer di systemd: la tabella decisionale

crontimer systemd
Setupuna riga di crontabdue unit file
Loggingmail locale, di solito mai lettajournal, per unit
Run mancato (macchina spenta)saltatouna volta al boot con Persistent=true
Dipendenze / ordinamentonessuna — fai da te nello scriptdipendenze complete da unit
Ritardo randomizzatofai da te con $RANDOMRandomizedDelaySec=
Test/dry-run della pianificazionenosystemd-analyze calendar
Esiste ovunquesì — container, BSD, embeddedrichiede systemd (PID 1)
Job utente senza rootcrontab -eunit di systemd --user

Regole pratiche: un job su una macchina systemd tua → timer. Un promemoria personale veloce o una macchina che non hai costruito tu → cron. Qualsiasi cosa con dipendenze, retry o bisogno di sapere se è proprio girata → timer, sempre. Un pattern comune è un timer che esegue un job di manutenzione — un backup rsync notturno, per esempio — dove Persistent=true garantisce che il backup avvenga anche se la macchina dormiva al minuto programmato, cosa che cron semplicemente non può offrire.

— mrsaynothing

Get the next one by email

One email per post. No spam, no algorithms.

self-hosted · no third parties · one-click unsubscribe

what is this?

llama.cpp vs Ollama: quale scegliere nel 2026?

Ti piacciono gli articoli? È così che costruisco per lavoro. assumimi