Un server si ripaga lavorando mentre dormi: backup, rotazione dei log, rinnovo dei certificati, un report alle nove. Linux ha due pianificatori per questo. Cron ha quarant'anni e sta in una riga. I timer di systemd richiedono due piccoli file e in cambio danno log, recupero dopo un fermo e orario esatto. Questa guida li copre entrambi su Ubuntu 24.04, con ogni comportamento verificato su un server nuovo dalla nostra immagine, compresi i tre errori che fanno fallire un job di cron senza una parola.
Ti serve un utente con sudo; la guida all'installazione di Ubuntu ne crea uno.
1. Cron in cinque minuti
Cron è installato e attivo sulle nostre immagini Ubuntu e Debian. Ogni utente ha una tabella di job; modifica la tua con:
crontab -e
Ogni riga ha cinque campi di tempo e un comando:
# min hour day month weekday command
30 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
*/5 * * * * /usr/local/bin/check.sh
0 9 * * 1-5 /usr/local/bin/report.sh
@reboot /usr/local/bin/start-tunnel.sh
Cioè: alle 03:30 ogni notte, ogni 5 minuti, alle 09:00 nei giorni feriali e una volta dopo ogni avvio. */5 significa un valore ogni cinque, 1-5 un intervallo, 1,15 un elenco. Vale il fuso orario del server, UTC sulle nostre immagini; imposta il tuo una volta con la guida su hostname e fuso orario e cron lo segue.
Controlla cosa è stato eseguito con journalctl -u cron. Ogni esecuzione registra utente e comando, ed è lì che emergono le tre trappole.
Trappola 1: l'output sparisce. Cron invia per email l'output di un job all'utente. La nostra immagine non ha un server di posta, quindi il journal riportava (CRON) info (No MTA installed, discarding output) e l'output era perso. Reindirizzalo tu, come nel primo esempio con >> /var/log/backup.log 2>&1.
Trappola 2: il segno di percentuale. In una crontab % chiude il comando e trasforma il resto in input standard. Abbiamo pianificato date +%F > /tmp/today. Il journal mostra cosa ha eseguito davvero cron: CMD (date +). Nessun file scritto e nessun errore arrivato a noi. Scrivi \%, oppure metti il comando in uno script e pianifica lo script.
Trappola 3: un ambiente diverso. Cron esegue i job con /bin/sh, non bash, nella tua home e con un ambiente ridotto. Su Ubuntu 24.04 il PATH si è rivelato migliore della sua fama: il percorso di sistema completo, inclusi /usr/local/bin e /snap/bin, per root e per un utente normale. Ciò che manca ancora è tutto quello sotto la tua home: ~/.local/bin, il node di nvm, pipx, cargo. Usa percorsi completi nel job o inizia la riga con . $HOME/.profile;.
I job che appartengono al sistema e non a un utente vanno in /etc/cron.d/, come file con un campo in più, l'utente:
30 3 * * * root /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
Ubuntu esegue anche tutto ciò che si trova in /etc/cron.hourly, cron.daily, cron.weekly e cron.monthly, al minuto 17 di ogni ora, alle 06:25, alle 06:47 la domenica e alle 06:52 il primo del mese. Metti lì uno script eseguibile e girerà con gli altri.
2. Timer di systemd
Un timer sono due unità: un servizio che fa il lavoro e un timer che dice quando. Crea prima lo script, poi le unità.
sudo nano /usr/local/bin/backup.sh
sudo chmod +x /usr/local/bin/backup.sh
sudo nano /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
sudo nano /etc/systemd/system/backup.timer
[Unit]
Description=Run the backup every night at 03:30
[Timer]
OnCalendar=*-*-* 03:30
Persistent=true
AccuracySec=1m
[Install]
WantedBy=timers.target
Abilita il timer, non il servizio:
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers backup.timer
list-timers mostra la prossima esecuzione, quanto manca e l'ultima esecuzione. I log non richiedono configurazione: journalctl -u backup.service contiene ogni avvio, ogni fine e ogni riga di output, con orario. Per eseguire subito il job, sudo systemctl start backup.service; è anche così che provi lo script prima di fidarti della pianificazione.
Sintassi del calendario. OnCalendar si legge giornosettimana anno-mese-giorno ora:minuto:secondo, con * per qualsiasi valore. Prova un'espressione prima di usarla:
systemd-analyze calendar "Mon..Fri *-*-* 03:00" --iterations 2
Stampa la forma normalizzata e le prossime date. Alcune espressioni che abbiamo verificato:
| OnCalendar | Significato |
|---|---|
*-*-* 03:30 | Ogni giorno alle 03:30 |
Mon..Fri *-*-* 09:00 | Nei giorni feriali alle 09:00 |
*:0/15 | Ogni 15 minuti |
weekly | Il lunedì alle 00:00 |
*-*-01 04:00 | Il primo di ogni mese alle 04:00 |
*-*-* 03:00 Europe/Kyiv | Le 03:00 ora di Kyiv; nel nostro test è partito alle 01:00 UTC |
Le tre impostazioni da conoscere. Persistent=true salva l'ultima esecuzione su disco e recupera un'esecuzione persa mentre il server era spento o il timer fermo. Abbiamo fermato il nostro timer ogni due minuti, atteso che passasse un'esecuzione prevista e lo abbiamo riavviato: l'esecuzione persa è partita nello stesso secondo. Senza Persistent, aspetta semplicemente lo slot successivo.
AccuracySec è la sorpresa. Di default systemd raggruppa i timer in una finestra di un minuto per risparmiare risvegli, così la nostra prima esecuzione è arrivata alle 07:42:18, non alle 07:42:00. Con AccuracySec=1s le successive sono cadute alle 07:46:00 e 07:48:00 al secondo. Impostalo quando conta il minuto; lascia il default per un backup notturno.
RandomizedDelaySec=10m fa il contrario, di proposito: distribuisce l'avvio su una finestra perché dieci server non colpiscano lo stesso storage di backup nello stesso secondo.
Per un job una tantum, nessun file:
sudo systemd-run --on-active=30m --unit=cleanup-once /usr/local/bin/cleanup.sh
Crea un timer transitorio che scatta una volta e sparisce; fino ad allora lo mostra systemctl list-timers.
3. Quale usare
| Cron | Timer systemd | |
|---|---|---|
| Configurazione | 1 riga | 2 file |
| Log | Solo se reindirizzi l'output | journalctl -u name.service |
| Esecuzione persa a server spento | Persa | Eseguita all'avvio con Persistent=true |
| Job ancora in corso al tick successivo | Parte una seconda copia | Saltato finché la prima non finisce |
| Orario esatto | Al minuto | Al secondo con AccuracySec=1s |
| Stato | Nessuno | list-timers, systemctl status |
Usa cron per una riga veloce che riconoscerai tra un anno. Usa un timer per tutto ciò di cui devi vedere il fallimento, che non deve sovrapporsi o che deve girare dopo un riavvio mancato: backup, rinnovo dei certificati, pulizia dei database. Se un job cron può sovrapporsi, avvolgilo: flock -n /tmp/backup.lock /usr/local/bin/backup.sh, e la seconda copia esce subito.
Entrambi i pianificatori avviano un job e si fermano. Per un programma che deve girare sempre e ripartire dopo un crash serve un servizio, non una pianificazione; vedi come creare un servizio systemd e, per Windows, come eseguire uno script 24/7 su Windows Server. Un buon primo timer è quello della nostra guida al backup con restic; gli aggiornamenti di sicurezza automatici sono un timer che Ubuntu fornisce già, apt-daily-upgrade.timer, uno dei 17 attivi su un server nuovo.
Commenti
Ancora nessun commento. Sii il primo.