Salta al contenuto principale

watch: ripetere un comando e vedere cosa cambia

Inviato da tuxsa il

Stai copiando un file grosso e vuoi sapere a che punto è? Hai riavviato un servizio e vuoi vedere se torna "attivo"? Aspetti che un disco si riempia o che una coda si svuoti? Potresti scrivere lo stesso comando venti volte, oppure lasciarlo a watch, che lo ripete da solo e ti mostra la situazione che si aggiorna sullo schermo.

Cos'è

watch ("guarda") fa parte del pacchetto procps, come top, free, uptime e ps, ed è presente su ogni distribuzione. È un piccolo programma con un solo compito: eseguire un comando a intervalli regolari e mostrarne l'output a schermo intero, sempre nello stesso punto, in modo che si possano vedere i cambiamenti. Il comando può essere qualunque cosa: watch non sa niente di dischi, memoria o servizi, ripete e basta.

Cosa fa

Esegue il comando ogni 2 secondi (a meno che tu non scelga un altro intervallo), cancella lo schermo, scrive la nuova uscita con in cima una riga di intestazione e ricomincia, finché non lo interrompi con Ctrl+C. Può anche evidenziare le parti che sono cambiate, o fermarsi da solo quando l'uscita cambia.

Come si usa

$ watch [opzioni] comando

Gli esempi usano il server web01 degli articoli precedenti; le uscite sono illustrative, ma i comportamenti delle opzioni li ho provati su un terminale di prova.

Esempio 1: il comando senza opzioni

$ watch free -h
Every 2.0s: free -h                        web01: Sun Nov  1 05:35:12 2026

               total        used        free      shared  buff/cache   available
Mem:           7.8Gi       3.0Gi       812Mi       112Mi       3.9Gi       4.5Gi
Swap:          2.0Gi       7.9Mi       2.0Gi

Lo schermo si svuota e compare l'uscita di free -h (vedi l'articolo su free), che si aggiorna ogni 2 secondi. La prima riga è l'intestazione: a sinistra l'intervallo e il comando in esecuzione (Every 2.0s: free -h), a destra il nome della macchina e l'ora dell'ultimo aggiornamento. Il testo dell'intestazione è in inglese e il formato dell'ora può cambiare con la lingua del sistema. Per uscire si preme Ctrl+C.

Esempio 2: scegliere l'intervallo, con -n

$ watch -n 1 uptime
$ watch -n 0.5 cat /proc/loadavg
$ watch -n 60 df -h /
$ watch -p -n 1 date +%T.%N

Con -n (interval) si sceglie ogni quanti secondi ripetere. Sono ammessi anche i decimali, con un minimo di 0,1 secondi. Un intervallo breve dà un quadro più vivo ma carica di più la macchina, uno lungo basta per le cose lente. Il tempo di attesa parte quando il comando finisce: se il comando è lento, i cicli si allungano. Con -p (precise) watch prova a mantenere gli intervalli esatti, anche contando il tempo impiegato dal comando.

Esempio 3: evidenziare cosa è cambiato, con -d

$ watch -d -n 1 'ls -l /mnt/dati/backup'
Every 1.0s: ls -l /mnt/dati/backup         web01: Sun Nov  1 05:38:41 2026

totale 4813120
-rw-r--r-- 1 root root 4928675840  1 nov 05.38 www-20261101.tar.gz
$ watch -d=permanent -n 1 'ls -l /mnt/dati/backup'

Con -d (differences) watch mette in evidenza, in negativo (colori invertiti), i caratteri che sono cambiati dall'aggiornamento precedente: nell'esempio, la dimensione del file di backup che cresce, mentre il nome resta uguale. Con -d=permanent (o --differences=permanent) l'evidenziazione resta su tutto ciò che è cambiato almeno una volta dall'inizio: utile per accorgersi di una variazione che dura un istante, per esempio una connessione che compare e sparisce. Qui l'evidenziazione non si vede, ma sul terminale è evidente.

Esempio 4: comandi con pipe, nel modo giusto

$ watch 'ps aux | grep nginx'
$ watch "ps aux | grep -c nginx"
$ watch 'df -h / | tail -n 1'
$ watch ps aux | grep nginx

Qui c'è l'errore più frequente. Con una pipe (|), o con altri simboli della shell (>, &&, $(...)), il comando va scritto tra apici, come un'unica stringa: così watch lo riceve intero e lo ripete. Senza apici (l'ultima riga) la shell la interpreta subito in un altro modo: l'uscita di watch finisce a grep, e vedrai quasi niente. Gli apici singoli ('...') lasciano il testo così com'è; con gli apici doppi ("...") la shell sostituisce prima le variabili e i comandi tra $(...), ed è raramente quello che vuoi.

Esempio 5: seguire lo spazio e i progressi

$ watch -n 5 df -h /mnt/dati
Every 5.0s: df -h /mnt/dati                web01: Sun Nov  1 05:40:02 2026

File system     Dim. Usati Dispon. Uso% Montato su
/dev/sdb1       1,8T   1,2T    545G  69% /mnt/dati
$ watch -n 2 du -sh /mnt/usb/copia
$ watch -n 1 'ls /mnt/usb/copia | wc -l'

Un uso classico: seguire dal vivo una copia lunga fatta con cp, rsync o tar in un'altra finestra. df mostra lo spazio che si riempie, du -sh la dimensione della cartella di destinazione, e ls ... | wc -l il numero di file già copiati (vedi gli articoli su df e du, su wc e su rsync). Con -n 2 o più, per non appesantire una macchina già impegnata.

Esempio 6: monitorare un servizio o il sistema

$ watch -n 2 systemctl status nginx --no-pager
$ watch -n 1 'ss -tn state established | wc -l'
$ watch -n 10 'journalctl -p err --since "10 minutes ago" -q | wc -l'
$ watch -n 1 'ps -eo pid,pcpu,pmem,comm --sort=-pcpu | head -n 6'
$ watch -n 1 lsblk

Altre combinazioni utili: lo stato di un servizio dopo averlo riavviato (vedi l'articolo su systemctl), il numero di connessioni attive (vedi ss), quanti errori sono stati registrati negli ultimi minuti (vedi journalctl), i cinque processi che usano più processore (vedi ps) e i dischi presenti mentre colleghi una chiavetta (vedi lsblk). Una dritta: per i processi, top è già pensato per aggiornarsi da solo, ma con watch scegli tu le colonne e l'ordine.

Esempio 7: aspettare che qualcosa cambi, con -g, -q ed -e

$ watch -n 5 -g 'systemctl is-active nginx'; echo "Lo stato di nginx è cambiato"
$ watch -n 1 -g 'ls /tmp/pronto 2>/dev/null'; echo "Il file è comparso"
$ watch -n 5 -q 3 'ls /mnt/dati/backup | wc -l'
$ watch -n 5 -e 'curl -fsS http://localhost/ -o /dev/null'

Per non restare davanti allo schermo, watch può fermarsi da solo. Con -g (chgexit) termina quando l'uscita cambia: il comando dopo il punto e virgola viene eseguito subito dopo (qui un semplice messaggio; potrebbe essere una notifica o il passo successivo di una procedura). Con -q N (equexit) termina quando l'uscita non cambia per N cicli di fila: per esempio quando una copia ha smesso di crescere. Con -e (errexit) si ferma se il comando fallisce, e mostra il messaggio "command exit with a non-zero status, press a key to exit"; il suo codice di uscita è 8 (vedi l'articolo su curl per le opzioni usate nell'ultimo esempio). Con -b emette un suono quando il comando fallisce.

Esempio 8: colori, titolo e righe lunghe

$ watch -c 'ls -l --color=always /var/www'
$ watch -t -n 1 date
$ watch -w -n 2 'ps -eo pid,args --sort=-pcpu | head -n 5'

Di norma watch mostra i colori come caratteri incomprensibili: con -c li interpreta, ma il comando deve produrli anche quando non scrive su un terminale (qui con --color=always, e lo stesso vale per grep). Con -t (no title) si toglie la riga di intestazione, utile per un orologio o un valore da tenere in un angolo dello schermo. Con -w (no wrap) le righe più lunghe dello schermo vengono tagliate invece di andare a capo.

Esempio 9: la stessa idea, dentro uno script

#!/bin/bash
# Aspetta che il servizio sulla porta 8080 sia pronto
until lsof -i :8080 -sTCP:LISTEN -t >/dev/null; do
    sleep 2
done
echo "Servizio pronto"

# Un "mini watch" con cronologia su file
while true; do
    ORA=$(date '+%F %T')
    echo "$ORA $(cut -d ' ' -f 1-3 /proc/loadavg)" | tee -a "$HOME/carico.log"
    sleep 60
done

watch è fatto per le persone: ha bisogno di un terminale, e non serve in uno script o in un compito programmato con crontab. Negli script lo stesso risultato si ottiene con un ciclo: until ripete finché il comando non riesce (qui, finché la porta non è in ascolto: vedi l'articolo su lsof), while true ripete all'infinito. Il secondo ciclo, a differenza di watch, conserva la cronologia: ogni riga viene scritta con tee -a in un file (vedi l'articolo su tee), così il giorno dopo puoi vedere come è andata. L'ho provato con un servizio finto.

Opzioni utili

  • -n secondi: intervallo di ripetizione (predefinito 2, minimo 0,1); -p: intervalli più precisi.
  • -d: evidenzia le differenze; -d=permanent: le tiene evidenziate per sempre.
  • -g: esce quando l'uscita cambia; -q N: esce se non cambia per N cicli; -e: esce se il comando fallisce; -b: suono in caso di errore.
  • -t: senza intestazione; -c: interpreta i colori; -w: righe tagliate invece che a capo.
  • -x: esegue il comando direttamente, senza la shell (utile se i caratteri speciali danno problemi).
  • top, vmstat 1, free -s 2, ping, tail -f, journalctl -f: programmi che si aggiornano già da soli.

Attenzione a

  • Gli apici fanno la differenza: i comandi con |, >, &&, ; o $(...) vanno scritti tra apici singoli. Se l'uscita ti sembra strana o vuota, è quasi sempre questo.
  • Gli alias non funzionano: watch esegue il comando in una shell semplice, che non conosce i tuoi alias né le tue funzioni (vedi l'articolo su alias). Usa il comando completo; per le variabili d'ambiente, ricorda l'articolo su export.
  • Con sudo, mettilo davanti a watch: sudo watch -n 2 'cat /var/log/...' chiede la password una sola volta e funziona; watch sudo ... la richiederebbe a ogni ciclo e rovinerebbe lo schermo.
  • Non appesantire la macchina: un comando costoso (du su un disco enorme, find /, lsof +D) ripetuto ogni secondo carica il disco e il processore, proprio quando vuoi capire cosa non va. Scegli intervalli più lunghi e comandi leggeri.
  • Non lasciarlo acceso per sbaglio: un watch dimenticato in una vecchia sessione ssh continua a lavorare per giorni. Chiudilo con Ctrl+C quando hai finito (vedi anche l'articolo su who per le sessioni aperte).
  • Non ricorda niente: ogni aggiornamento cancella il precedente, e uscendo lo schermo torna come prima. Per conservare i dati usa un ciclo con tee -a (esempio 9) oppure reindirizza l'uscita su un file.
  • Mostra solo ciò che sta nello schermo: un'uscita più lunga delle righe disponibili viene tagliata in fondo, e watch non ha una barra di scorrimento. Accorcia l'uscita con head o tail, o allarga la finestra.
  • Il tempo di esecuzione si somma: se un comando impiega 3 secondi e l'intervallo è 2, un ciclo dura 5. Per misure regolari usa -p, oppure strumenti pensati per questo come vmstat e iostat.
  • Serve un terminale: in un compito programmato o in un comando lanciato senza terminale watch non funziona. Per l'uso automatico servono i cicli dell'esempio 9.
  • Un comando che modifica qualcosa, lo modifica a ogni ciclo: watch rm ... o watch cp ... li ripetono all'infinito. Usa watch solo per comandi che leggono.

Riepilogo

ComandoCosa fa
watch comandoRipete il comando ogni 2 secondi a schermo intero
watch -n 5 comandoRipete ogni 5 secondi (anche 0.5)
watch 'cmd1 | cmd2'Ripete un comando con pipe (tra apici!)
watch -d comandoEvidenzia le differenze tra un aggiornamento e l'altro
watch -d=permanent comandoMantiene evidenziato tutto ciò che è cambiato
watch -g comandoSi ferma quando l'uscita cambia
watch -q 3 comandoSi ferma quando non cambia per 3 cicli
watch -e comandoSi ferma se il comando fallisce
watch -t comandoSenza riga di intestazione
watch -c comandoMostra i colori del comando
sudo watch comandoCome amministratore (la password una volta sola)
until comando; do sleep 2; doneAspetta in uno script che il comando riesca

Nel prossimo articolo: tmux, per tenere più terminali in una sola sessione che resta attiva anche dopo la disconnessione.