Pregunta

Estoy escribiendo un controlador gráfico URI para git: // vínculos con bash y zenity, y estoy usando un 'texto-info' de diálogo zenity a la salida de git clone espectáculo mientras se está ejecutando, utilizando FIFO tuberías. El guión es de aproximadamente 90 líneas de largo, así que no voy a molestar publicar aquí, pero aquí es 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 usando FIFO en lugar de una tubería directa para permitir que se ejecuten de forma asincrónica y permiten matar git si la ventana está cerrada zenity.

El problema es que la única línea que aparece a partir de la salida de Git es el primero:

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

Las otras líneas con objetos de recuento, etc. no muestran o se muestran en el terminal.

razón actual

El consenso actual de por qué esto no está funcionando parece ser que se cat no bloqueante y se cierra después de la primera línea, sólo el paso, que a Zenity y no el resto. Mi objetivo es forzar el bloqueo de la lectura, y tienen información de texto de Zenity de diálogo Mostrar toda la salida progresiva.

salidas git mensajes de progreso (otra cosa que el mensaje "iniciada") en stderr, pero el momento en que tratan de tubería stderr a un archivo o en combinación con la salida estándar, los mensajes desaparecen.

Fix intento 1

He tratado de escribir dos versiones de bloqueo de funciones de gato en C, pan y bwrite, como esto:

#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);
    }
}

Ellos trabajan muy bien porque bloquean y no dejar de fumar en el EOF, pero bastante no ha resuelto el problema todavía. Por el momento, el uso de uno, el otro o ambos, trabajos en teoría, pero en la práctica, espectáculos de Zenity nada en absoluto ahora.

Fix intento 2

@mvds sugiere que el uso de un archivo normal, en combinación con tail -f en lugar de cat, puede hacer esto. Sorprendido por una solución tan simple (¡gracias!) Lo probé pero, por desgracia, sólo la primera línea se presentó en Zenity y nada más.

Fix intento 3

Después de hacer algunas strace'ing e inspeccionar el código fuente de Git, que da cuenta de que git salidas toda su información de progreso (nada más allá del mensaje "iniciada") en stderr, y el hecho de que esta es la primera línea y mi suposición de que es debido gato dejar de fumar desde el principio fue un EOF / suposición equivocada coincidencia (GIT no lo hace EOF hasta el final del programa).

La situación parecía ser mucho más sencillo, 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 redirigida -. Y esto es sólo algo que ocurre en git

caso

Prueba? Prueba de esto, y ver si ves algo en el archivo (que 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 redirección; Incluso he escrito un pequeño programa C que las salidas en stderr y stdout para probar a mí mismo que la redirección simplemente no funciona para Git.

Fix intento 4

De acuerdo con la respuesta de Jakub Narebski, así como las respuestas a los correos electrónicos que he enviado a la lista de correo de git, --progress es la necesidad de que la opción. Tenga en cuenta que esta opción sólo funciona después de la orden, y no antes clone.

Éxito!

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

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

¿Fue útil?

Solución

creo que al menos algunos de los informes de progreso consigue silenciados cuando la salida es no un terminal (TTY). No estoy seguro de si se aplica a su caso, pero trato de pasar --progress a 'git clone' (es decir, el uso git clone --progress <repository>).

A pesar de que no sé si es lo que quería tener.

Otros consejos

Por un lado, la redirección de la salida se analiza derecha a izquierda, de modo

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

no es igual a

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

Este último será redirigir stderr a stdout, y luego la salida estándar (incluyendo stderr) al archivo. El primero será redirigir la salida estándar al archivo, y luego mostrar stderr en la salida estándar.

En cuanto a las tuberías a zenity (que no sé), creo que se le puede hacer cosas demasiado complicadas con la canalización con nombre. Usando strace puede arrojar alguna luz sobre el funcionamiento interno de los procesos que está disparando hacia arriba. Para los inexpertos, canalizaciones con nombre hacen cosas peores en comparación con tubos normales.

Dado el experimento con la FIFO llama 'a', creo que el problema radica en la forma en que los procesos de Zenity su entrada. ¿Qué pasa si se teclea en zenity desde el teclado? (La sospecha: se comporta como te gustaría, leyendo a EOF). Sin embargo, podría ser que las manijas de Zenity terminal de entrada (entrada TTY) usando bloqueo regular de E / S, pero los usos no-bloqueo de E / S para todos los otros tipos de dispositivos. Sin bloqueo de E / S está muy bien para la entrada de archivos; es menos deseable para la entrada de las tuberías o FIFOs, etc. si lo hiciera uso de no bloqueo I / O, zenity sería obtener la primera línea de salida y, a continuación salir del bucle pensando que se hizo porque su intento segunda lectura indicaría que no había nada más disponible inmediatamente.

Demostrando que esto es lo que está pasando (o no) será complicado. Que estaría mirando a 'armadura' o 'strace' u otro monitor llamada al sistema para realizar un seguimiento de lo que está haciendo zenity.

En cuanto a soluciones ... si la hipótesis es correcta, entonces tendrá que convencer a zenity que está leyendo desde un terminal y no un FIFO, por lo que probablemente tendrá que montar un pseudo-tty (o pty); el primer proceso escribiría a finales maestro de la pty y había arreglos para zenity a leer desde el extremo esclavo del pty. Todavía se puede utilizar la FIFO también -. Pesar de que hace una larga cadena de mando

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top