Guías · Nivel 2

Ubuntu Server: un disco lleno, journald, logrotate, kernels antiguos y un servicio que no arranca

Encontrar qué llena el disco con df, du y ncdu, poner límite al journal, rotar los logs de una aplicación con logrotate, limpiar la caché de apt y los kernels antiguos, leer systemctl status y journalctl -u, ajustar un servicio con systemctl edit y su política de reinicio, y el ticket de la aplicación que dejó de escribir logs.

¿Prefieres practicarlo?Resuelve el ticket simulado «502 Bad Gateway: la aplicación de fichajes no funciona» en SysAdmin Desks ↗

Qué vas a conseguir

Saber en cinco minutos qué está llenando un Ubuntu Server y liberar espacio sin borrar lo que no toca; dejar el journal y los logs de las aplicaciones con un tamaño máximo para que no vuelva a pasar; y, cuando un servicio no arranca, leer lo que systemd dice de él, corregir su unidad sin tocar el fichero del paquete y darle una política de reinicio sensata.

Antes de empezar

  • Ubuntu Server 22.04 o 24.04 LTS y un usuario con sudo.
  • El nombre del servicio de la aplicación (aquí, contoso-api.service) y dónde escribe sus logs (/var/log/contoso-api/).
  • ncdu instalado (sudo apt install ncdu). Si el disco está al 100 %, puede que ni apt funcione: los pasos 1 y 2 se hacen con lo que ya trae el sistema.

1. Qué está lleno: df, du y ncdu

bash · srv-app-02
df -h -x tmpfs -x squashfsFilesystem                         Size  Used Avail Use% Mounted on/dev/mapper/ubuntu--vg-ubuntu--lv   48G   48G     0 100% //dev/sda2                          2.0G  1.6G  248M  87% /bootdf -i /Filesystem                        Inodes  IUsed   IFree IUse% Mounted on/dev/mapper/ubuntu--vg-ubuntu--lv 3.1M    212K    2.9M    7% /sudo du -xh --max-depth=1 /var 2>/dev/null | sort -h | tail -n 41.2G    /var/cache3.9G    /var/lib41G     /var/log46G     /var
  • df -h dice qué sistema de ficheros está lleno; df -i, si lo que se ha acabado son los inodos (millones de ficheros pequeños, como sesiones o colas de correo). Con los inodos al 100 % hay espacio libre y aun así no se puede crear ningún fichero.
  • du -x no cruza a otros sistemas de ficheros: así no cuentas un recurso NFS montado debajo. Baja nivel a nivel (/var, luego /var/log) hasta dar con el culpable.
  • sudo ncdu -x / hace lo mismo de forma interactiva: flechas para entrar, d para borrar. Úsalo para mirar, y borra con cabeza.
  • En ext4, el 5 % del disco está reservado para root. Por eso los servicios que corren con su propio usuario fallan primero, mientras root aún puede escribir.

Un fichero borrado que un proceso tiene abierto no libera espacio hasta que el proceso lo cierra. Si df no baja después de un rm, sudo lsof +L1 lista esos ficheros. Para vaciar un log en uso, se trunca (sudo truncate -s 0 fichero.log), no se borra.

2. El journal de systemd

bash · srv-app-02
journalctl --disk-usageArchived and active journals take up 3.9G in the file system.sudo journalctl --vacuum-size=500MVacuuming done, freed 3.4G of archived journals from /var/log/journal/4c1f0e8a7d2b4e0f9a3c5d6e7f8a9b0c.sudo journalctl --vacuum-time=2weeks

--vacuum-size y --vacuum-time solo borran ficheros archivados; para que el límite sea permanente, un fichero propio en journald.conf.d:

/etc/systemd/journald.conf.d/10-tamano.conf
[Journal]SystemMaxUse=500MSystemKeepFree=2G

sudo systemctl restart systemd-journald lo aplica. Por defecto el journal puede ocupar el 10 % del sistema de ficheros, con un máximo de 4 GB: en un disco de 40 GB son 4 GB de logs del sistema.

3. Los logs de la aplicación con logrotate

journald no rota los ficheros que una aplicación escribe por su cuenta. Para eso, un fichero en /etc/logrotate.d/:

/etc/logrotate.d/contoso-api
/var/log/contoso-api/*.log {    daily    rotate 14    maxsize 500M    compress    delaycompress    missingok    notifempty    su contoso contoso    create 0640 contoso contoso    postrotate        systemctl kill -s HUP contoso-api.service    endscript}
  • rotate 14 guarda 14 ficheros; compress los comprime y delaycompress deja sin comprimir el más reciente, por si la aplicación aún escribe en él.
  • su hace falta cuando la carpeta pertenece al usuario de la aplicación; sin él, logrotate se niega con parent directory has insecure permissions.
  • postrotate avisa a la aplicación para que reabra el fichero. Si no sabe hacerlo, cambia create y el bloque postrotate por copytruncate: copia y vacía el fichero en su sitio, y puede perder las líneas escritas en ese instante.
  • En Ubuntu, logrotate lo lanza logrotate.timer una vez al día. maxsize solo se comprueba en cada ejecución: si la aplicación puede escribir gigas en unas horas, toca ejecutarlo más a menudo.
bash · probar la configuración
sudo logrotate -d /etc/logrotate.d/contoso-apisudo logrotate -f /etc/logrotate.d/contoso-apisystemctl list-timers logrotate.timer

-d simula y explica lo que haría sin tocar nada; -f fuerza una rotación ahora.

4. La caché de apt y los kernels antiguos

bash · srv-app-02
uname -r6.8.0-87-genericdpkg --list 'linux-image-[0-9]*' | awk '/^ii/{print $2}'linux-image-6.8.0-79-genericlinux-image-6.8.0-84-genericlinux-image-6.8.0-87-genericsudo apt cleansudo apt autoremove --purge
  • apt clean vacía /var/cache/apt/archives/, los paquetes ya instalados.
  • apt autoremove --purge quita los kernels que ya no hacen falta: conserva el que está en uso y el anterior, como vuelta atrás. Es lo que libera /boot cuando una actualización falla por falta de espacio. Nunca borres a mano el kernel que muestra uname -r.
  • Si el servidor usa snaps, sudo snap set system refresh.retain=2 limita a dos las versiones guardadas de cada uno.

5. Un servicio: systemctl status y journalctl -u

bash · srv-app-02
systemctl status contoso-api --no-pager× contoso-api.service - Contoso API de facturas     Loaded: loaded (/etc/systemd/system/contoso-api.service; enabled; preset: enabled)     Active: failed (Result: start-limit-hit) since Mon 2026-11-02 08:14:03 CET; 3min ago    Process: 2311 ExecStart=/opt/contoso-api/bin/contoso-api (code=exited, status=1/FAILURE)   Main PID: 2311 (code=exited, status=1/FAILURE)journalctl -u contoso-api -b -n 20 --no-pagerjournalctl -u contoso-api --since "08:00" -p err
  • Loaded dice dónde está el fichero de la unidad y si arranca con el sistema (enabled). Active dice cómo terminó: exit-code, oom-kill, timeout o start-limit-hit.
  • journalctl -u filtra por unidad; -b, desde el último arranque; -p err, solo errores; -f, en directo mientras lo arrancas en otra ventana.
  • systemctl cat contoso-api muestra la unidad completa, con los ficheros que la modifican.

6. Ajustar la unidad con systemctl edit y la política de reinicio

El fichero de la unidad lo instala el paquete o el equipo de la aplicación. Los cambios propios van en un fichero aparte, que sobrevive a las actualizaciones:

bash · sudo systemctl edit contoso-api
[Unit]StartLimitIntervalSec=300StartLimitBurst=5 [Service]Restart=on-failureRestartSec=10
  • systemctl edit crea /etc/systemd/system/contoso-api.service.d/override.conf y recarga systemd al guardar. systemctl revert contoso-api lo deshace.
  • Restart=on-failure vuelve a arrancar el servicio si muere con error, pero no si alguien lo para con systemctl stop. RestartSec es la espera entre intentos.
  • StartLimitBurst y StartLimitIntervalSec (en [Unit]) ponen el tope: más de 5 arranques en 300 segundos y systemd deja de intentarlo con start-limit-hit. Sin tope, un servicio roto se reinicia en bucle y llena el journal.

7. El ticket: "la aplicación ha dejado de escribir logs y el servicio no arranca"

Lunes, 8:20. Administración no puede emitir facturas. El equipo de la aplicación dice que el último log es del domingo a las 23:47 y que el servicio no levanta.

  1. El estado: systemctl status contoso-api dice failed (Result: start-limit-hit). Ese resultado no es la causa: es systemd diciendo que dejó de intentarlo.
  2. La causa, en el journal:
bash · journalctl -u contoso-api
journalctl -u contoso-api -b --no-pager | tail -n 4nov 02 08:13:52 srv-app-02 contoso-api[2311]: FATAL cannot open /var/log/contoso-api/app.log: No space left on devicenov 02 08:13:52 srv-app-02 systemd[1]: contoso-api.service: Main process exited, code=exited, status=1/FAILUREnov 02 08:14:03 srv-app-02 systemd[1]: contoso-api.service: Start request repeated too quickly.nov 02 08:14:03 srv-app-02 systemd[1]: contoso-api.service: Failed with result 'start-limit-hit'.
  1. El disco: df -h / al 100 % y du lleva a /var/log/contoso-api/app.log, de 38 GB. La aplicación cambió el nivel de log a debug en el despliegue del viernes y no había ninguna regla de logrotate para esa carpeta.
  2. Liberar espacio sin perder la evidencia: guardar las últimas líneas (sudo tail -n 5000 app.log > /root/app-tail.log), truncar el fichero (sudo truncate -s 0 /var/log/contoso-api/app.log) y vaciar lo archivado del journal (journalctl --vacuum-size=500M). Comprobar que df baja; si no baja, lsof +L1.
  3. Arrancar: después de un start-limit-hit, systemd no deja arrancar hasta reiniciar el contador:
bash · srv-app-02
sudo systemctl reset-failed contoso-apisudo systemctl start contoso-apisystemctl is-active contoso-apiactivecurl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/health200
  1. Que no se repita: la regla de logrotate del apartado 3, el límite del journal del apartado 2, el nivel de log devuelto a info por el equipo de la aplicación y una alerta de disco al 80 % en la monitorización.

En el ticket: sistema de ficheros y uso antes y después, qué fichero lo llenó y por qué, qué se truncó y qué se guardó, y las dos reglas nuevas.

Siguientes pasos

¿Quieres practicarlo? Resuelve el ticket «502 Bad Gateway: la aplicación de fichajes no funciona» en SysAdmin Desks, gratis y en el navegador.

¿Falta algo o en tu entorno es distinto? Escríbeme y lo corrijo.

Tech Career Lab · newsletter

¿Te ha servido? Cada dos semanas envío una idea práctica para perfiles IT: LinkedIn, proyectos, networking y procesos de selección.

Apúntate y llévate las 33 ideas →