¿Por qué el siguiente comando no produce ningún resultado?
$ tail -f /etc/passwd | tail
Después de leer sobre el almacenamiento en búfer , intenté lo siguiente en vano:
$ tail -f /etc/passwd | stdbuf -oL tail
Tenga en cuenta que lo siguiente produce resultados:
$ tail /etc/passwd | tail
Entonces, esto:
$ tail -f /etc/passwd | head
Estoy usando la versión de cola 8.21 (GNU coreutils).
Respuestas:
Pensé que había visto todo en UNIX. Esta pregunta me sacó de mi presunción. ¡Qué gran pregunta!
tail
muestra las últimas X líneas.tail -f
hace lo mismo, pero esencialmente en un bucle infinito: en el inicio, muestra las últimas X líneas del archivo, luego usa algo de magia del sistema operativo (como inotify), supervisa y muestra nuevas líneas.Para hacer su trabajo,
tail
debe poder ubicar el final del archivo. Sitail
no puede encontrar el final del archivo, no puede mostrar las últimas líneas X, porque "último" no está definido. Entonces, ¿qué hacetail
en este caso? Espera hasta que encuentre el final del archivo.Considera esto:
Esto nunca parece avanzar, porque nunca hay un final definitivo desde el archivo
chatter
.Obtiene el mismo comportamiento si solicita
tail
darle las últimas líneas de una tubería del sistema de archivos. Considerar:stdbuf
evitar el problema percibido fue un intento noble. Sin embargo, el hecho clave es que el almacenamiento en búfer de E / S no es la causa raíz: la falta de un fin de archivo definitivo sí lo es. Si revisa el código fuente tail.c , verá que elfile_lines
comentario de la función dice:Y esa es la magia. Necesita un final de archivo para que la cola funcione en cualquier configuración.
head
no tiene esa restricción, solo necesita un inicio de archivo (que podría no tener, intentehead test.pipe
). Transmitir como herramientas orientadassed
yawk
no requieren de un comienzo o al final del archivo: trabajan en los tampones.fuente
tail -f
La cola es realmente algo desconocido en el presente, entonces, ¿cómo deberíatail
saberlo el próximo ? Por otro ladotail -f
, la cabeza es algo ya conocido y que podría ser procesado.O para decirlo de manera más simple:
tail
es relativo al final del archivo, pero el flujo de salida detail -f
no obtuvo EOF (al menos no antes de su finalización).Si encuentra el
tail
pid del primer y lo mata, entonces debería ver el resultado del segundo.fuente
Respuesta técnica
Cuando se ejecuta con una secuencia como entrada,
tail
mantiene unn
búfer de línea que se llena a medida que lee la secuencia, pero no puede generar esas líneas hasta que llega al final de la secuencia, es decir, recibe unEOF
código especial cuando intenta leer desde la entrada corriente. La invocacióntail -f
no sale, por lo tanto, nunca cerrará su flujo, lo que hace imposible, por ejemplo, devolver las 10 últimas líneas de ese flujo.fuente
La función de
tail
es mostrar la última parte - "cola" - de la entrada o archivo. (La opción-f
es sobre lo que hace más tarde, por lo que eso no es relevante aquí).Pensemos en un archivo:
¿Cuál es la última parte de un archivo ?
Digamos que son las últimas n líneas de un archivo.
Cuando leemos la línea
i
del archivo de entrada, ¿cómo decidir si debe imprimirse o no?No sabemos si está en la última parte, porque no sabemos cuál será la última línea. Entonces no podemos imprimirlo ahora.
Necesitamos mantener la línea hasta que quede claro que es parte de las últimas
n
líneas, o que ya no puede ser parte de ella, porque conocemosn
más líneas.Si ahora llegamos al final del archivo , sabemos que las últimas
n
líneas que guardamos son, de hecho, las últimasn
líneas del archivo.Ahora, en el caso de
el primero
tail
lee el archivo, y luego espera obtener más datos de él, para escribir eso también. Por lo tanto, no indicará el final del archivo a la segunda cola cuando llegue al final del archivo que lee. Sin eso, el segundotail
nunca recibe una notificación del final del archivo, por lo que nunca puede averiguar cuáles son las últimas líneas que debe imprimir.fuente