Lo obvio es tail -f app.log db.log, pero hay una trampa en producción: cuando logrotate rota el archivo, lo renombra y crea uno nuevo, -f mantiene abierto el antiguo descriptor de archivo y tú te quedas mirando una pantalla congelada. La solución es un carácter: -F reabre el archivo por nombre en lugar de por inode. Aquí está cuándo usar cada variante.
1. Mostrar ambos archivos con headers que los separen
$ clai muestra ambos logs a la vez→ tail -n +1 app.log db.log==> app.log <==line A1==> db.log <==line B1
Cuando consultas varios archivos a la vez, tail automáticamente imprime headers como ==> nombre <== para mostrar cuál es la fuente de cada línea. Es crucial: sin eso no sabrás de dónde vino cada línea.
2. Seguir ambos logs conforme llegan nuevas líneas
$ clai sigue ambos logs mientras se escriben nuevas líneas→ tail -f app.log db.log
El header se imprime de nuevo cada vez que la fuente cambia. Mientras se escribe en un archivo, no ves header; cuando el otro archivo recibe una línea, aparece el header.
3. Sobrevivir la rotación de log y continuar leyendo
$ clai sigue el log para que no se quede mudo después de la rotación→ tail -F /var/log/app/app.log
Esta es la línea que importa. -f mantiene abierto el descriptor de archivo: después de que logrotate renombre el archivo y cree uno nuevo, tail -f se queda leyendo la copia renombrada y nunca ve líneas nuevas. -F vigila el nombre del archivo y lo reabre. Siempre usa -F en producción.
4. Etiquetar cada línea con el nombre de la fuente
$ clai muestra ambos logs mezclados pero etiqueta cada línea con el nombre del archivo→ for f in app.log db.log; do tail -F "$f" | sed "s/^/[$f] /" & done; wait
Los headers en bloques son incómodos cuando los logs se escriben simultáneamente. Un prefijo en cada línea es más fácil de leer. El & lanza cada tail en segundo plano, y wait mantiene el shell en ejecución.
5. Ver todos los archivos de log en un directorio, incluidos los creados después
$ clai sigue todos los archivos de log del directorio→ tail -F /var/log/app/*.log
El shell expande el glob una sola vez, al inicio. Los archivos creados después no se incluirán: tendrías que reiniciar.
6. Cuando necesitas una interfaz real con paneles
$ clai muestra varios logs en paneles separados→ multitail /var/log/syslog /var/log/auth.log
multitail dibuja paneles con resaltado de sintaxis y filtros. Para triage de incidentes con cuatro logs a la vez, eso es notablemente mejor que un stream. Instálalo por separado.
Trampas
-fy-Fsolo difieren en la rotación. Antes de que ocurra la rotación, no hay diferencia, así que el hábito de usar-fno se castiga. Te castigan en el momento exacto en que esperas una línea de log durante un incidente y deja de llegar.tail -fpor la red no funciona bien. En NFS, los cambios pueden no llegar al cliente. Ve el log en la máquina donde se está escribiendo.- Las líneas pueden revueltarse. Dos procesos escribiendo en un stream no están sincronizados. Para entender el orden de eventos, lee las marcas de tiempo dentro de las líneas, no el orden de salida.
Preguntas relacionadas
¿Cómo empiezo a leer desde una línea específica en lugar del final? tail -n +100 file comienza en la línea 100, tail -c +1000 comienza en el byte 1000.
¿Cómo sigo un log y lo filtro al mismo tiempo? tail -F app.log | grep --line-buffered ERROR. Sin --line-buffered, grep buferea la salida y las líneas llegan con retraso.
¿Por qué journalctl es mejor que tail para servicios? Entiende sobre rotación, puede filtrar por unidad y nivel de log, y no depende de dónde escriba el servicio.
Ver también
- Read a service's logs with journalctl
- Sweep old logs and backups with one sentence
- Grep with exclusions
Deja de memorizar edge cases de tail y logrotate — describe qué necesitas ver y CliAI escribe el comando. Instálalo en una línea.