Il server dice di avere solo 800 MB di memoria libera su 8 GB: è un problema? Quasi mai. free mostra come viene usata la memoria del computer, ma per leggerlo bene bisogna sapere che in Linux "memoria libera" e "memoria disponibile" sono due cose diverse. È il comando che ti evita di spaventarti per niente, e che ti avverte quando il problema è vero.
Cos'è
free fa parte del pacchetto procps, come top e ps, ed è presente su ogni distribuzione. Non misura niente da solo: legge i dati che il kernel espone nel file /proc/meminfo e li presenta in una piccola tabella. Parla di due tipi di memoria: la RAM, veloce, e lo swap, uno spazio su disco che il sistema usa come riserva quando la RAM non basta (molto più lento).
Cosa fa
Mostra, in una tabella, il totale, la quantità usata, quella libera e quella "disponibile" della RAM e dello swap. Può ripetere la misura a intervalli regolari, mostrare i valori in unità leggibili e sommare RAM e swap.
Come si usa
$ free [opzioni]Gli esempi mostrano un server con 8 GB di memoria e 2 GB di swap, lo stesso dell'articolo su top.
Esempio 1: il comando senza opzioni
$ free
total used free shared buff/cache available
Mem: 8144384 3180100 831800 114688 4132484 4668928
Swap: 2097148 8084 2089064Senza opzioni i valori sono in kibibyte (KiB, blocchi da 1024 byte): numeri lunghi e scomodi da leggere. Nella pratica si usa quasi sempre -h, che li converte in unità comprensibili.
Esempio 2: la forma leggibile, con -h
$ free -h
total used free shared buff/cache available
Mem: 7.8Gi 3.0Gi 812Mi 112Mi 3.9Gi 4.5Gi
Swap: 2.0Gi 7.9Mi 2.0GiCon -h (human) free sceglie da solo l'unità più adatta (Mi mebibyte, Gi gibibyte). Le colonne, una per una:
total: la memoria totale installata (leggermente meno di quella nominale, perché una parte è riservata al kernel);used: la memoria occupata dai programmi e dal sistema;free: la memoria completamente inutilizzata;shared: la memoria condivisa tra processi (in particolare quella usata datmpfs, cioè i file in/tmpe/dev/shmtenuti in memoria);buff/cache: la memoria usata come cache dei dischi, per tenere in memoria i file letti di recente;available: la stima di quanta memoria i programmi possono ottenere senza usare lo swap.
Esempio 3: free contro available, il punto più importante
$ free -h
total used free shared buff/cache available
Mem: 7.8Gi 3.0Gi 812Mi 112Mi 3.9Gi 4.5Gi
$ cat grosso.log > /dev/null
$ free -h
total used free shared buff/cache available
Mem: 7.8Gi 3.0Gi 220Mi 112Mi 4.5Gi 4.5GiLinux non lascia la memoria inutilizzata: quello che non serve ai programmi lo usa come cache per i file. Nell'esempio la lettura di un file grosso (cat) fa calare free da 812 Mi a 220 Mi, e salire buff/cache di altrettanto, ma available non cambia: la cache viene restituita ai programmi non appena la chiedono. Per questo un free basso non è un problema; il valore su cui ragionare è available. Una regola pratica: se available è almeno il 10-20% del totale, la memoria è a posto; se si avvicina allo zero, no.
Esempio 4: le unità di misura
$ free -m
total used free shared buff/cache available
Mem: 7953 3105 812 112 4035 4559
Swap: 2048 7 2040
$ free -g
$ free -b
$ free -h --si
total used free shared buff/cache available
Mem: 8.3G 3.3G 852M 117M 4.2G 4.8G-m mostra i mebibyte, -g i gibibyte (arrotondando per difetto: poco utile con memorie piccole), -b i byte, -k i kibibyte. Con --si le unità sono multipli di 1000 e non di 1024 (G invece di Gi): è la differenza tra gigabyte (1.000.000.000 byte) e gibibyte (1.073.741.824 byte), e spiega perché gli stessi 8 GB si leggono come 7.8Gi o 8.3G. Con le opzioni --kilo, --mega e --giga si scelgono le unità decimali una per una.
Esempio 5: guardare l'evoluzione nel tempo
$ free -h -s 5
$ free -m -s 2 -c 3
total used free shared buff/cache available
Mem: 7953 3105 812 112 4035 4559
Swap: 2048 7 2040
total used free shared buff/cache available
Mem: 7953 3112 805 112 4035 4551
Swap: 2048 7 2040
$ watch -n 2 free -h-s N (seconds) ripete la misura ogni N secondi, finché non si preme Ctrl+C, e -c N (count) la ripete solo N volte e poi esce. Utile per vedere se used cresce nel tempo (un segnale tipico di una perdita di memoria, quando un programma non rilascia quella che non usa più). In alternativa, watch ripete qualunque comando e ridisegna lo schermo.
Esempio 6: altre viste utili
$ free -h -t
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
Total: 9.8Gi 3.0Gi 2.8Gi
$ free -m -L
SwapUse 7 CachUse 4035 MemUse 3105 MemFree 812
$ free -m -w-t (total) aggiunge una riga con la somma di RAM e swap. -L (line) mostra tutto su una sola riga, facile da elaborare con awk o da inserire in un registro. -w (wide) separa la colonna buff/cache in due, buffers (le strutture dei file system) e cache (il contenuto dei file), ma l'output diventa più largo: su uno schermo stretto va a capo. Esiste anche -v, che aggiunge la memoria "impegnata" (committed), cioè quella che i programmi hanno chiesto al sistema anche se non l'hanno ancora usata.
Esempio 7: lo swap, e quando preoccuparsi
$ swapon --show
NAME TYPE SIZE USED PRIO
/swapfile file 2G 7M -2
$ cat /proc/sys/vm/swappiness
60
$ vmstat 1 3
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 8084 831800 11676 4120808 0 0 3 9 120 210 6 2 91 0 0
0 0 8084 831800 11676 4120808 0 0 0 0 101 190 3 1 96 0 0Un po' di swap usato (qui 7 Mi) è normale: il sistema sposta lì pagine di memoria che non usa da tempo. È un problema solo se si usa molto e di continuo: in vmstat le colonne si (da disco a memoria) e so (da memoria a disco) devono restare vicine a zero. Valori alti e costanti significano che il computer sta spostando continuamente dati tra RAM e disco (thrashing) e diventa lentissimo. swappiness (da 0 a 100) dice al kernel quanto volentieri usare lo swap: 60 è il valore predefinito, e sui server di database si abbassa spesso, ma è una scelta da fare con cognizione di causa.
Esempio 8: quali programmi usano la memoria?
$ ps -eo pid,user,rss,comm --sort=-rss | head -n 4
PID USER RSS COMMAND
1034 mysql 412336 mariadbd
4410 enzo 86400 python3
925 www-data 12044 nginx
$ ps -eo rss,comm | awk 'NR>1 {m[$2]+=$1} END {for (p in m) \
printf "%d MiB %s\n", m[p]/1024, p}' | sort -nr | head -n 4
402 MiB mariadbd
118 MiB nginx
84 MiB python3
31 MiB sshdfree dice quanta memoria è usata, non da chi. Per scoprire i maggiori consumatori si usa ps ordinato per RSS (la memoria fisica occupata, in KiB), oppure top con il tasto M. Il secondo comando, con awk, somma per nome di programma: utile quando un servizio avvia molti processi (come nginx con i suoi worker, o i processi di Apache e PHP) e nessuno di per sé è grosso, ma insieme occupano molto.
Esempio 9: quando la memoria finisce davvero
$ sudo dmesg | grep -i -E 'out of memory|killed process'
[612345.678901] Out of memory: Killed process 4410 (python3) total-vm:2456000kB,
anon-rss:1820000kB, file-rss:0kB, shmem-rss:0kB, UID:1000 pgtables:3980kB oom_score_adj:0
$ journalctl -k | grep -i 'out of memory'Se la memoria e lo swap finiscono, il kernel interviene con l'OOM killer (Out Of Memory): sceglie un processo, di solito il più grosso, e lo termina per salvare il sistema. Nei registri del kernel (dmesg o journalctl -k) compare un messaggio con il nome del processo e la memoria che usava. È il motivo classico per cui "il database si è fermato da solo di notte". La cura è capire chi ha consumato la memoria, e poi aggiungere RAM o swap, limitare i processi o correggere il programma.
Esempio 10: creare un file di swap
$ sudo fallocate -l 2G /swapfile
$ sudo chmod 600 /swapfile
$ sudo mkswap /swapfile
Setting up swapspace version 1, size = 2 GiB (2147479552 bytes)
no label, UUID=3f2a5c1e-0000-0000-0000-000000000000
$ sudo swapon /swapfile
$ echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
$ free -h | grep Swap
Swap: 2.0Gi 0B 2.0GiSu un piccolo server virtuale che non ha swap, un file di swap è una rete di sicurezza contro l'OOM killer. Si crea con fallocate un file da 2 GB, lo si protegge con chmod 600 (solo root può leggerlo, perché contiene pezzi di memoria), lo si formatta con mkswap e lo si attiva con swapon. L'ultima riga lo rende permanente aggiungendolo a /etc/fstab (con tee -a, per i privilegi: vedi l'articolo su tee). Per toglierlo: sudo swapoff /swapfile, la riga di /etc/fstab e il file.
Esempio 11: i dati grezzi in /proc/meminfo
$ grep -E 'MemTotal|MemFree|MemAvailable|Cached|SwapTotal' /proc/meminfo
MemTotal: 8144384 kB
MemFree: 831800 kB
MemAvailable: 4668928 kB
Cached: 3987200 kB
SwapCached: 1204 kB
SwapTotal: 2097148 kBÈ la fonte da cui free prende i dati, ed è un normale file di testo: si può leggere con cat e filtrare con grep o awk, e contiene molte più voci (Dirty, Slab, HugePages…) di quelle che free mostra. Il campo MemAvailable è proprio quello che free mostra come available. Con -i in grep e il nome esatto si trova la voce che serve.
Esempio 12: uso negli script
$ free -m | awk '/^Mem:/ {printf "%.0f%%\n", ($2-$7)/$2*100}'
38%
#!/bin/bash
SOGLIA=10
DISP=$(free | awk '/^Mem:/ {printf "%d", $7 / $2 * 100}')
if [ "$DISP" -lt "$SOGLIA" ]; then
echo "$(date '+%F %T') memoria disponibile: ${DISP}%" >> "$HOME/memoria.log"
ps -eo pid,user,rss,comm --sort=-rss | head -n 6 >> "$HOME/memoria.log"
fiIl primo comando calcola la percentuale di memoria realmente in uso (totale meno disponibile, divisa per il totale: 38% nell'esempio). Lo script confronta la percentuale di memoria disponibile con una soglia e, se è troppo bassa, scrive nel registro l'orario e i cinque maggiori consumatori. Programmato con crontab ogni pochi minuti, permette di capire cosa è successo prima di un blocco. Si legge la colonna 7 (available) con awk: il numero di colonna dipende dalla versione di free (vedi più avanti).
Esempio 13: dentro un container o un servizio limitato
$ docker stats --no-stream
$ cat /sys/fs/cgroup/memory.max
2147483648
$ cat /sys/fs/cgroup/memory.current
412336128
$ systemctl show mio-servizio -p MemoryMax -p MemoryCurrentDentro un container Docker o in un servizio con limiti di memoria, free mostra la memoria della macchina ospite, non quella assegnata al container: il valore non è affidabile. Il limite vero si trova nei file dei cgroup (memory.max è il tetto, memory.current l'uso attuale, in byte), con docker stats per i container, o con systemctl show per i servizi di systemd. Superare il tetto fa intervenire l'OOM killer solo su quel gruppo di processi.
Opzioni utili
-h: unità leggibili (Mi, Gi);--si: multipli di 1000 invece di 1024.-b/-k/-m/-g: byte, kibibyte, mebibyte, gibibyte;--kilo/--mega/--giga: unità decimali.-s N: ripete ogni N secondi;-c N: ripete N volte e poi esce.-t: aggiunge la riga con il totale RAM + swap;-w: separabuffersecache;-L: output su una riga;-v: memoria impegnata./proc/meminfo: i dati grezzi;swapon --show,mkswap,swapon,swapoff: gestione dello swap.vmstat: movimenti di memoria e swap nel tempo;top(tasto M) eps --sort=-rss: chi usa la memoria;dmesgejournalctl -k: messaggi dell'OOM killer.
Attenzione a
- Guarda
available, nonfree: una memoria "libera" bassa è normale, perché Linux usa il resto come cache. Allarmarsi perfreebasso è l'errore più comune. - Non svuotare la cache "per liberare memoria": il comando
echo 3 | sudo tee /proc/sys/vm/drop_cachessi trova in molte guide, ma peggiora le prestazioni (i file vanno riletti dal disco) e non risolve nulla. Serve solo per misurare, in prove particolari. - Un po' di swap usato non è un guasto: preoccupati se lo swap è quasi pieno e continua a muoversi (
siesodivmstatalti), segno di una memoria insufficiente. - Le colonne cambiano con la versione: le versioni vecchie di
free(prima della 3.3.10, per esempio su CentOS 6 e Ubuntu 14.04) non hanno la colonnaavailablee mostrano la riga-/+ buffers/cache. Negli script che usanoawkcon$7, il numero di colonna può non coincidere: in caso di dubbio leggiMemAvailableda/proc/meminfo. - In un container,
freemente: mostra i numeri della macchina ospite. Per il limite reale guarda i cgroup odocker stats. - Unità: Gi non è G:
free -husa i multipli di 1024 (Gi,Mi), mentre molti fornitori di server indicano i gigabyte decimali. I numeri non coincidono, ed è normale. - La memoria totale è sempre un po' meno di quella nominale: parte è riservata al kernel, alla scheda grafica integrata e ad altri componenti. Su una VPS da 8 GB,
totalsarà di poco inferiore. sharednon è sempre quello che sembra: comprende i file ditmpfs(come/tmp, se è tenuto in memoria): se salvi file grandi lì, occupano memoria vera. Controlla condf -h /tmp /dev/shm.- Un file di swap va protetto: deve avere permessi
600(chmod 600), altrimentiswaponavvisa e altri utenti potrebbero leggere frammenti della memoria. Sui file systembtrfsezfsla creazione è diversa, e su alcune VPS lo swap è disattivato dal fornitore. - Errori in
/etc/fstab: una riga sbagliata può impedire l'avvio del sistema. Dopo la modifica, verifica consudo swapoff -a && sudo swapon -ao consudo mount -aprima di riavviare, e tieni una copia del file (vedicp). - Una perdita di memoria si vede nel tempo: un singolo
freenon basta. Controlla seusedsale di continuo, o registra i valori con uno script ecron, e se serve riavvia il servizio responsabile. - L'OOM killer sceglie da solo: può terminare un processo importante (come il database) invece di quello che ha causato il problema. Per proteggere un servizio si può regolare
oom_score_adjo impostare dei limiti di memoria consystemd, ma è meglio evitare di arrivarci con una memoria adeguata.
Riepilogo
| Comando | Cosa fa |
|---|---|
free -h | Memoria e swap in unità leggibili |
free -m | Valori in mebibyte (comodi per gli script) |
free -h -s 5 | Ripete la misura ogni 5 secondi |
free -h -t | Aggiunge il totale RAM + swap |
free -m -L | Tutto su una sola riga |
free -h --si | Unità decimali (G invece di Gi) |
swapon --show | Elenca gli spazi di swap attivi |
vmstat 1 5 | Movimenti di memoria e swap nel tempo |
ps -eo pid,user,rss,comm --sort=-rss | head | Processi che occupano più memoria |
grep MemAvailable /proc/meminfo | Memoria disponibile, dato grezzo |
sudo dmesg | grep -i 'out of memory' | Cerca gli interventi dell'OOM killer |
sudo mkswap file / sudo swapon file | Prepara e attiva un file di swap |
docker stats --no-stream | Memoria dei container |