Quiero ver un archivo hasta que aparezca un poco de texto
Encontré esta respuesta:`tail -f` hasta que se vea el texto
pero cuando lo probé en ubuntu, no sale:
$ echo one > test.txt
$ echo two >> test.txt
$ echo three >> test.txt
$ echo four >> test.txt
$ cat test.txt | sed '/w/ q'
one
two
$
funciona como se esperaba. sin embargo, cuando trato de rastrear el archivo
$ tail -f test.txt | sed '/w/ q'
one
two
nunca sale. cola no se detiene a pesar de que la tubería está rota.
¿Alguien sabe cómo hacer tail
? salir cuando sed
salidas?
Respuesta aceptada:
Es lo mismo que en:
- ¿Cómo salir temprano en el cierre de la tubería?
- ¿Grep tarda en salir después de encontrar una coincidencia?
- limitar la salida de búsqueda Y evitar la señal 13
en:
cmd1 | cmd2
Su shell espera hasta cmd1
termina incluso después de cmd2
ya ha terminado. Ese no es el caso de todas las conchas. Algunos como el shell Bourne o Korn, por ejemplo, no lo hacen.
Cuando cmd2
muere, la tubería en cmd1
's stdout se vuelve roto , pero eso no termina cmd1
al instante.
cmd1
terminará la próxima vez que intente escribir en esa tubería. Luego recibirá un SIGPIPE cuya acción predeterminada es finalizar el proceso.
Con cmd1
==tail -f file
y cmd2
==sed /w/q
, tail -f
leerá las últimas 10 líneas del archivo y las escribirá en la salida estándar (la canalización), generalmente en un solo fragmento, a menos que las líneas sean realmente grandes y se queden allí esperando que se agregue más texto al file
.
sed
, que se ejecuta simultáneamente, esperará la entrada en su entrada estándar, la leerá, la procesará línea por línea y se cerrará si hay una línea que contenga w
.
Tan pronto (o posiblemente con una demora de una línea con algo de sed
) implementación) cuando encuentra esa línea, sale, pero en ese momento, tail
ya ha escrito en la tubería todo lo que tenía que ESCRIBIR, por lo que no recibirá un SIGPIPE a menos que se agregue algún texto adicional más adelante al archivo (momento en el cual hará el fatal write()
).
Si quisiera cmd1
para terminar tan pronto como cmd2
termina, necesitarías algo para matarlo una vez cmd2
termina Me gusta con:
sh -c 'echo "$$"; exec tail -f test.txt' | {
IFS= read pid
sed /w/q
kill -s PIPE "$pid"
}
O con bash
:
{ sed /w/q; kill -s PIPE "$!"; } < <(exec tail -f text.txt)
Editar 2020
Como señaló @user414777, desde la versión 8.28, la implementación GNU de tail
, en los modos de seguimiento, ahora no solo busca nuevos datos en los archivos que monitorea, sino que también verifica si su salida estándar se convierte en una tubería rota y sale de inmediato (o dentro de un segundo si inotify no se usa), lo que hace innecesarias las soluciones anteriores.
Sin embargo, tenga en cuenta que solo GNU tail
hace este tipo de procesamiento, no cualquier otra implementación de tail
(AFAIK), y ninguna otra utilidad (incluso las implementaciones de GNU).
Entonces, mientras:
tail -f file | head -n1
Saldrá después de una línea,
tail -f file | tr '[:lower:]' '[:upper:]' | head -n1
por ejemplo, no necesariamente como tr
no supervisará si su salida estándar se convierte en una tubería rota, por lo que solo morirá si escribe algo allí después de que la tubería se haya roto como de costumbre (y es solo en ese punto que GNU tail -f
saldrá).