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/). ncduinstalado (sudo apt install ncdu). Si el disco está al 100 %, puede que niaptfuncione: los pasos 1 y 2 se hacen con lo que ya trae el sistema.
1. Qué está lleno: df, du y ncdu
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 /vardf -hdice 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 -xno 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,dpara 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
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:
[Journal]SystemMaxUse=500MSystemKeepFree=2Gsudo 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/:
/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 14guarda 14 ficheros;compresslos comprime ydelaycompressdeja sin comprimir el más reciente, por si la aplicación aún escribe en él.suhace falta cuando la carpeta pertenece al usuario de la aplicación; sin él, logrotate se niega con parent directory has insecure permissions.postrotateavisa a la aplicación para que reabra el fichero. Si no sabe hacerlo, cambiacreatey el bloquepostrotateporcopytruncate: 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.timeruna vez al día.maxsizesolo se comprueba en cada ejecución: si la aplicación puede escribir gigas en unas horas, toca ejecutarlo más a menudo.
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
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 --purgeapt cleanvacía/var/cache/apt/archives/, los paquetes ya instalados.apt autoremove --purgequita los kernels que ya no hacen falta: conserva el que está en uso y el anterior, como vuelta atrás. Es lo que libera/bootcuando una actualización falla por falta de espacio. Nunca borres a mano el kernel que muestrauname -r.- Si el servidor usa snaps,
sudo snap set system refresh.retain=2limita a dos las versiones guardadas de cada uno.
5. Un servicio: systemctl status y journalctl -u
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,timeoutostart-limit-hit. journalctl -ufiltra por unidad;-b, desde el último arranque;-p err, solo errores;-f, en directo mientras lo arrancas en otra ventana.systemctl cat contoso-apimuestra 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:
[Unit]StartLimitIntervalSec=300StartLimitBurst=5 [Service]Restart=on-failureRestartSec=10systemctl editcrea/etc/systemd/system/contoso-api.service.d/override.confy recarga systemd al guardar.systemctl revert contoso-apilo deshace.Restart=on-failurevuelve a arrancar el servicio si muere con error, pero no si alguien lo para consystemctl stop.RestartSeces la espera entre intentos.StartLimitBurstyStartLimitIntervalSec(en[Unit]) ponen el tope: más de 5 arranques en 300 segundos y systemd deja de intentarlo constart-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.
- El estado:
systemctl status contoso-apidicefailed (Result: start-limit-hit). Ese resultado no es la causa: es systemd diciendo que dejó de intentarlo. - La causa, en el journal:
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'.- El disco:
df -h /al 100 % ydulleva 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. - 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 quedfbaja; si no baja,lsof +L1. - Arrancar: después de un
start-limit-hit, systemd no deja arrancar hasta reiniciar el contador:
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- 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
- La primera guía de Ubuntu, los primeros 30 minutos tras la instalación, cubre usuarios, SSH, firewall y actualizaciones automáticas.
- Con varios servidores, la alerta de disco y de servicio caído va en la monitorización: la guía de Zabbix: servidor, agentes y plantillas usa la plantilla de Linux con umbrales por sistema de ficheros.
- Para no buscar logs servidor a servidor, la guía de ELK los centraliza.
¿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.
What you'll get
Knowing within five minutes what is filling an Ubuntu Server and freeing space without deleting the wrong thing; capping the journal and the applications' logs so it does not happen again; and, when a service won't start, reading what systemd says about it, fixing its unit without touching the package's file and giving it a sensible restart policy.
Before you start
- Ubuntu Server 22.04 or 24.04 LTS and a user with
sudo. - The application's service name (here,
contoso-api.service) and where it writes its logs (/var/log/contoso-api/). ncduinstalled (sudo apt install ncdu). If the disk is at 100 %, evenaptmay not work: steps 1 and 2 use what the system already has.
1. What is full: df, du and ncdu
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 /vardf -htells you which file system is full;df -i, whether what has run out is inodes (millions of small files, such as sessions or mail queues). With inodes at 100 % there is free space and still no file can be created.du -xdoes not cross into other file systems: that way you do not count an NFS share mounted underneath. Go down level by level (/var, then/var/log) until you find the culprit.sudo ncdu -x /does the same interactively: arrows to go in,dto delete. Use it to look, and delete carefully.- On ext4, 5 % of the disk is reserved for root. That is why services running under their own user fail first, while root can still write.
A deleted file that a process still holds open frees no space until the process closes it. If df does not go down after an rm, sudo lsof +L1 lists those files. To empty a log in use, truncate it (sudo truncate -s 0 file.log), do not delete it.
2. The systemd journal
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 and --vacuum-time only delete archived files; to make the limit permanent, a file of your own in journald.conf.d:
[Journal]SystemMaxUse=500MSystemKeepFree=2Gsudo systemctl restart systemd-journald applies it. By default the journal may take 10 % of the file system, up to 4 GB: on a 40 GB disk that is 4 GB of system logs.
3. The application's logs with logrotate
journald does not rotate files an application writes on its own. For that, a file in /etc/logrotate.d/:
/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 14keeps 14 files;compresscompresses them anddelaycompressleaves the newest uncompressed, in case the app is still writing to it.suis needed when the folder belongs to the application's user; without it, logrotate refuses with parent directory has insecure permissions.postrotatetells the application to reopen the file. If it cannot, replacecreateand thepostrotateblock withcopytruncate: it copies and empties the file in place, and may lose the lines written at that instant.- On Ubuntu, logrotate is run by
logrotate.timeronce a day.maxsizeis only checked on each run: if the app can write gigabytes in a few hours, it has to run more often.
sudo logrotate -d /etc/logrotate.d/contoso-apisudo logrotate -f /etc/logrotate.d/contoso-apisystemctl list-timers logrotate.timer-d simulates and explains what it would do without touching anything; -f forces a rotation now.
4. The apt cache and old kernels
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 --purgeapt cleanempties/var/cache/apt/archives/, packages that are already installed.apt autoremove --purgeremoves kernels no longer needed: it keeps the running one and the previous one as a way back. It is what frees/bootwhen an update fails for lack of space. Never remove by hand the kerneluname -rshows.- If the server uses snaps,
sudo snap set system refresh.retain=2limits each one to two saved revisions.
5. A service: systemctl status and journalctl -u
systemctl status contoso-api --no-pager× contoso-api.service - Contoso invoicing API 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 says where the unit file is and whether it starts at boot (
enabled). Active says how it ended:exit-code,oom-kill,timeoutorstart-limit-hit. journalctl -ufilters by unit;-b, since the last boot;-p err, errors only;-f, live while you start it in another window.systemctl cat contoso-apishows the whole unit, with the files that modify it.
6. Adjusting the unit with systemctl edit and the restart policy
The unit file is installed by the package or by the application team. Your own changes go in a separate file that survives updates:
[Unit]StartLimitIntervalSec=300StartLimitBurst=5 [Service]Restart=on-failureRestartSec=10systemctl editcreates/etc/systemd/system/contoso-api.service.d/override.confand reloads systemd on save.systemctl revert contoso-apiundoes it.Restart=on-failurestarts the service again if it dies with an error, but not if someone stops it withsystemctl stop.RestartSecis the wait between attempts.StartLimitBurstandStartLimitIntervalSec(in[Unit]) set the ceiling: more than 5 starts in 300 seconds and systemd stops trying withstart-limit-hit. Without a ceiling, a broken service restarts in a loop and fills the journal.
7. The ticket: "the application stopped writing logs and the service fails to start"
Monday, 8:20. Accounts cannot issue invoices. The application team says the last log line is from Sunday at 23:47 and the service will not come up.
- The state:
systemctl status contoso-apisaysfailed (Result: start-limit-hit). That result is not the cause: it is systemd saying it gave up. - The cause, in the journal:
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'.- The disk:
df -h /at 100 % andduleads to/var/log/contoso-api/app.log, 38 GB. The application switched its log level to debug in Friday's deployment and there was no logrotate rule for that folder. - Free space without losing the evidence: keep the last lines (
sudo tail -n 5000 app.log > /root/app-tail.log), truncate the file (sudo truncate -s 0 /var/log/contoso-api/app.log) and clear the archived journal (journalctl --vacuum-size=500M). Check thatdfgoes down; if it does not,lsof +L1. - Start it: after a
start-limit-hit, systemd will not start the unit until the counter is reset:
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- So it does not happen again: the logrotate rule from section 3, the journal limit from section 2, the log level set back to info by the application team, and a disk alert at 80 % in monitoring.
In the ticket: file system and usage before and after, which file filled it and why, what was truncated and what was kept, and the two new rules.
Next steps
- The first Ubuntu guide, the first 30 minutes after installation, covers users, SSH, the firewall and automatic updates.
- With several servers, the disk and service-down alerts belong in monitoring: the Zabbix: server, agents and templates guide uses the Linux template with per-file-system thresholds.
- To stop hunting logs server by server, the ELK guide centralises them.
Want to practise it? Solve the ticket “502 Bad Gateway: the timesheets app is down” in SysAdmin Desks, free and in your browser.
Is something missing, or different in your environment? Get in touch and I'll fix it.
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.Found this useful? Every two weeks I send one practical idea for IT professionals: LinkedIn, projects, networking and hiring processes.
Apúntate y llévate las 33 ideasSign up and get the 33 ideas →