git stderr salida no puede tubería

Estoy escribiendo un controller gráfico de URI para git: // enlaces con bash y zenity, y estoy usando un cuadro de dialog zenity 'text-info' para mostrar la salida de clonación de git mientras se está ejecutando, utilizando tuberías FIFO. El script tiene 90 líneas, así que no me molestaré en publicarlo aquí, pero aquí están las líneas más importantes:

git clone "$1" "$target" 2>&1 | cat >> /tmp/githandler-fifo & cat /tmp/githandler-fifo | zenity --text-info --text='Cloning git repository' & 

Estoy utilizando FIFO en lugar de un conducto directo para permitir que se ejecuten de forma asincrónica y permitir matar a git si la window de zenity está cerrada.

El problema es que la única línea que aparece en la salida de git es la primera:

 Initialized empty Git repository in /home/delan/a/.git/ 

Las otras líneas con conteo de objects, etc. no se muestran o se muestran en la terminal.

Razón actual

El consenso actual sobre por qué esto no funciona parece ser que el cat no bloquea y se retira después de la primera línea, solo pasando eso al zenity y no al rest. Mi objective es forzar el locking de la lectura, y hacer que el cuadro de dialog de text de zenity muestre todos los resultados de forma progresiva.

git genera posts de progreso (cualquier cosa que no sea el post "Inicializado") en stderr, pero en el momento en que bash conectar el stderr a un file o fusionarlo con stdout, los posts desaparecen.

Intento de reparación 1

Intenté escribir dos versiones de locking de las funciones de gato en C, pan y bwrite, así:

 #include <stdio.h> main(int argc, char **argv) { int c; for (;;) { freopen(argv[1], "r", stdin); while ((c = getchar()) != EOF) putchar(c); } } #include <stdio.h> main(int argc, char **argv) { int c; for (;;) { freopen(argv[1], "w", stdout); while ((c = getchar()) != EOF) putchar(c), fputs("writing", stderr); } } 

Funcionan bien porque se bloquean y no se detienen en EOF, pero aún no ha resuelto el problema. Por el momento, usar uno, el otro o ambos funciona en teoría, pero en la práctica, el zenity no muestra nada ahora.

Intento de reparación 2

@mvds sugirió que usar un file común, en combinación con tail -f vez de cat , puede hacer esto. Sorprendido por una solución tan simple (¡gracias!) Lo intenté, pero desafortunadamente, solo la primera línea apareció en zenity y nada más.

Intento de reparación 3

Después de hacer un poco de straceing e inspeccionar el código fuente de Git, me doy count de que Git genera toda su información de progreso (algo más allá del post "Inicializado") en stderr, y el hecho de que esta es la primera línea y mi suposition de que es por gato dejar de fumar temprano en EOF fue una suposition de coincidencia / equivocada (git no EOF hasta que finaliza el progtwig).

La situación parecía ser mucho más simple, ya que no debería tener que cambiar nada del código original (al comienzo de la pregunta) y debería funcionar. Misteriosamente, sin embargo, la salida stderr 'desaparece' cuando se networkingirige, y esto es solo algo que sucede en git.

¿Caso de testing? Pruebe esto y vea si ve algo en el file (no lo hará):

 git clone git://anongit.freedesktop.org/xorg/proto/dri2proto 2> hurr 

Esto va en contra de todo lo que sé sobre stderr y la networkingirección; Incluso he escrito un pequeño progtwig de C que da salida en stderr y stdout para probarme a mí mismo que la networkingirección simplemente no funciona para git.

Intento de reparación 4

De acuerdo con la respuesta de Jakub Narębski, así como las respuestas a los correos electrónicos que envié a la list de correo git, el --progress es la opción que necesito. Tenga en count que esta opción solo funciona después del command, y no antes de clone .

¡Éxito!

Muchas gracias por toda tu ayuda. Esta es la línea fija:

 git clone "$1" "$target" --progress > /tmp/githandler-fifo 2>&1 & 

Creo que al less algunos de los informes de progreso se silencian cuando la salida no es un terminal (tty). No estoy seguro de si se aplica a su caso, pero trate de pasar la opción de --progress a 'git clone' (es decir, use git clone --progress <repository> ).

Aunque no sé si es lo que querías tener.

Por un lado, la networkingirección de salida se analiza de derecha a izquierda, por lo que

 git clone "$1" "$target" 2>&1 > /tmp/githandler-fifo & 

no es igual a

 git clone "$1" "$target" > /tmp/githandler-fifo 2>&1 & 

Este último networkingireccionará stderr a stdout, y luego stdout (incluido stderr) al file. El primero networkingireccionará stdout al file y luego mostrará stderr en stdout.

En cuanto a la canalización al zenity (que no sé), creo que puede estar haciendo las cosas demasiado complicadas con la tubería con nombre. Usar strace puede arrojar algo de luz sobre el funcionamiento interno de los processs que está activando. Para los inexpertos, las tuberías nombradas empeoran las cosas en comparación con las tuberías normales.

Dado el experimento con el FIFO llamado 'a', creo que el problema radica en la forma en que zenity procesa su input. ¿Qué sucede si escribe en zenity desde el keyboard? (Sospecha: se comporta como lo desearía, leyendo a EOF). Sin embargo, podría ser que zenity maneje la input del terminal (input tty) usando E / S de locking regular, pero usa E / S sin locking para todos los demás types de dispositivos. La E / S sin locking está bien para la input de files; es less deseable para la input desde tuberías o FIFO, etc. Si utilizara E / S sin locking, zenity obtendría la primera línea de salida, y luego saldría del bucle pensando que estaba hecho porque su segundo bash de lectura indicaría que no había nada más disponible de inmediato.

Demostrar que esto es lo que está sucediendo (o no) será complicado. Yo searchía 'truss' o 'strace' u otro monitor de llamada al sistema para rastrear lo que está haciendo zenity.

En cuanto a las soluciones alternativas … si la hipótesis es correcta, entonces tendrá que convencer a zenity de que está leyendo desde un terminal y no desde un FIFO, por lo que probablemente necesite instalar un pseudo-tty (o pty); el primer process escribiría en el extremo maestro de la pty y usted se encargaría de leer el zenity desde el extremo esclavo de la pty. También podría usar el FIFO también, aunque tenga una larga cadena de command.