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.
  • logrotate instalado (apt install logrotate o yum 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.conf y /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

DirectivaEfecto
daily / weekly / monthlyFrecuencia de rotación
rotate NNúmero de archivos rotados a conservar antes de eliminar
compressComprimir archivos rotados con gzip
delaycompressComprimir la rotación anterior, no la recién rotada
missingokOmitir silenciosamente si el archivo de log no existe
notifemptyNo rotar si el log está vacío
create modo propietario grupoCrear un nuevo log vacío con estos permisos tras la rotación
sharedscriptsEjecutar postrotate una vez para todos los archivos coincidentes
dateextAgregar fecha en lugar de número al nombre del archivo rotado
size N / minsize N / maxsize NDisparar 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

ProblemaCausaSolución
La rotación corre pero los logs siguen creciendonotifempty omite logs vacíos, o la app no respeta el reloadVerifica 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 todosCorrige permisos: chmod o-w /var/log/miapp
Archivos rotados sin comprimirFalta compress, o se usa sin delaycompress para apps que aún tienen el archivo abiertoAgrega delaycompress para comprimir en el siguiente ciclo
SELinux bloquea la rotaciónContexto SELinux incorrecto en archivos rotadosEjecuta restorecon -v /var/log/miapp/*.log o agrega una regla en postrotate
Corrupción del archivo de estadoEdiciones manuales o errores del sistema de archivosElimina /var/lib/logrotate/status — logrotate lo recrea y trata todos los logs como nunca rotados
Script postrotate falla silenciosamenteEl código de salida del script es distinto de ceroAgrega `

Comparativa: Logrotate vs Otras Alternativas

HerramientaMecanismoIdeal Para
logrotateRotación de archivos activada por cron con reglas configurablesArchivos de log tradicionales en /var/log/
systemd-journaldDiario binario con límites de tamaño/tiempo SystemMaxUse y MaxFileSecEntradas de journal de servicios systemd (journalctl)
rsyslog integradoMódulo om file con directivas de rotaciónEntornos con reenvío centralizado de logs via rsyslog
Drivers de DockerDriver json-file con opciones max-size y max-fileLogs de stdout/stderr de contenedores gestionados por Docker
Fluentd / VectorEnvío a almacenamiento remoto; sin rotación localEntornos cloud-native con agregación centralizada de logs

Resumen

  • Logrotate se ejecuta diariamente vía /etc/cron.daily/logrotate y usa /var/lib/logrotate/status para 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 postrotate con systemctl reload o kill -USR1 siempre que sea posible — prefiérelo sobre copytruncate.
  • Agrega delaycompress junto con compress para no comprimir archivos aún abiertos por procesos en ejecución.
  • Usa size, minsize o maxsize para servicios que puedan generar logs voluminosos de forma inesperada.
  • Siempre prueba con logrotate -d antes 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.

Artículos Relacionados