Cron è la scelta storica per schedulare job su Unix. Ma se la tua distro usa systemd (Ubuntu, Debian, Fedora, Arch, ecc.), hai già a disposizione un sistema di timer più potente e meglio integrato: systemd timers.
Perché passare ai timer systemd
- Log unificati:
journalctl -u miojob.serviceti dà tutto (stdout, stderr, exit code, durata). - Dipendenze: puoi dire "esegui solo se il NAS è montato" o "dopo che network-online è ready".
- OnCalendar più espressivo:
OnCalendar=*-*-* 09:00:00oppureOnCalendar=Mon..Fri 09:00. - Esecuzioni perse:
Persistent=truerecupera al boot le esecuzioni perse mentre il server era spento. - Risorse: puoi mettere limiti CPU/RAM su una specifica esecuzione (
CPUQuota=20%,MemoryMax=512M). - Sandbox:
PrivateTmp=true,ReadOnlyPaths, ecc.
Anatomia: service + timer
Un job schedulato richiede 2 file: l'unità service che definisce cosa fare, e l'unità timer che definisce quando.
Esempio: backup notturno alle 03:00
/etc/systemd/system/backup-casa.service:
[Unit]
Description=Backup notturno di /var/www su NAS
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
User=root
ExecStart=/usr/bin/rsync -a --delete /var/www/ /mnt/nas/backup/web/
ExecStartPost=/usr/bin/logger -t backup-casa "Backup completato con exit $EXIT_STATUS"
/etc/systemd/system/backup-casa.timer:
[Unit]
Description=Esegue backup-casa.service ogni notte alle 03:00
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
RandomizedDelaySec=300
[Install]
WantedBy=timers.target
Attivazione
sudo systemctl daemon-reload
sudo systemctl enable --now backup-casa.timer
# verifica
systemctl list-timers --all backup-casa.timer
# o tutti i timer attivi
systemctl list-timers
Sintassi OnCalendar più utile
| Espressione | Quando |
|---|---|
hourly | Allo scoccare di ogni ora |
daily | Ogni giorno a mezzanotte |
weekly | Ogni lunedì a mezzanotte |
*:0/15 | Ogni 15 minuti |
Mon..Fri 09:00 | Lun-ven alle 9:00 |
*-*-01 06:00:00 | Il primo del mese alle 06:00 |
2026-12-25 10:00:00 | Una sola volta, il 25/12/2026 |
Verifica un'espressione prima di metterla in produzione:
systemd-analyze calendar 'Mon..Fri 09:00'
Log di un job
# tutti i run del job
journalctl -u backup-casa.service
# solo gli ultimi 50
journalctl -u backup-casa.service -n 50 --no-pager
# stream live
journalctl -u backup-casa.service -f
# solo errori
journalctl -u backup-casa.service -p err
Differenze chiave vs cron
| Aspetto | cron | systemd timers |
|---|---|---|
| Job persi al boot | Solo con anacron | Nativi (Persistent=true) |
| Log | Email o redirect | journalctl integrato |
| Variabili ambiente | Ridotte (no PATH completo) | Default da unit + Environment= |
| Retry | No | Restart= nella service |
| Dipendenze | No | Wants/After/Requires |
| Output mail | Sì (postfix) | No native — fallo nel service |
Migrazione graduale: cron e systemd timers coesistono benissimo. Non c'è bisogno di migrare tutto in un giorno — sostituisci un job alla volta, partendo dai più critici.