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=trueesegue una volta al boot se la sua pianificazione è stata persa; cron semplicemente salta. - Dipendenze: i timer possono aspettare
network-online.targeto 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:
- I nomi di servizio e timer non corrispondono.
foo.timerfa scattarefoo.service— unOnFailurecon typo o un’unit rinominata significa che il timer «esegue» nel nulla.systemctl cat foo.timermostra esattamente cosa punta. - 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. Persistent=truecon semantica diOnCalendardiversa da quella che ti aspetti — oppure stai guardandosystemctl status foo.timer(mostra sempre attivo anche quando è inattivo) invece dilist-timers.- Il servizio che fa scattare fallisce all’istante, così il timer sembra morto.
journalctl -u foo.service --since -1hmostrerà il crash chelist-timersnasconde.
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
| cron | timer systemd | |
|---|---|---|
| Setup | una riga di crontab | due unit file |
| Logging | mail locale, di solito mai letta | journal, per unit |
| Run mancato (macchina spenta) | saltato | una volta al boot con Persistent=true |
| Dipendenze / ordinamento | nessuna — fai da te nello script | dipendenze complete da unit |
| Ritardo randomizzato | fai da te con $RANDOM | RandomizedDelaySec= |
| Test/dry-run della pianificazione | no | systemd-analyze calendar |
| Esiste ovunque | sì — container, BSD, embedded | richiede systemd (PID 1) |
| Job utente senza root | crontab -e | unit 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.
what is this?llama.cpp vs Ollama: quale scegliere nel 2026?
Ti piacciono gli articoli? È così che costruisco per lavoro. assumimi