¿Por qué "tail -f ... | cola "no puede producir ningún resultado?

36

¿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).

thomie
fuente
17
¿Cuáles son los últimos 10 dígitos de π?
Keith Thompson,

Respuestas:

15

Pensé que había visto todo en UNIX. Esta pregunta me sacó de mi presunción. ¡Qué gran pregunta!

tailmuestra las últimas X líneas. tail -fhace 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, taildebe poder ubicar el final del archivo. Si tailno puede encontrar el final del archivo, no puede mostrar las últimas líneas X, porque "último" no está definido. Entonces, ¿qué hace tailen este caso? Espera hasta que encuentre el final del archivo.

Considera esto:

$ chatter() { while :; do date; sleep 1; done; }
$ chatter | tail -f

Esto nunca parece avanzar, porque nunca hay un final definitivo desde el archivo chatter.

Obtiene el mismo comportamiento si solicita taildarle las últimas líneas de una tubería del sistema de archivos. Considerar:

$ mkfifo test.pipe
$ tail test.pipe

stdbufevitar 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 el file_linescomentario de la función dice:

END_POS es el desplazamiento del archivo de EOF (uno más grande que el desplazamiento del último byte).

Y esa es la magia. Necesita un final de archivo para que la cola funcione en cualquier configuración. headno tiene esa restricción, solo necesita un inicio de archivo (que podría no tener, intente head test.pipe). Transmitir como herramientas orientadas sedy awkno requieren de un comienzo o al final del archivo: trabajan en los tampones.

obispo
fuente
37

tail -fLa cola es realmente algo desconocido en el presente, entonces, ¿cómo debería tailsaberlo el próximo ? Por otro lado tail -f, la cabeza es algo ya conocido y que podría ser procesado.

O para decirlo de manera más simple: tailes relativo al final del archivo, pero el flujo de salida de tail -fno obtuvo EOF (al menos no antes de su finalización).

Si encuentra el tailpid del primer y lo mata, entonces debería ver el resultado del segundo.

Ghanima
fuente
21

Respuesta técnica

Cuando se ejecuta con una secuencia como entrada, tailmantiene un nbú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 un EOFcódigo especial cuando intenta leer desde la entrada corriente. La invocación tail -fno sale, por lo tanto, nunca cerrará su flujo, lo que hace imposible, por ejemplo, devolver las 10 últimas líneas de ese flujo.

sleblanc
fuente
3

La función de tailes mostrar la última parte - "cola" - de la entrada o archivo. (La opción -fes 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 idel 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 nlíneas, o que ya no puede ser parte de ella, porque conocemos nmás líneas.

Si ahora llegamos al final del archivo , sabemos que las últimas nlíneas que guardamos son, de hecho, las últimas nlíneas del archivo.

Ahora, en el caso de

tail -f /etc/passwd | tail

el primero taillee 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 segundo tail 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.

Volker Siegel
fuente