¿Cómo recuperar en tiempo real una salida que contiene una barra de progreso?

¿Cómo recuperar en tiempo real una salida que contiene una barra de progreso?

Estoy usando una herramienta ( openocd) que imprime mucha basura, luego una barra de progreso básica que imprime lentamente puntos simples y luego nuevamente algo de basura.

Me gustaría filtrar esta salida para grepque solo se muestre la línea con la barra de progreso y en tiempo real (es decir, cada punto generado openocdse imprime inmediatamente en la terminal):

openocd <args> |& grep '^\.'

El problema es que grepestá almacenado en un búfer de línea (en el mejor de los casos), por lo que la barra de progreso no se mostrará hasta que finalice.

¿Cómo puedo hacerlo grepo existe alguna alternativa estándar para lograr esto? Si hay una forma de realizar openocdla configuración, sería útil, aunque preferiría una solución más general.

Respuesta1

Esta es una especie de respuesta hacky/inusual, el hecho es que lo más probable es que esto sea posible de una manera no muy limpia.


grepparece que solo imprime la salida cuando encuentra un carácter de nueva línea, es probable que su barra de progreso no introduzca un carácter de nueva línea cuando se actualiza, de ahí su problema.

stracees una herramienta utilizada para ver las llamadas al sistema que realiza un comando, esto incluye cosas como leer y escribir cosas en la memoria/almacenamiento, así como cosas como abrir/cerrar descriptores de archivos.


Con stracepuede ver a qué proceso accede un proceso, en el caso de que su canalización stoutse pase a grep, por lo que stracepuede ver el texto al que se envía grep. straceSe enviará periódicamente el resultado procedente del comando canalizado, y podrá detectar ese resultado y mostrarlo. Estaba probando con rsync --progress, que parece encontrarse con un escenario similar. Utilicé grepel ##%porque eso es lo que rsyncse utiliza para mostrar el progreso.

rsync --progress file1 file2 | strace -e trace=read grep "[0-9]*%"

Si ejecuta este comando, encontrará que straceno tiene un buen resultado, pero cuando lo usé stracecaptó un par de readmensajes rsyncque grepnormalmente no aparecerían write, mostrando readmensajes para 0%, 21%, 45%, 68%, El 91% y el 100% parecían actualizarse aproximadamente cada segundo (probablemente según la frecuencia con la que rsyncse actualiza el progreso).

Entonces con eso puedes obtener grepel straceresultado, lo cual no es muy agradable, llamando a lo mismo grepnuevamente.

rsync --progress file1 file2 | strace -e trace=read grep "[0-9]*%" 2>&1 > /dev/null | grep -o "[0-9]*%"

Es 2>&1importante porque stracese imprime en stderr. Las > /dev/nullredirecciones stdouta para evitar que se informe /dev/nullla salida del primero . grepEl resultado final de esto fue el siguiente resultado:

0%
21%
45%
68%
91%
100%

Tendrás que cambiar el grep, pero parece que funcionará. No es bonito, pero funciona y evita las restricciones de grep. Parece que un grep -fsistema que funciona tail -fsería útil (sé que grep -fya está en uso).

La primera grepes principalmente para filtrar el texto que stracese enviará read, ya que solo las líneas coincidentes se enumerarán en stracelas readllamadas, pero también necesita algo por lo que el texto se mueva para stracepoder verlo.

Respuesta2

Estoy gastando la respuesta de Centimane ya que la respuesta final es bastante complicada.

Ya era bastante complicado... ahora se vuelve realmente cutre:

make flash \
    |& strace -e trace=read grep -e "^\." -e rror \
    |& stdbuf -o0 sed -ne 's/^.*"\.".*/\./p;/rror/p' \
    | stdbuf -o0 tr -d '\n' \
    ; echo

Entonces lo make flashanterior está llamando openocd;

straceestá utilizando el truco de Centimane explicado anteriormente;

sedreemplazar read(0, ".", xxx)líneas por simples .;

tres mantener todo .en una línea, y el eco final es poner el único EOL.

Además de eso, sedy trse llaman con stdbuf -o0lo que establece el tamaño del búfer de salida estándar en 0 (porque se eliminó EOL), y grep/sedtambién coinciden (e)rrorpara imprimir algo de basura en caso de error.

Intenté factorizar toda esta hinchazón al mínimo, pero no pude hacerlo mejor.

Tenga en cuenta también que estoy usando zsh/Ubuntu 14.04 y no estoy seguro de que esto pueda funcionar en otros Unix.

información relacionada