Devi riavviare il server, ma non adesso: stanotte alle quattro, quando i visitatori sono pochi. Oppure vuoi togliere tra un'ora la pagina di manutenzione, o fare una copia di sicurezza prima di andare a dormire. crontab (vedi l'articolo relativo) è fatto per le cose che si ripetono, at per quelle che accadono una volta sola.
Cos'è
at ("alle", come in "alle 4") è un piccolo programma di pianificazione. Funziona insieme a un servizio, atd, che resta in attesa in sottofondo e al momento giusto esegue i comandi che gli hai affidato. Sulle installazioni minime di Debian e Ubuntu non è presente: si aggiunge con sudo apt install at (vedi l'articolo su apt).
Cosa fa
Accetta un orario e un elenco di comandi, li mette in una coda e li esegue quando arriva il momento, una volta, poi dimentica il lavoro. Ricorda anche l'ambiente in cui l'hai programmato (cartella corrente, variabili) e permette di vedere, annullare o riprogrammare quello che hai in attesa.
Come si usa
$ at [opzioni] orarioGli esempi usano il server web01 degli articoli precedenti. Ho installato at 3.2.5 in un sandbox e ne ho provato i formati d'orario, la coda, -f, atrm e l'esecuzione dei lavori; le date negli esempi sono illustrative, e i nomi dei giorni sono in inglese perché at li scrive così.
Esempio 1: il comando di base
$ at 03:00 tomorrow
warning: commands will be executed using /bin/sh
at> /home/enzo/bin/backup.sh > /home/enzo/backup.log 2>&1
at> <EOT>
job 7 at Wed Nov 4 03:00:00 2026
$ echo "/home/enzo/bin/backup.sh > /home/enzo/backup.log 2>&1" | at 03:00 tomorrow
job 7 at Wed Nov 4 03:00:00 2026Dopo l'orario, at mostra un invito (at>) in cui scrivere i comandi, uno per riga; si termina con Ctrl+d, che compare come <EOT>. Alla fine risponde con il numero del lavoro (job 7) e con l'ora esatta in cui verrà eseguito. Il secondo modo è equivalente ma più comodo negli script: i comandi arrivano da echo attraverso una pipe (vedi l'articolo su echo e tee). L'avviso sulla /bin/sh è normale: i comandi vengono eseguiti con la shell semplice e non con bash.
Esempio 2: come scrivere l'orario
$ echo "comando" | at 14:30
$ echo "comando" | at 2:30pm
$ echo "comando" | at noon
$ echo "comando" | at midnight
$ echo "comando" | at teatime
$ echo "comando" | at now + 2 hours
$ echo "comando" | at now + 90 minutes
$ echo "comando" | at 08:00 tomorrow
$ echo "comando" | at 4pm + 3 days
$ echo "comando" | at 10:00 Mon
$ echo "comando" | at 10:00 next month
$ echo "comando" | at 10:00 Nov 20
$ echo "comando" | at 10:00 10.11.2026
$ echo "comando" | at 09:00 2026-11-10
$ at -t 202612010830at capisce un linguaggio molto libero, in inglese. Per l'ora: 14:30 o 2:30pm, e parole come noon (mezzogiorno), midnight (mezzanotte), teatime (le 16:00!) e now (adesso). Gli intervalli si scrivono con un +: now + 2 hours, + 90 minutes, + 3 days, + 1 week (le unità sono minutes, hours, days, weeks, months, years). Per la data: tomorrow, un giorno della settimana (Mon), un mese e un giorno (Nov 20), oppure 10.11.2026 (giorno, mese, anno) o 2026-11-10 (anno, mese, giorno). Con -t si scrive l'orario nel formato compatto AAAAMMGGhhmm. Se l'ora indicata è già passata oggi, il lavoro slitta a domani: alle 7:29, at 07:00 dà il giorno dopo.
Esempio 3: vedere, controllare e annullare
$ atq
7 Wed Nov 4 03:00:00 2026 a enzo
9 Thu Dec 31 17:30:00 2026 a enzo
$ at -l
$ at -c 7
#!/bin/sh
# atrun uid=1000 gid=1000
# mail enzo 0
umask 22
HOME=/home/enzo; export HOME
...
cd /home/enzo || {
echo 'Execution directory inaccessible' >&2
exit 1
}
/home/enzo/bin/backup.sh > /home/enzo/backup.log 2>&1
$ atrm 9
$ atq | wc -l
1atq (at queue), o at -l (list), elenca i lavori in attesa: numero, ora di esecuzione, la coda (una lettera, a per i lavori normali) e l'utente. Un utente normale vede solo i propri; root vede tutto. Con at -c N (cat) si legge che cosa verrà eseguito: at ha ricopiato tutto l'ambiente (variabili d'ambiente, umask: vedi l'articolo su export), la cartella in cui eri (cd ...) e, in fondo, i tuoi comandi. Qui ho ridotto le righe delle variabili con i puntini. Per annullare un lavoro, atrm N (at remove, o at -d N): ne puoi indicare più di uno.
Esempio 4: da un file, o con più righe
$ at -f /home/enzo/bin/backup.sh 03:00 tomorrow
warning: commands will be executed using /bin/sh
job 8 at Wed Nov 4 03:00:00 2026
$ at now + 2 minutes <<'FINE'
cd /var/www
tar czf /mnt/dati/www.tgz .
echo "backup finito $(date +%T)" >> /home/enzo/backup.log
FINE
job 9 at Tue Nov 3 07:32:00 2026Con -f file (file) i comandi vengono letti da un file: di solito uno script già pronto. Con un blocco di testo (here document: il pezzo tra <<'FINE' e la riga FINE) si scrivono più righe senza aprire l'invito interattivo: ideale negli script. Gli apici attorno a FINE fanno sì che $(date +%T) venga calcolato al momento dell'esecuzione, e non subito. Ho provato entrambe le forme: i comandi sono stati eseguiti all'ora prevista.
Esempio 5: dove va l'uscita
$ echo "/home/enzo/bin/backup.sh" | at 03:00
$ echo "/home/enzo/bin/backup.sh > /home/enzo/backup.log 2>&1" | at 03:00
$ echo "/home/enzo/bin/backup.sh" | at -m 03:00
$ echo "/home/enzo/bin/backup.sh" | at -M 03:00Un lavoro di at non ha uno schermo: ciò che il comando scrive viene inviato per posta all'utente (la posta locale del sistema, se esiste). Se la macchina non ha un servizio di posta, l'uscita va perduta: l'ho verificato, e persino un errore del comando sparisce senza lasciare traccia. Per questo la regola pratica è la seconda riga: reindirizza sempre l'uscita e gli errori in un file (> file 2>&1) e poi leggilo. Con -m (mail) si riceve un messaggio anche quando non c'è alcuna uscita; con -M non ne arriva mai.
Esempio 6: una rete di sicurezza per i cambiamenti rischiosi
$ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
$ echo "cp /etc/ssh/sshd_config.bak /etc/ssh/sshd_config; systemctl reload ssh" \
| sudo at now + 10 minutes
job 12 at Tue Nov 3 07:49:00 2026
$ sudo nano /etc/ssh/sshd_config
$ sudo systemctl reload ssh
(si prova ad aprire un secondo collegamento: se funziona...)
$ sudo atrm 12Un uso da amministratori prudenti. Prima di cambiare qualcosa che potrebbe tagliarti fuori dal server (la configurazione di ssh, il firewall, la rete: vedi gli articoli su ssh e ip), si programma il ripristino della configurazione precedente tra dieci minuti. Se la modifica funziona, si annulla il lavoro con atrm; se ti sei chiuso fuori, dopo dieci minuti il server si rimette a posto da solo. Il lavoro è creato con sudo at, quindi gira come root. Il collegamento aperto prima della modifica non cade, ma lo scopri solo provando uno nuovo.
Esempio 7: lavori che non gravano sul sistema, con batch
$ echo "/home/enzo/bin/rielabora-immagini.sh" | batch
warning: commands will be executed using /bin/sh
job 15 at Tue Nov 3 07:29:00 2026
$ atq
15 Tue Nov 3 07:29:00 2026 = enzo
$ echo "comando" | at -q b 03:00Il comando batch mette il lavoro in coda e lo avvia non a un'ora precisa, ma quando il sistema è abbastanza libero (di solito, con un carico medio sotto 1,5: vedi l'articolo su uptime). È pensato per lavori pesanti e non urgenti. Nell'elenco, il segno = al posto della lettera della coda indica un lavoro in esecuzione. Le code sono indicate da una lettera (da a a z), scelta con -q: batch usa di norma la b, e le lettere più avanti nell'alfabeto hanno una priorità più bassa.
Esempio 8: uso negli script
#!/bin/bash
# Pianifica un riavvio per le 04:00 e dice come annullarlo
JOB=$(echo "systemctl reboot" | at 04:00 tomorrow 2>&1 | awk '/^job/ {print $2}')
if [ -z "$JOB" ]; then
echo "Pianificazione fallita (atd è attivo?)" >&2
exit 1
fi
echo "Riavvio programmato (lavoro $JOB). Per annullare: sudo atrm $JOB"Lo script programma un riavvio e legge il numero del lavoro dalla risposta di at (con awk: vedi l'articolo relativo), così può dire come annullarlo. Va eseguito con sudo o come root. Esiste anche un modo diretto, sudo shutdown -r 04:00, che si annulla con sudo shutdown -c; at è più generale perché può eseguire qualunque comando.
Opzioni utili
at orario: programma un lavoro (comandi da tastiera, da pipe o da un blocco di testo).-f file: legge i comandi da un file;-t AAAAMMGGhhmm: orario in formato compatto.-m: manda sempre un messaggio al termine;-M: non manda mai niente.-q lettera: sceglie la coda (a-z);batch: esegue quando il carico è basso.atqoat -l: elenca i lavori;at -c N: mostra cosa verrà eseguito;atrm Noat -d N: annulla./etc/at.allow,/etc/at.deny: elenchi degli utenti ammessi o esclusi.crontab,shutdown -r ORA,systemd-run --on-active=: alternative per i lavori ripetuti, per il riavvio, per l'avvio dopo un'attesa.
Attenzione a
- Il servizio
atddeve essere in funzione: senza di esso il lavoro viene accettato ma non parte mai. Se vediCan't open /run/atd.pid to signal atd. No atd running?, controlla consystemctl status atd(vedi l'articolo susystemctl) e avvialo consudo systemctl enable --now atd. - L'uscita va nei file, non nel nulla: senza un servizio di posta locale, l'uscita e gli errori dei comandi spariscono. Reindirizza sempre (esempio 5), e dopo il primo lavoro controlla che il file ci sia.
- Si usa
sh, nonbash: le caratteristiche tipiche dibash(come[[ ... ]]o gli array) possono dare errore. Per uno script scritto perbash, usaat -f script.shcon la prima riga#!/bin/bash, oppure chiamabash script.sh. - La data americana è in agguato:
at 10:00 11/10/2026significa 10 novembre (mese/giorno/anno, come negli Stati Uniti), non 11 ottobre. Con i punti,10.11.2026, si legge giorno, mese, anno. Meglio ancora, scrivere2026-11-10, che non dà ambiguità, oppure controllare subito l'ora esatta nella risposta diat. - "yesterday" non esiste, e le ore sono 24:
atrispondeGarbled timea formati che non capisce eProblem in hours specificationa un'ora impossibile (25:00). Dopo ogniat, leggi la rigajob N at ...: è la conferma di cosa ha capito. - La precisione è al minuto: va bene per i compiti normali, non per i lavori che richiedono il secondo esatto.
- Non è pensato per i lavori critici: se la macchina è spenta o
atdsi ferma, non c'è garanzia che il lavoro parta. Per ciò che deve avvenire sempre usacrontabo un servizio disystemd; controlla conatqche il lavoro sia davvero in coda. - Il lavoro gira con i tuoi privilegi, e senza di te: se il comando ha bisogno di
sudocon la password non può funzionare; per i comandi da amministratore, programma il lavoro consudo at(esempio 6). Ricorda anche che non ha un terminale: i programmi interattivi non vanno bene. - Fuso orario e ora legale: l'orario è quello locale del server (controllalo con
date: vedi l'articolo relativo). Attorno al cambio di ora, e con i server in un altro fuso, verifica la data scritta daat. - Chi può usarlo: se esiste
/etc/at.allow, solo gli utenti elencati possono usareat; altrimenti vale/etc/at.deny(di default, contiene gli utenti di sistema comebackupebin);rootpuò sempre. Il comandoatdà un errore di permesso a chi non è ammesso. - Anche un lavoro può essere dimenticato: controlla ogni tanto con
atq(cometmux lsejobs) e annulla ciò che non serve.
Riepilogo
| Comando | Cosa fa |
|---|---|
at 03:00 tomorrow | Programma comandi (scritti dopo l'invito, fine con Ctrl+d) |
echo "cmd" | at now + 2 hours | Programma un comando senza invito interattivo |
at -f script.sh 03:00 | Programma i comandi di un file |
at -m 03:00 | Avvisa per posta alla fine, anche senza uscita |
atq / at -l | Elenca i lavori in attesa |
at -c N | Mostra cosa verrà eseguito (ambiente e comandi) |
atrm N | Annulla il lavoro N |
batch | Esegue quando il carico del sistema è basso |
sudo systemctl enable --now atd | Avvia il servizio che esegue i lavori |
sudo shutdown -r 04:00 | Riavvio programmato (si annulla con shutdown -c) |