Guida

Processi in Linux: ps, top, htop, kill, segnali e nice

Aggiornato: · Skillaria.Top

I processi Linux si osservano con ps aux (istantanea), top e htop (elenco aggiornato con il carico). Si terminano con kill PID, che di default invia un SIGTERM gentile; kill -9 (SIGKILL) serve solo se il processo non reagisce. La priorità si imposta con nice all'avvio e con renice per un processo già in esecuzione, nell'intervallo da -20 a 19.

Ogni programma in esecuzione su Linux è un processo, con un proprio numero PID, un proprietario, uno stato e una priorità. I processi si osservano con ps, top e htop, si terminano con kill, e la loro priorità si modifica con nice e renice. Qui sotto vediamo come leggere l'output di questi comandi, quali segnali inviare e perché kill -9 non dovrebbe essere il primo riflesso.

Cos'è un processo e il PID

Un processo è un programma nel momento in cui viene eseguito: codice, memoria, file aperti e un insieme di attributi. Il kernel assegna a ogni processo un identificatore univoco, il PID, e ne registra anche il PPID, cioè il numero del processo padre che lo ha avviato. Il primo processo del sistema, con PID 1, è di solito systemd, ed è l'antenato di tutti gli altri.

Un nuovo processo nasce in due passi. Prima il padre chiama fork() e ottiene una propria copia, poi la copia chiama execve() e sostituisce il proprio codice con quello del nuovo programma. Quando nel terminale digiti ls, bash fa esattamente questo e attende la fine del figlio con wait().

$ echo $$          # PID della shell corrente
4182
$ ps -o pid,ppid,cmd -p $$
    PID    PPID CMD
   4182    4170 -bash

Come vedere i processi con ps

ps fa un'istantanea: mostra i processi nel momento in cui viene lanciato e poi termina. Senza argomenti mostra solo i processi del terminale corrente, quindi nella pratica si usa quasi sempre una di due varianti.

$ ps aux | head -5
USER       PID %CPU %MEM    VSZ   RSS TTY   STAT START   TIME COMMAND
root         1  0.0  0.3 168540 12780 ?     Ss   09:12   0:03 /sbin/init
root         2  0.0  0.0      0     0 ?     S    09:12   0:00 [kthreadd]
www-data  1532  1.2  2.1 412308 86420 ?     S    09:15   1:47 php-fpm: pool www
postgres  1610  0.4  3.8 221004 154312 ?    Ss   09:15   0:31 postgres: checkpointer

Qui a significa processi di tutti gli utenti, u formato dettagliato con il proprietario, x include i processi senza terminale (i demoni). La sintassi alternativa in stile System V è ps -ef: mostra il PPID, utile per capire chi ha avviato chi.

ColonnaSignificato
PIDidentificatore del processo
%CPU, %MEMquota di processore e di memoria fisica
VSZmemoria virtuale in KB (inclusa quella non caricata in RAM)
RSSmemoria fisica effettivamente occupata, in KB
STATstato del processo (R, S, D, Z, T) e flag
TIMEtempo di processore complessivo, non il tempo di esecuzione

Trucchi utili con ps

# top 10 per memoria
ps aux --sort=-%mem | head -11

# top 10 per processore
ps aux --sort=-%cpu | head -11

# colonne personalizzate
ps -eo pid,ppid,user,ni,stat,etime,cmd

# albero dei processi
ps -ef --forest
pstree -p

# trovare il PID dal nome
pgrep -a nginx
pidof nginx

Errore classico: cercare un processo con ps aux | grep nginx e ritrovarsi nell'output lo stesso grep. Usa pgrep oppure il trucco grep [n]ginx, che non corrisponde alla propria riga di comando.

Stati dei processi: R, S, D, Z, T

La lettera nella colonna STAT non è un dettaglio: è lo stato reale del processo. Da essa dipende come interpretare il carico e se kill servirà a qualcosa.

CodiceStatoCosa significa in pratica
RRunningin esecuzione oppure in coda per la CPU
SInterruptible sleepin attesa di un evento (rete, input, timer); è lo stato normale della maggior parte dei processi
DUninterruptible sleepin attesa di I/O dentro il kernel, i segnali non vengono consegnati
ZZombieterminato, ma il padre non ha ancora letto il suo codice di uscita
TStoppedsospeso da un segnale SIGSTOP o da Ctrl+Z

Utili anche i caratteri aggiuntivi dopo la lettera: s — leader di sessione, + — processo in primo piano nel terminale, < — priorità elevata, N — priorità ridotta, l — multithread.

Processo nello stato D

Un processo in D si trova dentro una chiamata di sistema e aspetta, ad esempio, la risposta di un disco o di un NFS bloccato. Non riceve alcun segnale, nemmeno SIGKILL. Quindi kill -9 qui è inutile: bisogna cercare la causa dell'attesa, osservando iostat, dmesg e lo stato dello storage di rete.

Processi zombie

Uno zombie è già morto: non consuma CPU né memoria, occupa solo una riga nella tabella dei processi. Non si può ucciderlo, perché è già terminato. Scompare quando il padre chiama wait(), oppure quando il padre stesso termina e lo «adotta» il PID 1.

# trovare gli zombie e i loro padri
ps -eo pid,ppid,stat,cmd | awk '$3 ~ /Z/'

Un singolo zombie è innocuo. Se ce ne sono centinaia e il numero cresce, c'è un errore nel programma padre: va corretto oppure riavviato.

top: processi e carico in tempo reale

top mostra lo stesso elenco, ma lo aggiorna ogni pochi secondi e presenta un riepilogo del sistema. È il primo comando da lanciare quando «il server rallenta».

top - 14:21:07 up 12 days,  3:02,  2 users,  load average: 1.84, 1.20, 0.95
Tasks: 213 total,   2 running, 211 sleeping,   0 stopped,   0 zombie
%Cpu(s): 23.1 us,  4.2 sy,  0.0 ni, 70.3 id,  1.9 wa,  0.0 hi,  0.5 si,  0.0 st
MiB Mem :   7821.4 total,    412.6 free,   3105.8 used,   4303.0 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   4398.2 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   1532 www-data  20   0  412308  86420  14212 R  38.2   1.1   1:47.31 php-fpm
   1610 postgres  20   0  221004 154312 148900 S   6.0   1.9   0:31.08 postgres

Nella riga %Cpu(s) la cosa più importante è: us — codice utente, sy — kernel, id — inattività, wa — attesa del disco. Un valore alto di wa con il processore libero indica chiaramente un collo di bottiglia nell'I/O.

Tasti rapidi di top

TastoAzione
P / Mordinamento per CPU / per memoria
1mostra ogni core separatamente
criga di comando completa
ufiltro per utente
kinvia un segnale a un processo
rcambia il nice del processo
Hmostra i thread
quscita

Per script e log è utile la modalità batch: top -b -n 1 | head -20 stampa un'istantanea senza interattività. Per seguire un processo specifico usa top -p 1532.

Load Average: è una coda, non una percentuale

I tre numeri del load average indicano la lunghezza media della coda negli ultimi 1, 5 e 15 minuti. In Linux vi rientrano i processi nello stato R e D, mentre il sonno normale S no. Il valore LA va confrontato con il numero di core (nproc): su 4 core, il valore 4 significa carico pieno, mentre 12 significa una coda tre volte superiore alle capacità.

Se il LA è alto ma il processore è inattivo, cerca i processi in D: ps -eo stat,pid,cmd | grep '^D'. Quasi sempre si tratta di un disco lento o di uno storage di rete.

htop: una comoda alternativa a top

htop mostra le stesse informazioni, ma con indicatori colorati per ogni core, scorrimento, supporto del mouse e albero dei processi. Di solito va installato: sudo apt install htop oppure sudo dnf install htop.

  • F3 oppure / — cerca un processo per nome;
  • F4 — filtro che lascia visibili solo le corrispondenze;
  • F5 oppure t — albero «padre — figli»;
  • F6 — scelta della colonna di ordinamento;
  • F7 / F8 — diminuisce o aumenta il nice;
  • F9 — menu dei segnali per il processo selezionato;
  • Space — seleziona più processi per un'azione di massa.

Sui server dove non si può installare nulla basta top: anche lì ci sono tutte le operazioni fondamentali.

Come terminare un processo: kill e i segnali

Il comando kill non «uccide» in senso stretto, ma invia un segnale al processo. Cosa succede dopo dipende dal segnale e da come il programma lo gestisce.

SegnaleNumeroScopo
SIGHUP1caduta del terminale; molti demoni rileggono la configurazione
SIGINT2interruzione, come Ctrl+C
SIGKILL9terminazione forzata dal kernel, non può essere intercettata
SIGTERM15richiesta di terminare in modo corretto; è il default di kill
SIGSTOP19sospende il processo, non può essere intercettato
SIGCONT18riprende un processo sospeso
SIGTSTP20sospensione dal terminale, Ctrl+Z

I numeri valgono per x86 e ARM; l'elenco completo si ottiene con kill -l. Indicare il segnale per nome è più affidabile che per numero.

kill 1532              # SIGTERM
kill -TERM 1532        # lo stesso, esplicito
kill -HUP $(pidof nginx)   # rileggere la configurazione
kill -STOP 1532; kill -CONT 1532
kill -0 1532 && echo "il processo è vivo"

Il segnale 0 non invia niente, ma verifica che il processo esista e che tu abbia il diritto di scrivergli: utile negli script.

Perché non cominciare da kill -9

SIGTERM dà al programma la possibilità di chiudere i file, svuotare i buffer, rimuovere i file di lock e completare correttamente le transazioni. SIGKILL interrompe tutto all'istante: i dati non scritti vanno persi, i file temporanei restano, e un database può entrare in ripristino al successivo avvio.

La sequenza corretta è questa:

  1. Invia kill PID (SIGTERM).
  2. Attendi 5–30 secondi, controllando con kill -0 PID.
  3. Solo se il processo è ancora vivo e non è nello stato D — kill -9 PID.

Per i servizi gestiti da systemd è meglio non toccare il PID a mano: systemctl stop invia da solo SIGTERM, attende il timeout e poi ricorre a SIGKILL.

pkill e killall: per nome

pkill -f "python worker.py"   # per riga di comando completa
pkill -u alice                 # tutti i processi dell'utente
killall -TERM node             # tutti i processi chiamati node
pgrep -l -f worker             # prima verifica cosa verrà colpito

Prima di un pkill di massa esegui sempre pgrep con lo stesso pattern: -f corrisponde a qualsiasi parte della riga di comando e può facilmente colpire processi non voluti.

I segnali si possono inviare solo ai propri processi; per quelli altrui serve sudo. L'errore Operation not permitted significa proprio questo.

Priorità dei processi: nice e renice

Il valore nice indica allo scheduler quanto un processo debba cedere il passo agli altri per il processore. L'intervallo va da -20 (priorità massima) a 19 (cede a tutti), il valore predefinito è 0. In top compare nella colonna NI, mentre PR è la priorità interna derivata.

# avviare un'attività pesante con priorità ridotta
nice -n 10 tar czf backup.tar.gz /var/www

# abbassare la priorità di un processo in esecuzione
renice -n 15 -p 1532

# alzare la priorità (solo root)
sudo renice -n -5 -p 1610

# tutti i processi di un utente
sudo renice -n 10 -u alice

Un utente normale può solo abbassare la priorità dei propri processi; i valori negativi sono riservati a root. È importante conoscere il limite di nice: incide solo sulla CPU. Se un'attività rallenta il sistema tramite il disco, usa ionice -c3 comando — classe idle, che riceve il disco solo quando nessun altro lo richiede.

Processi in background e job della shell

Un comando si può avviare in background aggiungendo &, oppure sospendere con Ctrl+Z. La shell tiene un elenco di job, gestiti con i comandi interni.

$ long_task &
[1] 5120
$ jobs
[1]+  Running    long_task &
$ fg %1        # riportare in primo piano
^Z             # sospendere (SIGTSTP)
$ bg %1        # proseguire in background

Chiudendo il terminale, la shell invia SIGHUP ai job, che terminano. Per far sopravvivere il processo all'uscita, avvialo con nohup comando &, staccalo con disown oppure usa tmux. Per un'attività permanente è meglio trasformarla in un servizio systemd.

Scenari tipici di diagnostica

Chi consuma il processore

top -o %CPU            # oppure P dentro top
ps -eo pid,user,%cpu,etime,cmd --sort=-%cpu | head

Se un processo consuma CPU senza motivo, abbassagli prima la priorità con renice: è un'operazione sicura e lascia il tempo di capire cosa succede.

Chi occupa una porta

sudo ss -ltnp | grep :8080
sudo lsof -i :8080

L'output riporta il PID, e da lì in /proc/PID/ si trovano l'eseguibile (exe), la directory di lavoro (cwd) e gli argomenti (cmdline).

Il processo è sparito all'improvviso

Una causa frequente è l'OOM Killer, che termina i processi quando la memoria si esaurisce. Verifica con dmesg -T | grep -i oom oppure journalctl -k | grep -i "killed process".

Conclusioni

Per lavorare con i processi su Linux bastano pochi comandi: ps aux per un'istantanea, top e htop per il monitoraggio, kill con il segnale giusto per terminare e nice/renice per le priorità. Osserva lo stato del processo prima di agire: gli zombie e i processi in D non si risolvono con i segnali. E inizia sempre con SIGTERM, lasciando kill -9 per i casi estremi. Processi, memoria, load average e chiamate di sistema sono trattati in modo approfondito, con esempi pratici, nel corso Linux.

Domande frequenti

Qual è la differenza tra ps aux e ps -ef?

Sono due sintassi dello stesso comando: aux è lo stile BSD con le colonne %CPU, %MEM e STAT, -ef è lo stile System V con la colonna PPID. In entrambi i casi l'elenco dei processi è lo stesso, cioè tutti i processi del sistema.

Come faccio a sapere quanti processi sono in esecuzione nel sistema?

Il modo più semplice è guardare la riga Tasks in top oppure eseguire ps -e --no-headers | wc -l. Il numero dei thread si ottiene con ps -eLf --no-headers | wc -l.

Perché un processo non termina nemmeno con kill -9?

O è nello stato D e attende l'I/O nel kernel, oppure è uno zombie già terminato. Nel primo caso cerca il problema sul disco o sullo storage di rete, nel secondo correggi o riavvia il processo padre.

Cosa succede se termino il processo con PID 1?

Il kernel protegge init: i segnali ordinari, incluso SIGKILL inviato da un utente, non gli vengono consegnati se non li gestisce. Se però init dovesse terminare, il sistema andrebbe in kernel panic.

Come limito la memoria usata da un processo?

Per un servizio systemd imposta MemoryMax= nel file unit; per un'esecuzione occasionale usa systemd-run --scope -p MemoryMax=500M comando. Funziona tramite i cgroup ed è più affidabile del vecchio ulimit -v.

Impara l’argomento in video

Questo argomento è trattato in modo approfondito, con pratica, nel corso «Linux: с нуля до уверенного администрирования».

Vai al corso