--- title: "Diagnosticar alto uso de memoria en Linux con free y smem" description: "Averigua qué consume la RAM en Ubuntu 24.04, interpreta free y /proc/meminfo, localiza procesos con smem, detecta fugas y OOM y limita servicios con systemd." category: "Guía de Solución de Problemas" language: es source: https://cubepath.com/es/docs/guía-de-solución-de-problemas/diagnostico-y-analisis-de-alto-uso-de-memoria updated: 2026-09-25 --- # Diagnosticar alto uso de memoria en Linux con free y smem En Linux es normal ver la memoria "casi llena": el kernel usa la RAM libre como caché de disco y la devuelve en cuanto una aplicación la necesita. El problema real empieza cuando la memoria disponible se agota, el sistema empieza a usar swap de forma continua o el OOM killer mata procesos. En esta guía aprenderás a distinguir ambas situaciones en Ubuntu 24.04, a localizar qué proceso o componente consume la memoria, a detectar fugas y a limitar el consumo de un servicio. ## Requisitos previos - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. En Debian 12 los comandos son los mismos. - Un usuario no root con privilegios `sudo`. - Los paquetes `sysstat` y `smem`, que instalarás en el primer paso. ## Paso 1: Instalar las herramientas `free`, `ps` y `vmstat` vienen con el sistema. `pidstat` (del paquete `sysstat`) permite seguir la memoria de un proceso a lo largo del tiempo, y `smem` calcula la memoria real de cada proceso teniendo en cuenta la memoria compartida: ```bash sudo apt update sudo apt install sysstat smem ``` ## Paso 2: Leer correctamente la salida de free Empieza siempre por `free` con unidades legibles: ```bash free -h ``` ```output total used free shared buff/cache available Mem: 3.8Gi 2.9Gi 151Mi 42Mi 1.0Gi 702Mi Swap: 2.0Gi 1.4Gi 614Mi ``` Cada columna significa lo siguiente: | Columna | Significado | |---|---| | `used` | Memoria usada por procesos y el kernel, sin contar caché | | `free` | Memoria que no se usa para nada. Suele ser baja y no es preocupante | | `shared` | Memoria compartida y ficheros en `tmpfs` (como `/dev/shm`) | | `buff/cache` | Caché de disco. El kernel la libera cuando hace falta | | `available` | Estimación de la memoria disponible para nuevas aplicaciones sin usar swap | La columna importante es `available`. En el ejemplo quedan 702 MiB de 3,8 GiB y se usan 1,4 GiB de swap: el servidor sí tiene presión de memoria. Si `free` fuera baja pero `available` alta, no habría ningún problema. ## Paso 3: Comprobar si hay presión de memoria Que haya swap usada no es grave por sí mismo: puede ser memoria que se intercambió hace días y no se ha vuelto a tocar. Lo grave es el intercambio continuo. Compruébalo con `vmstat`: ```bash vmstat 2 5 ``` ```output procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 2 3 1468212 148620 10204 982316 840 1260 2210 1480 1905 3120 18 12 38 31 1 1 4 1470100 139880 10204 979004 912 1310 2344 1532 1988 3244 16 14 36 33 1 ``` Si las columnas `si` (entrada desde swap) y `so` (salida a swap) no son cero de forma sostenida, el sistema está constantemente moviendo páginas al disco, lo que dispara el `wa` (espera de E/S) y hace que todo vaya lento. El kernel también expone la presión de memoria (PSI), que indica qué porcentaje de tiempo han estado las tareas bloqueadas esperando memoria: ```bash cat /proc/pressure/memory ``` ```output some avg10=12.40 avg60=9.85 avg300=4.12 total=184502331 full avg10=5.10 avg60=3.97 avg300=1.60 total=80213442 ``` Valores de `avg10` cercanos a cero son lo normal. Si `full` supera unos pocos puntos de forma sostenida, hay momentos en que ninguna tarea puede avanzar por falta de memoria. ## Paso 4: Encontrar los procesos que más memoria usan ### Con ps `ps` ordena los procesos por memoria residente (RSS, la RAM física que ocupan, en KiB): ```bash ps -eo pid,user,rss,%mem,etime,cmd --sort=-rss | head -10 ``` ```output PID USER RSS %MEM ELAPSED CMD 1204 mysql 1210448 30.4 6-03:12:40 /usr/sbin/mysqld 9812 www-data 184320 4.6 02:11 php-fpm: pool www 9813 www-data 182104 4.5 02:10 php-fpm: pool www ``` ### Con smem El RSS cuenta varias veces la memoria compartida: si diez procesos de PHP-FPM comparten 100 MiB de librerías, cada uno la suma en su RSS. `smem` calcula el PSS (Proportional Set Size), que reparte la memoria compartida entre los procesos que la usan, así que la suma se acerca al consumo real: ```bash sudo smem -rs pss -k | head -10 ``` Para ver el total por usuario (útil para ver cuánto ocupan en conjunto todos los workers de `www-data`): ```bash sudo smem -u -k ``` ### Por servicio Cada servicio de systemd se ejecuta en su propio cgroup, que suma la memoria de todos sus procesos (incluida la caché de sus ficheros). Para verlo ordenado por memoria: ```bash systemd-cgtop -m ``` Pulsa `q` para salir. Es la forma más rápida de saber qué servicio, y no qué proceso suelto, consume más. ## Paso 5: Revisar la memoria que no pertenece a ningún proceso A veces la suma de los procesos no explica la memoria usada. En ese caso, consulta el desglose del kernel: ```bash grep -E '^(MemTotal|MemAvailable|Cached|Shmem|AnonPages|Slab|SReclaimable|SUnreclaim|HugePages_Total|Hugepagesize):' /proc/meminfo ``` ```output MemTotal: 3995232 kB MemAvailable: 718900 kB Cached: 901224 kB AnonPages: 2410388 kB Shmem: 43104 kB Slab: 412880 kB SReclaimable: 98420 kB SUnreclaim: 314460 kB HugePages_Total: 0 Hugepagesize: 2048 kB ``` Qué revisar en cada campo: - **`AnonPages`**: memoria de las aplicaciones (heap, pilas). Debe cuadrar aproximadamente con la suma de procesos. - **`Shmem`**: memoria compartida y `tmpfs`. Si es alta, revisa qué ocupa espacio en `tmpfs` con `df -h -t tmpfs`; los ficheros en `/dev/shm` o `/run` viven en RAM. - **`SUnreclaim`**: memoria del kernel que no se puede liberar. Si crece sin parar, sospecha de un módulo o driver con fugas; `sudo slabtop -o | head -20` muestra qué caché del kernel crece. - **`HugePages_Total`**: las huge pages reservadas se descuentan de la memoria disponible aunque no se usen. ## Paso 6: Detectar eventos del OOM killer Cuando la memoria se agota del todo, el kernel elige un proceso y lo mata. Si un servicio "se cae solo", busca en el log del kernel: ```bash sudo journalctl -k | grep -iE 'out of memory|oom-kill|killed process' ``` ```output Sep 25 03:14:07 web01 kernel: Out of memory: Killed process 1204 (mysqld) total-vm:2841212kB, anon-rss:1810244kB, file-rss:0kB, shmem-rss:0kB, UID:112 pgtables:4160kB oom_score_adj:0 ``` La línea indica qué proceso murió y cuánta memoria anónima (`anon-rss`) tenía en ese momento. Recuerda que el proceso matado no siempre es el culpable: el kernel mata al que más memoria usa, que suele ser la base de datos, aunque la fuga esté en otro proceso. Para ver qué proceso sería el siguiente candidato, consulta su puntuación (a mayor valor, más probable): ```bash cat /proc/PID/oom_score ``` Si quieres proteger un servicio crítico para que el OOM killer lo elija en último lugar, añade `OOMScoreAdjust` a su unidad. Por ejemplo, para MySQL: ```bash sudo systemctl edit mysql ``` Añade en la zona editable: ```ini [Service] OOMScoreAdjust=-500 ``` Reinicia el servicio para aplicarlo: ```bash sudo systemctl restart mysql ``` ## Paso 7: Detectar fugas de memoria Una fuga se reconoce porque la memoria de un proceso crece de forma continua y nunca baja, aunque la carga sea estable. `pidstat -r` imprime el RSS de un proceso en intervalos; este ejemplo toma una muestra por minuto: ```bash pidstat -r -p PID 60 ``` ```output 11:00:00 UID PID minflt/s majflt/s VSZ RSS %MEM Command 11:01:00 33 9812 12.40 0.00 412220 184320 4.61 php-fpm8.3 11:02:00 33 9812 10.95 0.00 418364 190512 4.77 php-fpm8.3 11:03:00 33 9812 11.20 0.00 424508 196704 4.92 php-fpm8.3 ``` Déjalo en marcha un buen rato (pulsa `Ctrl+C` para parar). Un RSS que sube unos MiB por minuto sin estabilizarse es una fuga. La columna `majflt/s` (fallos de página mayores) indica que el proceso está leyendo páginas desde el disco o la swap. Mitigaciones habituales mientras se corrige el código: - **PHP-FPM**: fija `pm.max_requests = 500` en el pool para que cada worker se recicle tras 500 peticiones. - **Aplicaciones con systemd**: limita la memoria como se muestra en el paso 8 para que la fuga no afecte al resto del sistema. ## Paso 8: Limitar la memoria de un servicio systemd permite fijar límites por servicio usando cgroups v2. `MemoryHigh` frena al servicio (le obliga a liberar memoria) cuando supera el valor, y `MemoryMax` es el límite absoluto, a partir del cual el OOM killer actúa solo dentro de ese servicio. Por ejemplo, para `myapp.service`: ```bash sudo systemctl set-property myapp.service MemoryHigh=800M MemoryMax=1G ``` Comprueba que se ha aplicado y cuánta memoria usa el servicio: ```bash systemctl show myapp.service -p MemoryHigh -p MemoryMax -p MemoryCurrent ``` ```output MemoryCurrent=624902144 MemoryHigh=838860800 MemoryMax=1073741824 ``` Para contenedores Docker, el equivalente es la opción `--memory` (por ejemplo `docker run --memory=1g ...`) o `mem_limit` en Docker Compose. Revisa también la configuración de memoria de tus aplicaciones, porque muchas reservan memoria de forma fija: - **MySQL**: `innodb_buffer_pool_size` no debe superar en torno al 50-70 % de la RAM si comparte servidor con otras aplicaciones. - **PHP-FPM**: `pm.max_children` multiplicado por la memoria de cada worker (el PSS que viste con `smem`) debe caber en la RAM disponible. - **Java**: fija el heap con `-Xmx`. ## Paso 9: Añadir swap o ajustar swappiness Una pequeña swap da margen ante picos puntuales y evita que el OOM killer actúe de inmediato. No sustituye a la RAM: si el sistema intercambia continuamente, necesitas más memoria o reducir el consumo. Comprueba primero si ya tienes swap: ```bash swapon --show ``` Si no aparece nada, crea un fichero de swap de 2 GB: ```bash sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile ``` Para que se active en cada arranque, añádelo a `/etc/fstab`: ```bash echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab ``` Verifícalo: ```bash swapon --show ``` ```output NAME TYPE SIZE USED PRIO /swapfile file 2G 0B -2 ``` El parámetro `vm.swappiness` (60 por defecto) controla cuánto prefiere el kernel usar swap frente a descartar caché. En servidores con bases de datos suele bajarse a 10 para que la memoria de las aplicaciones se mantenga en RAM: ```bash echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swappiness.conf sudo sysctl --system ``` ```bash sysctl vm.swappiness ``` ```output vm.swappiness = 10 ``` ## Solución de problemas - **`free` muestra poca memoria libre pero `available` es alta**: es el comportamiento normal de Linux. No vacíes la caché con `drop_caches`: solo conseguirás que el disco trabaje más mientras la caché se vuelve a llenar. - **La memoria usada no cuadra con la suma de procesos**: revisa `Shmem`, `SUnreclaim` y `HugePages` en `/proc/meminfo` (paso 5). También puede ser la caché ARC si usas ZFS. - **`fallocate` falla al crear la swap con `Operation not supported`**: el sistema de ficheros no lo admite. Usa `sudo dd if=/dev/zero of=/swapfile bs=1M count=2048` en su lugar. - **Un servicio con `MemoryMax` se reinicia continuamente**: el límite es demasiado bajo para su carga normal. Consulta `MemoryCurrent` durante el funcionamiento normal y sube el límite con margen. ## Conclusión Ahora sabes distinguir la caché normal de una presión de memoria real, localizar qué proceso, servicio o componente del kernel consume la RAM, reconocer los eventos del OOM killer y detectar fugas. Como siguientes pasos, aplica límites `MemoryMax` a los servicios propensos a crecer, activa la recogida de `sysstat` para tener histórico con `sar -r`, y si la memoria disponible se queda corta de forma habitual, valora ampliar tu VPS a un plan con más RAM.