ps mostra quali programmi sono in esecuzione sul sistema in questo momento, e kill permette di intervenire su di essi, per esempio fermando uno che non risponde più. Insieme sono lo strumento di base per capire "cosa sta girando" e "come lo chiudo" quando un programma si blocca.
Prima di cominciare: cos'è un processo
Un processo è un programma in esecuzione. Ogni processo ha:
- un PID (process id), il numero che lo identifica, assegnato dal sistema all'avvio;
- un PPID, il PID del processo "genitore" che lo ha avviato: i processi formano un albero, e il capostipite è il processo con PID 1 (di solito
systemd); - un proprietario, cioè l'utente con i cui permessi sta girando.
Anche la shell in cui scrivi i comandi è un processo, e ogni comando che lanci diventa un suo "figlio".
Cos'è
ps è l'abbreviazione di process status, "stato dei processi". Fa parte del pacchetto procps (nella versione procps-ng) ed è un eseguibile (/usr/bin/ps).
kill è invece un nome ingannevole: serve a inviare un segnale a un processo, e "uccidere" è solo il caso più comune. Esiste in due versioni, come comando interno di Bash e come eseguibile (/usr/bin/kill, sempre da procps), con un comportamento praticamente identico.
Cosa fanno
psstampa una fotografia dei processi nell'istante in cui lo lanci: non si aggiorna da solo. Per un elenco che si aggiorna di continuo esistonotopehtop.killinvia un segnale al processo di cui indichi il PID. Il segnale di default è SIGTERM, una richiesta cortese di terminare: il programma può salvare i dati, chiudere i file e uscire in modo ordinato.
Come si usano
$ ps [opzioni]
$ kill [-segnale] PID...Esempio 1: ps senza opzioni
$ ps
PID TTY TIME CMD
2841 pts/0 00:00:00 bash
3120 pts/0 00:00:00 psSenza opzioni mostra solo i processi dell'utente e del terminale correnti: qui la shell (bash) e lo stesso ps. La colonna TIME è il tempo di processore consumato, non il tempo trascorso.
Esempio 2: tutti i processi del sistema con ps aux
$ ps aux | head -n 4
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 168940 13120 ? Ss 06:58 0:03 /sbin/init
root 2 0.0 0.0 0 0 ? S 06:58 0:00 [kthreadd]
enzo 2841 0.0 0.1 10220 5280 pts/0 Ss 07:02 0:00 -bashLa forma ps aux (senza trattino) mostra tutti i processi di tutti gli utenti. Le colonne principali:
| Colonna | Significato |
|---|---|
USER | Proprietario del processo |
PID | Identificativo del processo |
%CPU | Uso del processore (media sull'intera vita del processo, non il valore istantaneo) |
%MEM | Percentuale di memoria fisica usata |
VSZ / RSS | Memoria virtuale / memoria fisica occupata, in kibibyte |
TTY | Terminale di controllo (? significa nessuno: tipico dei servizi) |
STAT | Stato del processo (vedi sotto) |
START / TIME | Quando è partito / tempo di processore consumato |
COMMAND | Il comando con cui è stato avviato; tra parentesi quadre i processi del kernel |
Esempio 3: la forma alternativa ps -ef
$ ps -ef | head -n 4
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 06:58 ? 00:00:03 /sbin/init
root 2 0 0 06:58 ? 00:00:00 [kthreadd]
enzo 2841 2830 0 07:02 pts/0 00:00:00 -bashps -ef (con il trattino) mostra gli stessi processi ma con la colonna PPID, il genitore. Sono due stili storici (BSD e UNIX) che ps accetta entrambi: ps aux e ps -ef sono le due forme da ricordare.
Esempio 4: lo stato di un processo (colonna STAT)
| Lettera | Stato |
|---|---|
R | In esecuzione (running) |
S | In attesa di un evento, interrompibile (il caso più comune) |
D | In attesa, non interrompibile (di solito operazioni su disco o rete) |
T | Fermato (per esempio con Ctrl+Z) |
Z | Zombie: terminato, ma il genitore non ne ha ancora raccolto l'uscita |
Dopo la lettera principale possono comparire dei simboli: s (capo di una sessione), l (più thread), + (in primo piano sul terminale), < e N (priorità alta o bassa).
Esempio 5: cercare un processo per nome
$ ps aux | grep nginx
root 1320 0.0 0.1 ... nginx: master process /usr/sbin/nginx
www-data 1321 0.0 0.1 ... nginx: worker process
enzo 3402 0.0 0.0 ... grep --color=auto nginxL'ultima riga è lo stesso grep, che compare perché la parola "nginx" è nella sua riga di comando. Per evitarlo ci sono due strade. La prima è il trucco delle parentesi quadre, che fa sì che il testo cercato non corrisponda alla riga di grep:
$ ps aux | grep [n]ginxLa seconda, più semplice, è pgrep, pensato proprio per questo:
$ pgrep nginx
1320
1321
$ pgrep -a nginx # mostra anche il comando completo
$ pgrep -u mario firefox # solo i processi dell'utente mario
$ pidof nginx # tutti i PID su una rigaEsempio 6: scegliere le colonne e ordinare
$ ps -eo pid,user,%mem,%cpu,comm --sort=-%mem | head -n 4
PID USER %MEM %CPU COMMAND
3310 enzo 8.4 2.1 firefox
1520 mysql 4.2 0.3 mysqld
1180 www-data 1.9 0.0 php-fpm8.3Con -eo (tutti i processi, colonne a scelta) indichi tu quali campi mostrare, e con --sort l'ordine: il segno - davanti alla colonna significa "dal più grande". È il modo rapido per scoprire quali processi occupano più memoria (--sort=-%mem) o più processore (--sort=-%cpu).
Esempio 7: l'albero dei processi
$ ps -ef --forest
...
root 1320 1 0 06:58 ? 00:00:00 /usr/sbin/nginx
www-data 1321 1320 0 06:58 ? 00:00:00 \_ nginx: worker process
www-data 1322 1320 0 06:58 ? 00:00:00 \_ nginx: worker processCon --forest i processi figli sono mostrati sotto il genitore. Esiste anche pstree, che disegna lo stesso albero in forma più compatta.
Esempio 8: un processo preciso
$ ps -p 2841
$ ps -fp 2841 # con più dettagli (compreso il genitore)
$ ps -u enzo # tutti i processi dell'utente enzoEsempio 9: fermare un processo con kill
Lanciamo un processo di prova che dorme per cinque minuti, tenuto in secondo piano:
$ sleep 300 &
[1] 4021
$ ps -p 4021
PID TTY TIME CMD
4021 pts/0 00:00:00 sleep
$ kill 4021
[1]+ Terminato sleep 300Il numero tra parentesi quadre è il numero di job della shell, il secondo è il PID. Il processo ha ricevuto SIGTERM e si è chiuso. Per i processi lanciati dalla stessa shell si può usare anche il numero di job con il segno di percentuale: kill %1.
Esempio 10: i segnali
Il comando kill -l elenca tutti i segnali disponibili. I più utili:
| Numero | Nome | Effetto |
|---|---|---|
| 15 | SIGTERM | Richiesta di terminare: è il segnale di default, il processo può chiudersi in modo ordinato |
| 9 | SIGKILL | Terminazione immediata, eseguita dal kernel: il processo non può né intercettarla né ignorarla |
| 2 | SIGINT | Interruzione: lo stesso segnale di Ctrl+C |
| 1 | SIGHUP | "Riaggancio": molti servizi lo interpretano come "rileggi la configurazione" |
| 19 | SIGSTOP | Sospende il processo, senza possibilità di ignorare il segnale |
| 18 | SIGCONT | Riprende un processo sospeso |
Il segnale si indica per numero o per nome, con o senza il prefisso SIG; le forme seguenti sono equivalenti:
$ kill -9 4021
$ kill -KILL 4021
$ kill -SIGKILL 4021Esempio 11: prima con le buone, poi con le cattive
La regola è partire sempre da kill PID (SIGTERM) e usare kill -9 solo se il processo non risponde dopo qualche secondo:
$ kill 4021
$ ps -p 4021 # c'è ancora?
$ kill -9 4021 # ultima risorsaCon SIGKILL il programma non ha modo di salvare nulla né di ripulire dopo di sé: file temporanei, file di blocco e dati non scritti possono restare in uno stato incoerente.
Esempio 12: sospendere e riprendere un processo
$ kill -STOP 4021 # il processo si ferma
$ kill -CONT 4021 # riprende da dove eraÈ utile, per esempio, per liberare temporaneamente il processore da un'elaborazione pesante senza perderne il lavoro fatto.
Esempio 13: fermare per nome con pkill e killall
$ pkill firefox # invia SIGTERM ai processi che corrispondono a "firefox"
$ pkill -u mario # tutti i processi dell'utente mario
$ pkill -f "backup.py" # cerca nella riga di comando completa
$ killall firefox # per nome esattoSono comodi, ma possono colpire più processi di quelli che pensi. Prima di usare pkill, controlla con lo stesso criterio cosa verrebbe colpito:
$ pgrep -a -f "backup.py"
$ pkill -f "backup.py"Con pgrep e pkill i criteri di ricerca sono gli stessi, e pgrep -a mostra a colpo d'occhio chi verrebbe fermato.
Esempio 14: i processi degli altri utenti
Un utente normale può inviare segnali solo ai propri processi. Per gli altri serve sudo:
$ kill 1320
bash: kill: (1320) - Operazione non permessa
$ sudo kill 1320Esempio 15: uso negli script
Uno script che ferma un programma in modo ordinato e, se non risponde, lo forza:
#!/bin/bash
PID=$(pgrep -o -f "miascript.py")
[ -n "$PID" ] || { echo "Processo non in esecuzione"; exit 1; }
kill "$PID"
sleep 5
if kill -0 "$PID" 2>/dev/null; then
echo "Non risponde, forzo la chiusura"
kill -9 "$PID"
else
echo "Terminato correttamente"
fiCon pgrep -o si prende il processo più vecchio tra quelli trovati. Il segnale speciale 0 non fa nulla al processo: kill -0 serve solo a verificare se esiste ancora (restituisce successo se sì, errore se no).
Opzioni utili
Per ps:
ps auxeps -ef: tutti i processi del sistema, nei due formati classici.-p PID: un processo preciso;-u utente: i processi di un utente.-eo colonne: sceglie le colonne (pid,ppid,user,%cpu,%mem,etime,comm,cmd...).--sort=-%mem: ordina in base a una colonna; il segno-inverte l'ordine.--forest: mostra l'albero genitore-figlio.-w: non taglia le righe lunghe alla larghezza dello schermo.
Per kill, pkill e pgrep:
kill -l: elenca i segnali.kill -SEGNALE PID: invia il segnale indicato (per numero o per nome).pgrep -a modello: elenca i processi con il comando completo;pgrep -f: cerca nell'intera riga di comando.pkill -u utente modello: limita la ricerca ai processi di un utente.
Attenzione a
- Prima SIGTERM, poi SIGKILL:
kill -9dovrebbe essere l'ultima risorsa, non l'abitudine. Toglie al programma ogni possibilità di chiudersi in modo ordinato. - Controlla il PID: con
ps -p PIDverifica che sia davvero il processo che intendi fermare. Un PID digitato male può colpire un altro programma, magari uno importante. pkillekillallsono ampi:pkill pythonferma tutti i programmi Python, non solo il tuo. Anteponi semprepgrep -acon lo stesso criterio. Su alcuni sistemi Unix commerciali, inoltre,killallha tutt'altro significato (termina tutti i processi): su Linux non succede, ma conviene saperlo.- I processi in stato
D(attesa non interrompibile) non reagiscono nemmeno akill -9finché l'operazione su disco o rete non si sblocca. Spesso il vero problema è l'unità o la connessione. - Gli zombie (
Z) sono già terminati: non occupano risorse, se non una riga nella tabella dei processi, e non si possono "uccidere". Se ne accumulano, bisogna fermare o riavviare il processo genitore (colonna PPID). - I servizi vanno gestiti dal loro gestore: se un servizio è controllato da
systemd, fermalo consudo systemctl stop nomeservizio. Un semplicekillpotrebbe far sì chesystemdlo riavvii subito. - Il genitore e i figli: terminare un genitore non sempre termina i figli. Guarda l'albero con
ps -ef --forestprima di decidere. - Segnali verso processi di sistema:
kill -9 -1invia SIGKILL a tutti i tuoi processi, comprese la sessione grafica e il terminale. Non provarlo per curiosità. - I numeri di PID vengono riusati: se tieni il PID di un processo per molto tempo (per esempio in un file), controlla che appartenga ancora allo stesso programma prima di inviargli un segnale.
- %CPU in
psnon è istantaneo: è la media dall'avvio del processo. Per vedere cosa sta consumando adesso usatopohtop.
Riepilogo
| Comando | Cosa fa |
|---|---|
ps | Processi del terminale corrente |
ps aux | Tutti i processi, con utente, CPU e memoria |
ps -ef | Tutti i processi, con il PID del genitore |
ps -ef --forest | Albero dei processi |
ps aux --sort=-%mem | head | I processi che usano più memoria |
ps -p PID | Un processo preciso |
pgrep -a nome | Cerca i processi per nome |
kill PID | Chiede al processo di terminare (SIGTERM) |
kill -9 PID | Termina subito il processo (SIGKILL) |
kill -STOP PID / kill -CONT PID | Sospende / riprende un processo |
kill -l | Elenca i segnali |
pkill nome | Invia un segnale ai processi con quel nome |
kill -0 PID | Verifica se il processo esiste ancora |