Stai per riavviare un server e vuoi sapere se qualcuno ci sta lavorando. Oppure ti accorgi di un rallentamento e vuoi capire chi è collegato, e da dove. who ("chi") risponde con un elenco di poche righe: gli utenti presenti in questo momento, il terminale che usano, da quando e da quale indirizzo si sono collegati.
Cos'è
who fa parte del pacchetto coreutils, quindi è disponibile su ogni distribuzione. Non cerca niente per conto suo: legge il registro delle sessioni, un piccolo file chiamato utmp (in /var/run/utmp) in cui il sistema annota chi entra e chi esce. Per questo who risponde subito, ed è affidabile finché il registro è aggiornato.
Cosa fa
Elenca le sessioni aperte, una per riga: il nome utente, il terminale su cui lavora, la data e l'ora di accesso e, se la connessione è da remoto, l'indirizzo di provenienza. Con le opzioni aggiunge le intestazioni, da quanto tempo l'utente è inattivo, l'ora dell'ultimo avvio e altro.
Come si usa
$ who [opzioni]Gli esempi mostrano un server chiamato web01, con due utenti collegati.
Esempio 1: il comando senza opzioni
$ who
enzo pts/0 2026-10-29 09:20 (203.0.113.45)
backup pts/1 2026-10-29 08:02 (192.168.1.20)Le colonne, da sinistra a destra: il nome dell'utente, il terminale, la data e l'ora di accesso e, tra parentesi, l'indirizzo da cui si è collegato. Gli indirizzi sono inventati. Il terminale pts/N indica una sessione da remoto (per esempio con ssh) o una finestra di terminale in un ambiente grafico; tty1, tty2… sono i terminali "veri" davanti alla macchina; un indirizzo come :0 tra parentesi indica una sessione grafica locale. Se nessuno è collegato, l'output è vuoto.
Esempio 2: con le intestazioni, con -H
$ who -H
NAME LINE TIME COMMENT
enzo pts/0 2026-10-29 09:20 (203.0.113.45)
backup pts/1 2026-10-29 08:02 (192.168.1.20)Con -H (heading) compare la riga con i nomi delle colonne, comoda quando si mostra l'output a qualcun altro.
Esempio 3: chi è inattivo, con -u
$ who -Hu
NAME LINE TIME IDLE PID COMMENT
enzo pts/0 2026-10-29 09:20 . 3841 (203.0.113.45)
backup pts/1 2026-10-29 08:02 01:15 3902 (192.168.1.20)L'opzione -u (users) aggiunge due colonne: IDLE, da quanto tempo l'utente non scrive niente (il punto . significa "attivo nell'ultimo minuto", 01:15 è un'ora e un quarto fa) e PID, il numero del processo della sessione (vedi l'articolo su ps e kill). L'utente backup risulta quindi collegato ma fermo da più di un'ora: forse una sessione dimenticata aperta.
Esempio 4: contare gli utenti, con -q
$ who -q
enzo backup
# users=2Con -q (quick, o count) si ottengono solo i nomi e il totale delle sessioni. Se lo stesso utente ha due finestre aperte il nome compare due volte e il totale conta due.
Esempio 5: ultimo avvio e altre informazioni
$ who -b
system boot 2026-09-12 06:39
$ who -r
run-level 5 2026-09-12 06:39
$ who -a-b (boot) mostra la data dell'ultimo avvio, come visto nell'articolo su uptime. L'opzione -r (runlevel) è un residuo dei vecchi sistemi: oggi i sistemi con systemd mostrano spesso un valore fisso (come 5) che non ha più un significato pratico, e su molte installazioni non mostra niente. Con -a (all) si ottiene tutto insieme: avvio, processi di accesso, utenti e altro.
Esempio 6: chi sono io? who am i
$ who am i
enzo pts/0 2026-10-29 09:20 (203.0.113.45)
$ whoami
enzo
$ id -un
enzo
$ logname
enzoCon who am i (o who -m) si ottiene solo la riga della propria sessione. Per il solo nome, ci sono altri tre comandi molto vicini, ma con una differenza: whoami e id -un mostrano l'utente con cui stai lavorando ora, mentre logname mostra l'utente con cui hai fatto l'accesso. Dopo sudo -i o su, whoami risponde root, mentre logname continua a rispondere enzo (vedi l'articolo su sudo). Dove il registro delle sessioni non è disponibile (come in alcuni container), who am i e logname possono non mostrare niente o dare un errore, mentre whoami funziona sempre.
Esempio 7: da quali indirizzi ci si collega
$ who | awk '{print $NF}' | tr -d '()' | sort | uniq -c
1 192.168.1.20
1 203.0.113.45
$ who | awk '{print $1}' | sort -u
backup
enzoCon awk, sort e uniq (vedi gli articoli relativi) si estrae l'informazione che serve. Nel primo comando, $NF è l'ultimo campo di ogni riga (l'indirizzo) e tr -d '()' toglie le parentesi: il risultato è l'elenco degli indirizzi di provenienza, con il numero di sessioni. Il secondo dà i nomi degli utenti, senza ripetizioni. Utile per scoprire un accesso da un indirizzo che non conosci.
Esempio 8: chi si è collegato in passato, con last
$ last -n 3
enzo pts/0 203.0.113.45 Thu Oct 29 09:20 still logged in
backup pts/1 192.168.1.20 Thu Oct 29 08:02 still logged in
enzo pts/0 203.0.113.45 Wed Oct 28 18:41 - 19:05 (00:24)
$ sudo lastb | head -n 3who mostra solo chi c'è adesso. Per la storia degli accessi si usa last, che legge il registro /var/log/wtmp: mostra chi si è collegato, da dove, quando e per quanto tempo (00:24 è la durata di 24 minuti), con -n per limitare il numero di righe. Con sudo lastb si leggono invece i tentativi di accesso falliti (dal registro /var/log/btmp, leggibile solo da root): su un server esposto a Internet, l'elenco è di solito lungo, perché qualcuno prova continuamente password a caso.
Esempio 9: scrivere a chi è collegato, o farlo uscire
$ echo "Riavvio tra 10 minuti: salvate il lavoro" | wall
$ echo "Ciao, mi senti?" | write backup pts/1
$ sudo pkill -KILL -t pts/1
$ sudo loginctl terminate-user backupDopo aver visto chi c'è, si può agire. wall (write all) manda un messaggio a tutti gli utenti collegati; write utente terminale lo manda a uno solo (se riceve messaggi). Per chiudere una sessione si può terminare tutti i processi di quel terminale con pkill -t (vedi l'articolo su kill), oppure usare loginctl terminate-user sui sistemi con systemd. Prima di farlo, avverti sempre l'utente: potrebbe avere un lavoro non salvato.
Esempio 10: uso negli script
#!/bin/bash
AMMESSI="enzo backup"
who | awk '{print $1, $NF}' | sort -u | while read -r utente origine; do
case " $AMMESSI " in
*" $utente "*) ;;
*) echo "Accesso inatteso: $utente da $origine" ;;
esac
doneLo script elenca le sessioni aperte e segnala quelle di utenti che non sono nell'elenco degli ammessi. Il while read legge una riga alla volta, e case confronta il nome con l'elenco. Programmato con crontab ogni pochi minuti, e con l'output mandato per posta o in un registro, dà un primo avviso di accessi inattesi. Non sostituisce però un vero sistema di sicurezza.
Opzioni utili
-H: aggiunge la riga con i nomi delle colonne.-u: mostra da quanto tempo ogni utente è inattivo e il numero del processo di sessione.-q: solo i nomi e il numero totale di utenti.-b: data dell'ultimo avvio;-r: runlevel (di scarso interesse oggi).-moam i: solo la propria sessione.-a: tutte le informazioni insieme;-T: indica se l'utente accetta messaggi.w: comewho, più cosa sta facendo ciascun utente e il carico (vediuptime);users: solo i nomi su una riga.last,lastb: storia degli accessi riusciti e falliti;loginctl list-sessions: le sessioni secondosystemd.
Attenzione a
- Mostra le sessioni, non le persone: la stessa persona con tre finestre di terminale compare tre volte. Il numero di
-qconta le sessioni, non gli utenti diversi. - Non vede tutto:
wholegge il registroutmp, e non tutti i programmi lo aggiornano. Le sessioni nate dasuosudorestano associate all'utente originale, e alcune connessioni (comesshcon un comando singolo e senza terminale) non compaiono. Se il registro non è disponibile, come in molti container, l'output è vuoto anche se ci sono processi attivi. - Non è uno strumento di sicurezza: se qualcuno ha preso il controllo della macchina può modificare o cancellare i registri. Per le indagini serve confrontare più fonti (
last,journalctl,/var/log/auth.log). - Il formato della data dipende dalla lingua: con la lingua del sistema impostata normalmente la data è del tipo
2026-10-29 09:20; con la lingua "C" (quella minima, usata da alcuni script e container) diventaOct 29 09:20. Negli script, non fare affidamento sul formato della data: usa le colonne del nome e del terminale. - L'indirizzo può mancare: sulle sessioni locali non c'è la parte tra parentesi, o contiene solo il nome dello schermo grafico (
:0). Con--lookupwhoprova a risolvere il nome della macchina con il DNS, che può rallentare il comando. - Un utente inattivo non è un utente assente: una sessione ferma da ore può avere programmi in esecuzione (con
screenotmux, per esempio). Chiuderla conpkillinterrompe tutto quello che c'è dentro. - Prima di riavviare, controlla: un
whoprima direbootoshutdownè una buona abitudine su un server condiviso, e unwallcon un preavviso è la buona educazione. whoaminon èlogname: il primo dice con quale utente stai lavorando adesso (cambia consudoesu), il secondo con quale hai fatto l'accesso. Negli script di amministrazione, per sapere chi ha lanciato davvero il comando, la variabile$SUDO_USERè spesso più utile.- Gli indirizzi sono dati personali: un elenco di accessi con indirizzi e orari può identificare delle persone. Se lo condividi (in una segnalazione o in un forum), togli o sostituisci quelle informazioni.
Riepilogo
| Comando | Cosa fa |
|---|---|
who | Elenca le sessioni aperte (utente, terminale, ora, origine) |
who -H | Aggiunge le intestazioni delle colonne |
who -Hu | Aggiunge inattività e numero del processo |
who -q | Solo i nomi e il numero di sessioni |
who -b | Data e ora dell'ultimo avvio |
who am i | Solo la propria sessione |
whoami | Utente con cui stai lavorando ora |
logname | Utente con cui hai fatto l'accesso |
w | Sessioni, attività di ciascuno e carico |
last -n 10 | Ultimi 10 accessi |
sudo lastb | Tentativi di accesso falliti |
wall | Manda un messaggio a tutti gli utenti collegati |
loginctl list-sessions | Sessioni secondo systemd |