TL;DR — Resumen Rápido
Logrotate automatiza la rotación de logs en Linux. Aprende directivas clave, scripts postrotate, rotación por tamaño y cómo probar tu configuración.
Gestionar archivos de log en Linux es una tarea operativa rutinaria que, cuando se descuida, provoca discos llenos, rendimiento degradado y servicios caídos. Logrotate es la herramienta estándar para automatizar la rotación, compresión y limpieza de logs en prácticamente todas las distribuciones Linux. Esta guía cubre todo, desde la configuración global hasta ejemplos por aplicación, estrategias de prueba y solución de problemas reales.
Prerrequisitos
- Servidor Linux con Ubuntu, Debian, RHEL o una distribución compatible.
logrotateinstalado (apt install logrotateoyum install logrotate).- Familiaridad básica con la línea de comandos y la gestión de servicios con
systemctl. - Acceso root o sudo para editar
/etc/logrotate.confy/etc/logrotate.d/.
Cómo Funciona Logrotate
Logrotate no se ejecuta como un demonio. Es invocado diariamente por la entrada cron en /etc/cron.daily/logrotate. Cada vez que se ejecuta, lee su configuración, consulta el archivo de estado en /var/lib/logrotate/status para saber cuándo se rotó cada log por última vez, y actúa solo cuando ha transcurrido el intervalo programado.
# Ver el archivo de estado manualmente
cat /var/lib/logrotate/status
El archivo de estado contiene entradas como:
"/var/log/nginx/access.log" 2026-3-21-6:0:0
"/var/log/syslog" 2026-3-22-6:0:0
Si este archivo se corrompe o se elimina, logrotate rotará todos los logs en su próxima ejecución como si nunca hubieran sido rotados.
Config Global vs Configs por Aplicación
/etc/logrotate.conf — Valores Predeterminados Globales
Este archivo establece los valores heredados por todas las configuraciones:
# Rotar semanalmente por defecto
weekly
# Mantener 4 rotaciones
rotate 4
# Comprimir logs rotados
compress
# Cargar configs por aplicación
include /etc/logrotate.d
Cualquier directiva aquí aplica globalmente a menos que sea anulada en un archivo de app.
/etc/logrotate.d/ — Sobreescrituras por Aplicación
Cada archivo en este directorio configura la rotación de una aplicación. El nombre del archivo es arbitrario (por convención el nombre de la app), y un solo archivo puede gestionar múltiples rutas de log:
/var/log/nginx/access.log /var/log/nginx/error.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 www-data adm
postrotate
systemctl reload nginx
endscript
}
Directivas Clave
| Directiva | Efecto |
|---|---|
daily / weekly / monthly | Frecuencia de rotación |
rotate N | Número de archivos rotados a conservar antes de eliminar |
compress | Comprimir archivos rotados con gzip |
delaycompress | Comprimir la rotación anterior, no la recién rotada |
missingok | Omitir silenciosamente si el archivo de log no existe |
notifempty | No rotar si el log está vacío |
create modo propietario grupo | Crear un nuevo log vacío con estos permisos tras la rotación |
sharedscripts | Ejecutar postrotate una vez para todos los archivos coincidentes |
dateext | Agregar fecha en lugar de número al nombre del archivo rotado |
size N / minsize N / maxsize N | Disparar rotación basada en el tamaño del archivo |
copytruncate vs postrotate
Esta es la decisión arquitectónica más importante para cada aplicación que gestiones.
postrotate / endscript (recomendado)
Después de que logrotate renombra el archivo de log, el bloque postrotate ejecuta un comando que le indica a la aplicación que cierre el descriptor antiguo y abra el nuevo archivo vacío:
postrotate
systemctl reload nginx
# o para procesos que usan SIGUSR1:
kill -USR1 $(cat /var/run/gunicorn.pid) 2>/dev/null || true
endscript
Es el enfoque correcto para Nginx, Apache, Gunicorn y cualquier servicio que maneje reload o SIGUSR1 correctamente.
copytruncate
Algunas aplicaciones (scripts personalizados, ciertas apps Java) no pueden recargar descriptores de archivo. copytruncate instruye a logrotate a copiar el archivo al nombre rotado y luego truncar el original a cero bytes:
/var/log/miapp/app.log {
daily
rotate 7
compress
delaycompress
copytruncate
}
Precaución: Hay una pequeña ventana entre la copia y el truncado donde se pueden escribir líneas al archivo original. Estas líneas terminan en el archivo activo, no en la copia — lo que significa que se pierden del archivo rotado. Para logs de alto volumen, prefiere postrotate siempre que sea posible.
Rotación Basada en Tamaño
La rotación por tiempo no siempre es suficiente. Una aplicación repentinamente verbosa puede llenar el disco antes de que corra el cron diario. Usa estas directivas para agregar disparadores por tamaño:
/var/log/miapp/app.log {
# Rotar cuando el archivo supere 100 MB sin importar el horario
size 100M
# Solo rotar cuando el archivo tenga al menos 10 MB Y haya pasado el intervalo
# minsize 10M
# Rotar cuando supere 500 MB, incluso si no ha pasado el intervalo
# maxsize 500M
rotate 10
compress
delaycompress
missingok
notifempty
}
size anula completamente el horario de tiempo. minsize requiere tanto el umbral de tamaño como el intervalo de tiempo. maxsize rota inmediatamente por tamaño independientemente del horario.
Ejemplos por Aplicación
Nginx
/var/log/nginx/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 0640 www-data adm
sharedscripts
postrotate
nginx -s reopen
endscript
}
nginx -s reopen envía SIGUSR1 al proceso maestro, lo que hace que todos los workers reabran sus archivos de log.
Docker
Docker escribe logs JSON en /var/lib/docker/containers/<id>/<id>-json.log. Puedes rotarlos con logrotate como respaldo cuando no esté configurado --log-opt max-size del demonio Docker:
/var/lib/docker/containers/*/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
copytruncate
}
La solución preferida a largo plazo es configurar el demonio Docker con "log-driver": "json-file" y "log-opts": {"max-size": "100m", "max-file": "5"} en /etc/docker/daemon.json.
Logs de Aplicación en /var/log/miapp/
/var/log/miapp/*.log {
daily
rotate 14
size 50M
compress
delaycompress
missingok
notifempty
create 0640 miapp miapp
sharedscripts
postrotate
systemctl reload miapp 2>/dev/null || true
endscript
}
Nombres de Archivo con Fecha (dateext)
Por defecto, logrotate agrega sufijos numéricos: access.log.1, access.log.2.gz. Activa dateext para nombres con fecha legibles:
/var/log/nginx/*.log {
daily
rotate 30
dateext
dateformat -%Y-%m-%d
compress
delaycompress
missingok
}
Esto produce nombres como access.log-2026-03-22.gz — mucho más fácil de auditar.
Pruebas de Configuración
Simulación (Seguro)
# Simular sin hacer ningún cambio
sudo logrotate -d /etc/logrotate.d/nginx
Forzar Rotación
# Forzar rotación ahora sin importar el horario
sudo logrotate -f /etc/logrotate.d/nginx
Modo Verbose
sudo logrotate -v /etc/logrotate.conf
Verificar el resultado:
ls -lh /var/log/nginx/
cat /var/lib/logrotate/status | grep nginx
Solución de Problemas
| Problema | Causa | Solución |
|---|---|---|
| La rotación corre pero los logs siguen creciendo | notifempty omite logs vacíos, o la app no respeta el reload | Verifica si el log tiene contenido; comprueba que la app reabra archivos con systemctl reload |
| ”error: skipping porque el directorio padre tiene permisos inseguros” | logrotate rechaza directorios con permisos de escritura para todos | Corrige permisos: chmod o-w /var/log/miapp |
| Archivos rotados sin comprimir | Falta compress, o se usa sin delaycompress para apps que aún tienen el archivo abierto | Agrega delaycompress para comprimir en el siguiente ciclo |
| SELinux bloquea la rotación | Contexto SELinux incorrecto en archivos rotados | Ejecuta restorecon -v /var/log/miapp/*.log o agrega una regla en postrotate |
| Corrupción del archivo de estado | Ediciones manuales o errores del sistema de archivos | Elimina /var/lib/logrotate/status — logrotate lo recrea y trata todos los logs como nunca rotados |
Script postrotate falla silenciosamente | El código de salida del script es distinto de cero | Agrega ` |
Comparativa: Logrotate vs Otras Alternativas
| Herramienta | Mecanismo | Ideal Para |
|---|---|---|
| logrotate | Rotación de archivos activada por cron con reglas configurables | Archivos de log tradicionales en /var/log/ |
| systemd-journald | Diario binario con límites de tamaño/tiempo SystemMaxUse y MaxFileSec | Entradas de journal de servicios systemd (journalctl) |
| rsyslog integrado | Módulo om file con directivas de rotación | Entornos con reenvío centralizado de logs via rsyslog |
| Drivers de Docker | Driver json-file con opciones max-size y max-file | Logs de stdout/stderr de contenedores gestionados por Docker |
| Fluentd / Vector | Envío a almacenamiento remoto; sin rotación local | Entornos cloud-native con agregación centralizada de logs |
Resumen
- Logrotate se ejecuta diariamente vía
/etc/cron.daily/logrotatey usa/var/lib/logrotate/statuspara rastrear los tiempos de rotación. - Los valores globales están en
/etc/logrotate.conf; las configs por app van en/etc/logrotate.d/. - Usa
postrotateconsystemctl reloadokill -USR1siempre que sea posible — prefiérelo sobrecopytruncate. - Agrega
delaycompressjunto concompresspara no comprimir archivos aún abiertos por procesos en ejecución. - Usa
size,minsizeomaxsizepara servicios que puedan generar logs voluminosos de forma inesperada. - Siempre prueba con
logrotate -dantes de desplegar una configuración nueva en producción. - Los nombres con fecha (
dateext) facilitan mucho la gestión y auditoría de archivos de log.