Salta al contenuto principale

free: quanta memoria c'è davvero

Inviato da tuxsa il

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     2089064

Senza 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.0Gi

Con -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 da tmpfs, cioè i file in /tmp e /dev/shm tenuti 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.5Gi

Linux 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  0

Un 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 sshd

free 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.0Gi

Su 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"
fi

Il 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 MemoryCurrent

Dentro 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: separa buffers e cache; -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) e ps --sort=-rss: chi usa la memoria; dmesg e journalctl -k: messaggi dell'OOM killer.

Attenzione a

  • Guarda available, non free: una memoria "libera" bassa è normale, perché Linux usa il resto come cache. Allarmarsi per free basso è l'errore più comune.
  • Non svuotare la cache "per liberare memoria": il comando echo 3 | sudo tee /proc/sys/vm/drop_caches si 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 (si e so di vmstat alti), 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 colonna available e mostrano la riga -/+ buffers/cache. Negli script che usano awk con $7, il numero di colonna può non coincidere: in caso di dubbio leggi MemAvailable da /proc/meminfo.
  • In un container, free mente: mostra i numeri della macchina ospite. Per il limite reale guarda i cgroup o docker stats.
  • Unità: Gi non è G: free -h usa 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, total sarà di poco inferiore.
  • shared non è sempre quello che sembra: comprende i file di tmpfs (come /tmp, se è tenuto in memoria): se salvi file grandi lì, occupano memoria vera. Controlla con df -h /tmp /dev/shm.
  • Un file di swap va protetto: deve avere permessi 600 (chmod 600), altrimenti swapon avvisa e altri utenti potrebbero leggere frammenti della memoria. Sui file system btrfs e zfs la 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 con sudo swapoff -a && sudo swapon -a o con sudo mount -a prima di riavviare, e tieni una copia del file (vedi cp).
  • Una perdita di memoria si vede nel tempo: un singolo free non basta. Controlla se used sale di continuo, o registra i valori con uno script e cron, 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_adj o impostare dei limiti di memoria con systemd, ma è meglio evitare di arrivarci con una memoria adeguata.

Riepilogo

ComandoCosa fa
free -hMemoria e swap in unità leggibili
free -mValori in mebibyte (comodi per gli script)
free -h -s 5Ripete la misura ogni 5 secondi
free -h -tAggiunge il totale RAM + swap
free -m -LTutto su una sola riga
free -h --siUnità decimali (G invece di Gi)
swapon --showElenca gli spazi di swap attivi
vmstat 1 5Movimenti di memoria e swap nel tempo
ps -eo pid,user,rss,comm --sort=-rss | headProcessi che occupano più memoria
grep MemAvailable /proc/meminfoMemoria disponibile, dato grezzo
sudo dmesg | grep -i 'out of memory'Cerca gli interventi dell'OOM killer
sudo mkswap file / sudo swapon filePrepara e attiva un file di swap
docker stats --no-streamMemoria dei container