Un disco lleno hace que las bases de datos dejen de escribir, que los servicios no arranquen y que los logs se pierdan. El espacio no es lo único que se agota: cada archivo consume un inodo, y un sistema de archivos con millones de archivos pequeños puede quedarse sin inodos teniendo gigas libres. En este tutorial aprenderás a medir ambos recursos en Ubuntu 24.04, a encontrar qué los está consumiendo, a liberar espacio sin romper nada y a programar una comprobación periódica que avise antes de que el disco se llene.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. Los comandos de análisis funcionan igual en Debian 12 y Rocky Linux 9.
  • Un usuario no root con privilegios sudo.

Paso 1: Consultar el espacio libre con df

df muestra el tamaño, el uso y el espacio libre de cada sistema de archivos montado. Con -h las cifras salen en unidades legibles, con -T se muestra el tipo, y con -x se excluyen los sistemas de archivos virtuales que no interesan:

df -hT -x tmpfs -x devtmpfs -x squashfs -x efivarfs
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/vda1      ext4   78G   61G   14G  82% /
/dev/vda15     vfat  105M  6.1M   99M   6% /boot/efi
/dev/vdb1      ext4   98G   12G   81G  13% /datos

Fíjate en que Used más Avail no suma Size en ext4: por defecto se reserva un 5 % del disco para root, de modo que los servicios del sistema puedan seguir escribiendo cuando los usuarios llenan el disco. Un disco al 100 % para un usuario normal todavía tiene ese margen para root.

Paso 2: Consultar el uso de inodos

Con -i, df muestra inodos en lugar de bloques:

df -i -x tmpfs -x devtmpfs -x squashfs -x efivarfs
Filesystem      Inodes   IUsed   IFree IUse% Mounted on
/dev/vda1      5160960 4983211  177749   97% /
/dev/vda15           0       0       0     - /boot/efi
/dev/vdb1      6553600    1123 6552477    1% /datos

En ext4 el número de inodos se fija al crear el sistema de archivos y no puede ampliarse después. Si IUse% llega al 100 %, no se pueden crear archivos nuevos (No space left on device) aunque haya espacio libre. Los sistemas de archivos como XFS o Btrfs asignan inodos de forma dinámica, y vfat muestra un guion porque no los usa.

Para ver espacio e inodos juntos en una sola tabla, df permite elegir las columnas:

df --output=target,size,pcent,itotal,ipcent -h -x tmpfs -x devtmpfs -x squashfs -x efivarfs

Paso 3: Encontrar qué directorios ocupan más espacio

df dice cuánto se usa; du dice dónde. Este comando suma el tamaño de cada directorio del primer nivel de /, sin salir del sistema de archivos (-x), y los ordena de menor a mayor:

sudo du -xh --max-depth=1 / 2>/dev/null | sort -h
...
1.2G	/home
3.8G	/usr
54G	/var
61G	/

Repite el comando sobre el directorio más grande para bajar un nivel, por ejemplo sudo du -xh --max-depth=1 /var | sort -h, hasta dar con el culpable. Los sospechosos habituales son /var/log, /var/lib/docker, /var/lib/mysql, /var/cache/apt y los directorios de copias de seguridad.

Para buscar directamente archivos grandes, usa find. Este ejemplo lista los archivos de más de 500 MB del sistema de archivos raíz:

sudo find / -xdev -type f -size +500M -exec ls -lh {} + 2>/dev/null | sort -k5 -h

Explorar el disco de forma interactiva con ncdu

ncdu hace lo mismo que du, pero con una interfaz navegable en la terminal. Instálalo y analiza la raíz:

sudo apt install ncdu
sudo ncdu -x /

Muévete con las flechas, entra en un directorio con Enter, vuelve con la tecla izquierda y pulsa q para salir. La tecla d borra el elemento seleccionado tras pedir confirmación, así que úsala con cuidado.

Paso 4: Encontrar qué directorios consumen más inodos

Si el problema son los inodos, busca directorios con muchos archivos. du --inodes cuenta archivos en lugar de bytes:

sudo du --inodes -x --max-depth=1 / 2>/dev/null | sort -n
...
61240	/usr
4712388	/var
4983190	/

Baja nivel a nivel igual que en el paso anterior. Los orígenes típicos son directorios de sesiones de PHP (/var/lib/php/sessions), cachés de aplicaciones, colas de correo (/var/spool/postfix) y archivos temporales que una aplicación crea y nunca borra. Una vez localizado el directorio, cuenta sus archivos para confirmarlo:

sudo find /var/lib/php/sessions -xdev -type f | wc -l

Paso 5: Detectar espacio ocupado por archivos borrados

Si df indica que el disco está lleno pero du no encuentra dónde, lo más probable es que haya archivos borrados que un proceso sigue teniendo abiertos. El espacio no se libera hasta que el proceso cierra el archivo. Es típico al borrar a mano un log que un servicio sigue escribiendo. lsof +L1 lista los archivos abiertos con cero enlaces, es decir, ya borrados:

sudo lsof -nP +L1
COMMAND   PID     USER   FD   TYPE DEVICE   SIZE/OFF NLINK    NODE NAME
java     2231  appuser   4w   REG  252,1 9876543210     0  393221 /var/log/app/app.log (deleted)

La columna SIZE/OFF muestra cuánto ocupa. Para liberar el espacio, reinicia el servicio que lo mantiene abierto (en este ejemplo, el de la aplicación Java) con sudo systemctl restart nombre_servicio. Para evitarlo en el futuro, vacía los logs en lugar de borrarlos (sudo truncate -s 0 archivo.log) o, mejor, configura logrotate.

Paso 6: Liberar espacio de forma segura

Antes de borrar nada a mano, recurre a las herramientas que conocen sus propios datos. Comprueba primero cuánto ocupa cada uno.

Registro de systemd (journald). Consulta su tamaño y redúcelo a 500 MB:

journalctl --disk-usage
sudo journalctl --vacuum-size=500M

Para que no vuelva a crecer, fija el límite de forma permanente en /etc/systemd/journald.conf:

sudo nano /etc/systemd/journald.conf
[Journal]
SystemMaxUse=500M
sudo systemctl restart systemd-journald

Caché de paquetes de APT y paquetes huérfanos, incluidos kernels antiguos que ya no se usan:

sudo apt clean
sudo apt autoremove --purge

Docker, si lo usas. Muestra cuánto ocupan imágenes, contenedores, volúmenes y caché de construcción, y elimina lo que no está en uso (los volúmenes no se borran salvo que añadas --volumes):

sudo docker system df
sudo docker system prune

Logs rotados antiguos. Revisa /var/log con sudo du -h /var/log | sort -h | tail y, si un servicio genera logs enormes, ajusta su configuración en /etc/logrotate.d/ en lugar de borrarlos a mano.

Tras cada limpieza, comprueba el resultado con df -h /.

Paso 7: Programar una alerta de espacio e inodos

Revisar df a mano no escala. Este script comprueba todos los sistemas de archivos reales y escribe un aviso en el registro del sistema cuando el uso de espacio o de inodos supera un umbral (85 % por defecto). Crea el archivo:

sudo nano /usr/local/bin/disk-alert
#!/usr/bin/env bash
# Avisa en el journal cuando un sistema de archivos supera el umbral de espacio o inodos.
set -euo pipefail

threshold="${1:-85}"

df --output=pcent,ipcent,target -x tmpfs -x devtmpfs -x squashfs -x efivarfs -x overlay \
  | tail -n +2 \
  | while read -r pcent ipcent target; do
      pcent="${pcent%\%}"
      ipcent="${ipcent%\%}"
      if [[ "$pcent" =~ ^[0-9]+$ ]] && (( pcent >= threshold )); then
        logger -t disk-alert -p user.warning "Espacio en ${target} al ${pcent}% (umbral ${threshold}%)"
      fi
      if [[ "$ipcent" =~ ^[0-9]+$ ]] && (( ipcent >= threshold )); then
        logger -t disk-alert -p user.warning "Inodos en ${target} al ${ipcent}% (umbral ${threshold}%)"
      fi
    done

Hazlo ejecutable y pruébalo con un umbral del 1 % para forzar avisos:

sudo chmod 755 /usr/local/bin/disk-alert
sudo /usr/local/bin/disk-alert 1
journalctl -t disk-alert -n 5
sep 25 12:10:04 servidor disk-alert[4412]: Espacio en / al 82% (umbral 1%)
sep 25 12:10:04 servidor disk-alert[4413]: Inodos en / al 97% (umbral 1%)

Crea una unidad de servicio de systemd que ejecute el script:

sudo nano /etc/systemd/system/disk-alert.service
[Unit]
Description=Comprobar espacio en disco e inodos

[Service]
Type=oneshot
ExecStart=/usr/local/bin/disk-alert 85

Y un temporizador que lo lance cada 15 minutos:

sudo nano /etc/systemd/system/disk-alert.timer
[Unit]
Description=Comprobar espacio en disco e inodos cada 15 minutos

[Timer]
OnCalendar=*:0/15
Persistent=true

[Install]
WantedBy=timers.target

Activa el temporizador y comprueba cuándo se ejecutará:

sudo systemctl daemon-reload
sudo systemctl enable --now disk-alert.timer
systemctl list-timers disk-alert.timer
NEXT                        LEFT       LAST PASSED UNIT             ACTIVATES
Thu 2026-09-25 12:15:00 UTC 4min 10s   -    -      disk-alert.timer disk-alert.service

Los avisos quedan en el journal con la etiqueta disk-alert. Desde ahí puedes enviarlos a tu sistema de monitorización o de logs centralizados, o sustituir logger por el envío a un webhook o un correo si ya tienes uno configurado en el servidor.

Solución de problemas

No space left on device con espacio libre en df -h: se han agotado los inodos. Compruébalo con df -i y sigue el paso 4.

df y du no coinciden: hay archivos borrados que siguen abiertos (paso 5), o archivos escondidos bajo un punto de montaje, escritos en el directorio antes de montar el disco encima. Para ver estos últimos, monta la raíz en otra ruta con sudo mount --bind / /mnt y ejecuta sudo du -sh /mnt/datos; desmonta después con sudo umount /mnt.

du tarda mucho: limita el análisis a un sistema de archivos con -x y a un directorio concreto en lugar de /.

Conclusión

Ahora sabes medir el espacio y los inodos con df, localizar qué los consume con du, ncdu y find, detectar archivos borrados que siguen ocupando espacio y liberar espacio sin borrar a ciegas, además de tener una comprobación automática cada 15 minutos. Como siguientes pasos, puedes revisar la configuración de logrotate de tus servicios, mover los datos que más crecen a un disco adicional montado con fstab, o aplicar cuotas de disco si varios usuarios comparten el servidor.