
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 grep
que solo se muestre la línea con la barra de progreso y en tiempo real (es decir, cada punto generado openocd
se imprime inmediatamente en la terminal):
openocd <args> |& grep '^\.'
El problema es que grep
está 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 grep
o existe alguna alternativa estándar para lograr esto? Si hay una forma de realizar openocd
la 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.
grep
parece 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.
strace
es 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 strace
puede ver a qué proceso accede un proceso, en el caso de que su canalización stout
se pase a grep
, por lo que strace
puede ver el texto al que se envía grep
. strace
Se 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é grep
el ##%
porque eso es lo que rsync
se utiliza para mostrar el progreso.
rsync --progress file1 file2 | strace -e trace=read grep "[0-9]*%"
Si ejecuta este comando, encontrará que strace
no tiene un buen resultado, pero cuando lo usé strace
captó un par de read
mensajes rsync
que grep
normalmente no aparecerían write
, mostrando read
mensajes para 0%, 21%, 45%, 68%, El 91% y el 100% parecían actualizarse aproximadamente cada segundo (probablemente según la frecuencia con la que rsync
se actualiza el progreso).
Entonces con eso puedes obtener grep
el strace
resultado, lo cual no es muy agradable, llamando a lo mismo grep
nuevamente.
rsync --progress file1 file2 | strace -e trace=read grep "[0-9]*%" 2>&1 > /dev/null | grep -o "[0-9]*%"
Es 2>&1
importante porque strace
se imprime en stderr
. Las > /dev/null
redirecciones stdout
a para evitar que se informe /dev/null
la salida del primero . grep
El 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 -f
sistema que funciona tail -f
sería útil (sé que grep -f
ya está en uso).
La primera grep
es principalmente para filtrar el texto que strace
se enviará read
, ya que solo las líneas coincidentes se enumerarán en strace
las read
llamadas, pero también necesita algo por lo que el texto se mueva para strace
poder 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 flash
anterior está llamando openocd
;
strace
está utilizando el truco de Centimane explicado anteriormente;
sed
reemplazar read(0, ".", xxx)
líneas por simples .
;
tr
es mantener todo .
en una línea, y el eco final es poner el único EOL.
Además de eso, sed
y tr
se llaman con stdbuf -o0
lo que establece el tamaño del búfer de salida estándar en 0 (porque se eliminó EOL), y grep/sed
también coinciden (e)rror
para 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.