Cuando tienes un archivo de texto grande —un log de 200 MB, un CSV con millones de filas— leerlo entero con cat es un error. head y tail resuelven exactamente ese problema: te dan acceso a los extremos del archivo sin cargarlo completo en memoria. Son herramientas de lectura parcial, y su diseño responde a cómo funciona el sistema de archivos: head lee secuencialmente desde el principio y para; tail busca el final del archivo primero y lee hacia atrás.
La diferencia que más importa en producción es la opción -f de tail. Con -f (follow), el proceso no termina: mantiene el descriptor de archivo abierto y espera a que el kernel le notifique que hay datos nuevos. Esto se apoya en inotify (o en un polling de fallback cuando el sistema de archivos no lo soporta). El detalle crítico es que -f sigue el inodo, no el nombre. Cuando logrotate rota un log, mueve /var/log/nginx/access.log a /var/log/nginx/access.log.1 y crea un archivo nuevo con el mismo nombre pero un inodo distinto. Tu tail -f se queda siguiendo el archivo viejo, que ya no va a crecer más. La solución es -F (mayúscula): sigue el nombre del archivo. Si el archivo desaparece y vuelve a aparecer —con un inodo diferente—, tail -F se reconecta automáticamente. En cualquier sistema que use logrotate, usa siempre -F cuando necesites una sesión de monitoreo larga.
El flag -c abre otra dimensión: en lugar de líneas, operas en bytes. head -c 100 archivo te da los primeros 100 bytes exactos, útil para inspeccionar cabeceras de archivos binarios o protocolos. tail -c +100 usa la notación +N, que significa “desde el byte 100 hasta el final” —empieza a contar desde el principio, no desde el final— lo cual permite saltar cabeceras fijas o procesar streams en tramos.
Si confundes -f y -F en un entorno con logrotate, pasarás horas mirando una terminal congelada convencido de que no hay tráfico, cuando en realidad el log activo es otro archivo.
# Primeras 20 líneas de un archivo de configuración head -n 20 /etc/ssh/sshd_config # Últimas 20 líneas del log de autenticación tail -n 20 /var/log/auth.log # Inspeccionar los primeros 16 bytes (cabecera mágica de un PNG, por ejemplo) head -c 16 /usr/share/pixmaps/debian-logo.png | xxd # Saltar los primeros 100 bytes y leer el resto # (útil para archivos con cabecera de longitud fija) tail -c +101 /var/log/dpkg.log | head -c 200 # Seguir el log de nginx EN PRODUCCIÓN: -F porque logrotate lo rota # grep filtra solo las líneas que contienen errores HTTP 5xx tail -F /var/log/nginx/access.log | grep --line-buffered ' 5[0-9][0-9] ' # Monitorear auth.log buscando intentos fallidos de SSH # --line-buffered evita que grep acumule el output en un buffer interno # y las líneas aparezcan con retraso tail -F /var/log/auth.log | grep --line-buffered 'Failed password'
Por qué --line-buffered en el pipe: cuando grep detecta que su salida no va a una terminal sino a otro proceso o a un pipe, activa el buffering por bloques (normalmente 4 KB o 8 KB). Eso significa que las líneas coincidentes se acumulan en memoria hasta llenar el buffer antes de mostrarse, lo que produce una experiencia extraña donde ves nada durante minutos y luego aparecen diez líneas de golpe. --line-buffered le fuerza a vaciar el buffer línea a línea, que es el comportamiento que quieres cuando estás monitoreando en tiempo real.
El regex 5[0-9][0-9] en el ejemplo de nginx no es arbitrario: el formato de access.log tiene el código de estado HTTP con espacios a ambos lados, así que anclar la búsqueda con espacios evita falsos positivos de URLs que contengan “500” en la ruta.
tail -c +101 usa la convención +N que comparte con cut y algunos comandos POSIX: el + indica offset absoluto desde el inicio, no desde el final. Sin el +, tail -c 101 daría los últimos 101 bytes, que es lo contrario de lo que necesitas para saltar cabeceras.
Por qué head para binarios: head -c 16 sobre un PNG te da los bytes del magic number sin que la terminal intente interpretar el resto del archivo como texto. Combinado con xxd o od, es la forma más rápida de verificar el tipo real de un archivo cuando la extensión no es de fiar —más directa que file cuando quieres ver los bytes exactos, no la interpretación.
El patrón tail -F archivo | grep --line-buffered patrón es el punto de partida de cualquier monitoreo manual en producción antes de desplegar algo más sofisticado como Loki o un stack de ELK.
N° 30