Logs en Linux: journalctl, /var/log, rsyslog y logrotate
En las distribuciones actuales de Linux los logs los recoge journald y se leen con journalctl: journalctl -u nginx muestra los registros de un único servicio, -f sigue el flujo en tiempo real, y --since y -p filtran por hora e importancia. Los logs de texto están en /var/log, los escribe rsyslog o la propia aplicación, y logrotate comprime y elimina periódicamente los archivos antiguos para que el disco no se llene.
Cuando un servicio se cae de noche, la respuesta casi siempre está en los logs; la cuestión es dónde buscarla. En las distribuciones modernas (Ubuntu, Debian, RHEL, Fedora, Arch) los eventos los recoge el servicio journald y se leen con el comando journalctl. Al mismo tiempo, muchos programas escriben archivos de texto normales en /var/log, y logrotate se encarga de que no crezcan sin control. A continuación veremos cómo trabajar con los logs de journalctl en Linux en la práctica, dónde están los demás registros y cómo no perder lo importante durante la rotación.
Dónde se guardan los logs en Linux
Hay tres fuentes, y conviene tenerlas presentes como un mapa:
- journald — el diario binario de systemd. Recibe stdout y stderr de todos los servicios, los mensajes del núcleo y syslog. Se guarda en
/var/log/journal/(de forma permanente) o en/run/log/journal/(hasta el reinicio). - /var/log — archivos de texto. Los escribe
rsyslog(por ejemplo,/var/log/syslog,/var/log/auth.log) o las propias aplicaciones: nginx, PostgreSQL, MySQL. - Búfer circular del núcleo — mensajes de los controladores y del hardware; los muestra
dmesgojournalctl -k.
| Archivo | Contenido |
|---|---|
/var/log/syslog (Debian/Ubuntu) | registro general del sistema |
/var/log/messages (RHEL/Fedora) | lo mismo en la familia Red Hat |
/var/log/auth.log o /var/log/secure | inicios de sesión, sudo, SSH |
/var/log/kern.log | mensajes del núcleo |
/var/log/dpkg.log, /var/log/apt/ | instalación de paquetes |
/var/log/nginx/ | access.log y error.log del servidor web |
/var/log/wtmp, /var/log/btmp | registros binarios de inicios de sesión, se leen con last y lastb |
La mayoría de los archivos de /var/log solo son accesibles para root o para el grupo adm, por eso los comandos de lectura a menudo deben ejecutarse con sudo.
journalctl: comandos básicos
Sin argumentos, journalctl muestra el diario completo, desde los registros más antiguos, a través del paginador less. Rara vez es lo que se necesita: normalmente se reduce la selección enseguida.
journalctl # todo el diario, de más antiguo a más reciente
journalctl -e # abrir directamente al final
journalctl -n 50 # las últimas 50 líneas
journalctl -r # en orden inverso, lo más nuevo arriba
journalctl --no-pager # sin less; útil en scripts y con grep
Dentro del paginador funcionan las teclas habituales de less: / para buscar, G para ir al final y q para salir. Las líneas largas se cortan según el ancho de la pantalla; las flechas izquierda y derecha las desplazan.
Logs de un servicio concreto: journalctl -u
El caso más frecuente es ver lo que escribió una unidad de systemd. No hace falta buscar el archivo ni filtrar con grep:
$ sudo journalctl -u nginx -n 20
Oct 14 03:12:41 web1 systemd[1]: Starting nginx.service - A high performance web server...
Oct 14 03:12:41 web1 nginx[1834]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Oct 14 03:12:41 web1 systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Oct 14 03:12:41 web1 systemd[1]: nginx.service: Failed with result 'exit-code'.
El flag -u puede repetirse: journalctl -u nginx -u php8.2-fpm muestra ambos servicios mezclados por hora, lo cual resulta cómodo cuando el error aparece en la frontera entre los dos. Para las unidades de usuario (systemctl --user) use journalctl --user -u nombre.
Logs en tiempo real: journalctl -f
sudo journalctl -u nginx -f
Es el equivalente de tail -f: muestra las últimas 10 entradas y espera las nuevas. Resulta útil tenerlo en otra terminal mientras reinicia el servicio o reproduce el error. Para salir, pulse Ctrl+C.
Filtros por tiempo y por arranque
Si sabe cuándo ocurrió la avería, la selección por tiempo se hace con --since y --until. Aceptan tanto fechas exactas como valores relativos:
journalctl --since "2026-10-14 02:50" --until "2026-10-14 03:30"
journalctl --since "1 hour ago"
journalctl --since yesterday --until today
journalctl -u nginx --since "10 min ago"
El segundo corte útil es por arranques del sistema. Si el servidor se reinició solo, la causa suele estar al final de la sesión anterior:
$ journalctl --list-boots
-2 8f1c... Sat 2026-10-12 09:01:12 UTC Sun 2026-10-13 22:47:03 UTC
-1 a7d2... Sun 2026-10-13 22:48:30 UTC Tue 2026-10-14 03:05:51 UTC
0 c3e9... Tue 2026-10-14 03:07:02 UTC Tue 2026-10-14 09:15:40 UTC
$ journalctl -b -1 -e # final del arranque anterior
$ journalctl -b # solo el arranque actual
La lista de arranques solo está disponible si el diario se guarda en disco. Cómo activarlo se explica más abajo, en la sección sobre la configuración de journald.
Filtro por importancia: journalctl -p
Cada entrada tiene una prioridad de syslog del 0 al 7. El flag -p muestra el nivel indicado y todos los más importantes:
| Código | Nombre | Cuándo se usa |
|---|---|---|
| 0 | emerg | el sistema no funciona |
| 1 | alert | se necesita intervención inmediata |
| 2 | crit | error crítico |
| 3 | err | error |
| 4 | warning | advertencia |
| 5 | notice | evento significativo pero normal |
| 6 | info | mensaje informativo |
| 7 | debug | depuración |
journalctl -p err -b # todos los errores desde el arranque
journalctl -p warning..err -u ssh # rango de niveles para un servicio
El comando journalctl -p err -b es una buena primera comprobación tras reiniciar o actualizar: en unos segundos muestra qué ha salido mal.
Búsqueda y otros filtros
El diario guarda campos estructurados en cada entrada, y por ellos se puede filtrar sin grep:
journalctl _PID=1834 # por número de proceso
journalctl _COMM=sshd # por nombre del programa
journalctl _UID=1000 # por usuario
journalctl /usr/sbin/sshd # por la ruta del ejecutable
journalctl -k # solo mensajes del núcleo (como dmesg)
journalctl -t CRON # por identificador de syslog
journalctl -g "Out of memory" # búsqueda por texto, con expresión regular
El flag -g (--grep) apareció en systemd 237; en sistemas más antiguos use la tubería habitual journalctl --no-pager | grep .... Los filtros por distintos campos se combinan con «Y», así que journalctl -u nginx -p err --since today devuelve solo los errores de nginx de hoy.
Formatos de salida
El flag -o cambia el formato. Las variantes más útiles:
-o short-iso— hora en formato ISO 8601, cómodo para comparar con los logs de la aplicación.-o verbose— todos los campos de la entrada, incluidos_SYSTEMD_UNIT,_PIDy_BOOT_ID.-o jsonojson-pretty— para procesarlo con un script o conjq.-o cat— solo el texto del mensaje, sin fecha ni host.
journalctl -u myapp -o json --since today | jq -r '.MESSAGE'
Configurar journald: almacenamiento y tamaño
La configuración está en /etc/systemd/journald.conf (es mejor poner las modificaciones en /etc/systemd/journald.conf.d/*.conf). El parámetro principal es Storage:
persistent— el diario se escribe en disco, en/var/log/journal, y sobrevive al reinicio.volatile— solo en memoria, en/run/log/journal.auto(por defecto) — en disco si existe el directorio/var/log/journal.
En algunas imágenes mínimas ese directorio no existe y el historial desaparece tras el reinicio. Para activar el almacenamiento permanente:
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald
Para que el diario no ocupe todo el disco, establezca límites:
# /etc/systemd/journald.conf.d/size.conf
[Journal]
Storage=persistent
SystemMaxUse=500M
MaxRetentionSec=1month
Por defecto, SystemMaxUse es el 10 % del tamaño del sistema de archivos, pero no más de 4 GB.
Cómo limpiar el diario de journalctl
$ journalctl --disk-usage
Archived and active journals take up 1.8G in the file system.
sudo journalctl --vacuum-size=300M # dejar como máximo 300 MB
sudo journalctl --vacuum-time=2weeks # eliminar entradas de más de dos semanas
sudo journalctl --rotate # cerrar los archivos activos para poder borrarlos también
No conviene borrar archivos de /var/log/journal con rm: vacuum hace lo mismo de forma segura y no toca el archivo activo.
rsyslog: los logs de texto clásicos
rsyslog es el demonio que recibe mensajes de syslog (también los reenviados desde journald) y los distribuye en archivos según reglas. La configuración está en /etc/rsyslog.conf y /etc/rsyslog.d/*.conf. Una regla consta de un selector origen.nivel y una acción:
# /etc/rsyslog.d/50-default.conf (fragmento)
auth,authpriv.* /var/log/auth.log
*.*;auth,authpriv.none -/var/log/syslog
kern.* -/var/log/kern.log
El guion delante de la ruta significa que no se sincroniza el archivo con el disco tras cada línea: es más rápido, pero en caso de avería pueden perderse las últimas líneas. Después de cambiar la configuración, compruebe la sintaxis y reinicie el servicio:
sudo rsyslogd -N1
sudo systemctl restart rsyslog
La razón principal para mantener rsyslog junto a journald es reenviar los logs a un servidor central. Una sola línea envía todo por TCP:
# /etc/rsyslog.d/90-remote.conf
*.* @@logs.example.com:514
Un solo @ significa UDP, y dos @@, TCP. Si el servidor se cae por completo, la copia de los logs queda en otra máquina. Para escribir un mensaje propio en el registro del sistema desde un script, use logger:
logger -t backup -p user.err "La copia de seguridad de la base de datos falló"
journalctl -t backup -n 5
logrotate: rotación de logs
Los logs de texto crecen sin límite hasta que alguien los recorta. Esa tarea la hace logrotate: una vez al día (desde cron o desde el temporizador logrotate.timer) renombra el archivo actual, comprime los antiguos y elimina los más viejos. La configuración general está en /etc/logrotate.conf, y las reglas de cada programa, en /etc/logrotate.d/.
# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 myapp adm
postrotate
systemctl reload myapp > /dev/null 2>&1 || true
endscript
}
| Directiva | Significado |
|---|---|
daily / weekly / size 100M | cuándo rotar |
rotate 14 |
Preguntas frecuentes
¿Por qué journalctl muestra solo las entradas del último arranque?
El diario se guarda en memoria (/run/log/journal). Cree el directorio /var/log/journal o establezca Storage=persistent en journald.conf y reinicie systemd-journald.
¿Cómo permitir que un usuario normal lea el diario del sistema sin sudo?
Añádalo al grupo systemd-journal (o adm en Debian y Ubuntu): sudo usermod -aG systemd-journal nombre, y después vuelva a iniciar sesión.
¿Se puede ver el diario de otro sistema, por ejemplo de un disco conectado?
Sí, indique el directorio del diario con el flag -D: journalctl -D /mnt/var/log/journal. El flag --file lee un archivo .journal concreto.
¿Hace falta rsyslog si ya existe journald?
No necesariamente. Es útil si se necesitan archivos de texto para herramientas antiguas o para reenviar los logs a un servidor central; en muchas imágenes mínimas ya no se instala.
¿Cómo exportar los logs de un servicio a un archivo para enviárselos a un compañero?
Ejecute journalctl -u nombre --since today --no-pager > service.log: se obtiene un archivo de texto normal.
Este tema se explica a fondo y con práctica en el curso «Linux: с нуля до уверенного администрирования».
Ir al curso