--- title: "Diagnosticar alto uso de CPU con top, ps y pidstat" description: "Encuentra qué proceso consume la CPU en Ubuntu 24.04 con top, ps, pidstat, mpstat y vmstat, interpreta load average, iowait y steal, y limita el consumo." category: "Guía de Solución de Problemas" language: es source: https://cubepath.com/es/docs/guía-de-solución-de-problemas/diagnostico-de-alto-uso-de-cpu-con-top-ps-pidstat updated: 2026-09-25 --- # Diagnosticar alto uso de CPU con top, ps y pidstat Cuando un servidor responde lento, lo primero que suele mirarse es la CPU. Pero un load average alto no siempre significa que falte CPU: puede tratarse de disco lento, de un vecino ruidoso en la virtualización o de un único hilo bloqueado. En esta guía aprenderás a distinguir esos casos en Ubuntu 24.04 con `top`, `ps`, `pidstat`, `mpstat` y `vmstat`, a localizar el proceso y el código responsable, y a limitar su consumo mientras lo corriges. ## Requisitos previos - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. Los comandos funcionan igual en Debian 12. - Un usuario no root con privilegios `sudo`. - El paquete `sysstat`, que proporciona `pidstat`, `mpstat`, `iostat` y `sar`. Lo instalarás en el primer paso. ## Paso 1: Instalar sysstat `top` y `ps` vienen con el sistema, pero las herramientas que miden la CPU por proceso e intervalo están en `sysstat`: ```bash sudo apt update sudo apt install sysstat ``` Comprueba que está disponible: ```bash pidstat -V ``` ```output sysstat version 12.6.1 (C) Sebastien Godard (sysstat orange.fr) ``` ## Paso 2: Comparar la carga con el número de núcleos El load average es el número medio de tareas que están ejecutándose o esperando para ejecutarse (incluidas las que esperan al disco) en los últimos 1, 5 y 15 minutos. Por sí solo no dice nada: hay que compararlo con el número de núcleos. ```bash nproc uptime ``` ```output 4 11:02:17 up 3 days, 2:41, 1 user, load average: 9.12, 7.40, 4.05 ``` Con 4 núcleos, una carga de 9 significa que hay más del doble de trabajo del que la CPU puede atender. Estas son las pautas generales: | Carga (1 min) respecto a núcleos | Significado | |---|---| | Por debajo del número de núcleos | Hay capacidad libre | | Igual al número de núcleos | CPU al límite, sin cola | | Claramente por encima | Hay tareas esperando: el servidor irá lento | Si la carga del minuto es mucho mayor que la de 15 minutos, el problema acaba de empezar; si es al revés, ya está remitiendo. ## Paso 3: Averiguar en qué se va el tiempo de CPU Antes de buscar el proceso culpable, averigua qué tipo de consumo es. `mpstat` muestra el desglose por núcleo; este ejemplo toma 3 muestras de 2 segundos: ```bash mpstat -P ALL 2 3 ``` ```output Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle Average: all 71.30 0.00 9.85 0.40 0.00 0.62 1.10 0.00 0.00 16.73 Average: 0 98.50 0.00 1.50 0.00 0.00 0.00 0.00 0.00 0.00 0.00 Average: 1 62.10 0.00 12.40 0.50 0.00 0.80 1.60 0.00 0.00 22.60 Average: 2 61.80 0.00 13.00 0.60 0.00 0.90 1.40 0.00 0.00 22.30 Average: 3 62.80 0.00 12.50 0.50 0.00 0.80 1.40 0.00 0.00 22.00 ``` Así se interpreta cada columna relevante: | Columna | Qué mide | Si es alta | |---|---|---| | `%usr` | Código de aplicaciones | Busca el proceso en el paso 4 | | `%sys` | Código del kernel (llamadas al sistema) | Muchas llamadas al sistema, red o disco: usa `strace` en el paso 6 | | `%iowait` | CPU ociosa esperando al disco | No es un problema de CPU: revisa el disco con `iostat` | | `%soft` | Interrupciones de software, sobre todo red | Mucho tráfico de red o un posible ataque | | `%steal` | Tiempo que el hipervisor dio a otras máquinas | Contención en el host físico | En el ejemplo, el núcleo 0 está al 98 % en `%usr` mientras los demás tienen margen: es típico de un proceso de un solo hilo que no puede repartir su trabajo, como un script o una instancia de Redis. ## Paso 4: Encontrar el proceso con top Abre `top` ordenado por CPU: ```bash top -o %CPU ``` Dentro de `top`, estas teclas son las más útiles: - `1`: muestra una línea por núcleo, como `mpstat`. - `c`: alterna entre el nombre del proceso y la línea de comandos completa. - `H`: muestra hilos en lugar de procesos. - `u`: filtra por usuario (por ejemplo `www-data`). - `k`: envía una señal a un PID. - `q`: sale. Si necesitas guardar una instantánea (para un ticket de soporte o un log), usa el modo batch: ```bash top -b -n 1 -o %CPU | head -20 ``` > Nota: en `top`, un proceso puede superar el 100 %. El valor es relativo a un núcleo, así que un proceso que usa 4 núcleos completos aparece con un 400 %. ## Paso 5: Confirmar con ps y pidstat `ps` da un listado fácil de filtrar y guardar: ```bash ps -eo pid,ppid,user,%cpu,%mem,etime,cmd --sort=-%cpu | head -10 ``` ```output PID PPID USER %CPU %MEM ELAPSED CMD 21877 1 www-data 96.4 3.2 41:10 php-fpm: pool www 21880 1 www-data 88.1 3.0 41:09 php-fpm: pool www 1204 1 mysql 35.7 18.6 3-02:40:11 /usr/sbin/mysqld ``` Ten en cuenta que el `%CPU` de `ps` es la media desde que arrancó el proceso, no el consumo actual. Un proceso que lleva días en marcha y acaba de dispararse puede aparecer con un valor bajo. Para medir el consumo real en un intervalo, usa `pidstat`. Este ejemplo toma 3 muestras de 5 segundos de los procesos activos: ```bash pidstat -u 5 3 ``` ```output Average: UID PID %usr %system %guest %wait %CPU CPU Command Average: 33 21877 91.20 4.60 0.00 2.10 95.80 - php-fpm8.3 Average: 33 21880 85.40 3.20 0.00 3.00 88.60 - php-fpm8.3 Average: 112 1204 30.10 6.40 0.00 0.80 36.50 - mysqld ``` La columna `%wait` indica el tiempo que el proceso estuvo listo para ejecutarse pero esperando CPU. Si es alta en muchos procesos, la máquina se ha quedado corta de núcleos. Para un proceso con muchos hilos (Java, MySQL, Node.js con workers), ve hilo a hilo con `-t`. Sustituye `PID` por el número del proceso: ```bash pidstat -t -p PID 2 5 ``` Y para ver cambios de contexto, útiles cuando `%sys` es alto: ```bash pidstat -w -p PID 2 5 ``` Un número muy alto de cambios de contexto involuntarios (`nvcswch/s`) indica que el proceso compite por la CPU; muchos voluntarios (`cswch/s`) indican que se bloquea continuamente esperando E/S o locks. ## Paso 6: Ver la cola de ejecución con vmstat `vmstat` resume el sistema en una línea por intervalo: ```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 9 0 0 412304 88120 2310456 0 0 4 36 2210 5120 81 10 8 0 1 8 0 0 410988 88120 2310520 0 0 0 52 2305 5340 83 9 7 0 1 ``` Mira estas columnas: - `r`: procesos esperando CPU. Si se mantiene por encima del número de núcleos, falta CPU. - `b`: procesos bloqueados esperando E/S. Si es alto, el cuello de botella es el disco. - `si` y `so`: memoria que entra y sale de swap. Si no son cero de forma constante, el problema real es la memoria y la CPU se consume intercambiando páginas. - `st`: tiempo robado por el hipervisor. ## Paso 7: Investigar qué hace el proceso Una vez localizado el PID, averigua a qué servicio pertenece. `systemctl status` acepta un PID y muestra la unidad que lo gestiona: ```bash systemctl status PID ``` Para saber en qué llamadas al sistema pasa el tiempo, `strace -c` las cuenta durante unos segundos. Pulsa `Ctrl+C` para ver el resumen: ```bash sudo strace -c -f -p PID ``` ```output % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 62.14 0.412230 12 33210 read 21.07 0.139781 8 16804 1203 stat ``` > Advertencia: `strace` ralentiza mucho el proceso mientras está conectado. Úsalo solo unos segundos en producción. Si el tiempo se va en código de usuario (`%usr` alto), `perf` muestra qué funciones consumen la CPU. Instálalo con las herramientas que corresponden a tu kernel: ```bash sudo apt install linux-tools-common linux-tools-$(uname -r) sudo perf top -p PID ``` `perf top` muestra las funciones más calientes en tiempo real. En lenguajes interpretados (PHP, Python, Ruby) verás sobre todo funciones del intérprete; en esos casos es más útil el perfilador propio del lenguaje o los logs de la aplicación. Algunas causas habituales según el proceso: - **PHP-FPM**: activa el slow log del pool (`slowlog` y `request_slowlog_timeout` en `/etc/php/8.3/fpm/pool.d/www.conf`) para ver qué scripts tardan. - **MySQL**: ejecuta `SHOW FULL PROCESSLIST;` para ver las consultas en curso y activa el slow query log. - **Un proceso que no reconoces**: puede ser un minero de criptomonedas instalado tras un compromiso. Consulta la guía sobre cómo detectar si tu servidor está bajo ataque. ## Paso 8: Limitar el consumo mientras lo corriges Si no puedes arreglar la causa de inmediato, reduce el impacto sobre el resto del sistema. Baja la prioridad de un proceso en ejecución. Un valor `nice` mayor significa menos prioridad (de -20 a 19): ```bash sudo renice -n 10 -p PID ``` Para un servicio de systemd, es mejor fijar una cuota de CPU. Este ejemplo limita `myapp.service` al equivalente a medio núcleo: ```bash sudo systemctl set-property myapp.service CPUQuota=50% ``` El cambio se aplica al momento y persiste tras reiniciar. Compruébalo con: ```bash systemctl show myapp.service -p CPUQuotaPerSecUSec ``` ```output CPUQuotaPerSecUSec=500ms ``` Si el proceso está colgado en un bucle, reinicia el servicio con `sudo systemctl restart myapp`. Usa `kill -9` solo como último recurso, porque el proceso no puede cerrar ficheros ni conexiones limpiamente. ## Paso 9: Consultar el histórico con sar Muchas veces el pico ya ha pasado cuando lo investigas. `sysstat` puede guardar métricas cada 10 minutos. En Ubuntu la recogida está desactivada por defecto; actívala editando el fichero de configuración: ```bash sudo nano /etc/default/sysstat ``` Cambia la línea `ENABLED="false"` por: ```ini ENABLED="true" ``` Activa el servicio: ```bash sudo systemctl enable --now sysstat ``` A partir de ese momento, puedes consultar la CPU y la carga del día: ```bash sar -u sar -q ``` Y los de un día anterior leyendo su fichero en `/var/log/sysstat/`, donde `saDD` corresponde al día del mes (por ejemplo `sa24`): ```bash sar -u -f /var/log/sysstat/sa24 ``` ## Solución de problemas - **Load average alto pero CPU ociosa**: la carga incluye procesos en estado `D` (esperando E/S sin interrupción). Lístalos con `ps -eo state,pid,cmd | awk '$1=="D"'` y revisa el disco con `iostat -xz 2 3`. - **`%steal` por encima del 10 % de forma sostenida**: la máquina virtual no recibe toda la CPU que pide porque el host físico está ocupado. No lo puedes arreglar desde dentro del servidor; contacta con el soporte de CubePath o valora un plan con más recursos. - **`ksoftirqd` consumiendo CPU**: el kernel está procesando muchas interrupciones de red. Comprueba el tráfico con `sar -n DEV 1 5`; puede ser un pico legítimo o un ataque. - **`perf` no encuentra el paquete `linux-tools-$(uname -r)`**: estás usando un kernel sin paquete de herramientas disponible. Instala `linux-tools-generic` o actualiza al kernel más reciente de la distribución. ## Conclusión Has visto cómo pasar de un síntoma genérico ("el servidor va lento") a una causa concreta: comparar la carga con los núcleos, identificar el tipo de consumo con `mpstat`, localizar el proceso con `top` y `pidstat`, e investigarlo con `strace` y `perf`. Como siguientes pasos, deja activa la recogida de `sar` para tener histórico, configura alertas de CPU en tu sistema de monitorización y revisa también la guía de diagnóstico de alto uso de memoria, ya que la falta de memoria suele manifestarse como alto uso de CPU.