Question

J'écris un gestionnaire d'URI graphique pour git: // liens avec bash et zenity, et je suis sur un zenity « text-info » boîte de dialogue à la sortie du clone de git show alors qu'il est en cours d'exécution, en utilisant la tuyauterie FIFO. Le script est d'environ 90 lignes, donc je ne vais pas le poster ici, mais voici les lignes les plus importantes:

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

J'utilise FIFO au lieu d'un tuyau directement pour leur permettre de fonctionner de manière asynchrone et permettent de tuer git si la fenêtre est fermée zenity.

Le problème est, la seule ligne qui apparaît à partir de la sortie de git est le premier:

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

Les autres lignes avec des objets de comptage, etc. ne montrent pas ou sont affichés sur le terminal.

raison actuelle

Le consensus actuel pour expliquer pourquoi cela ne fonctionne pas semble être que cat est non bloquant et les départs volontaires après la première ligne, ne passant que de zenity et non le reste. Mon but est de forcer le blocage de la lecture, et ont l'info texte zenity DIALOG afficher toutes les sorties progressivement.

sorties git messages de progression (autre chose que le message « Initialisé ») sur stderr, mais le moment j'essaie de tuyau stderr vers un fichier ou de fusionner avec stdout, les messages disparaissent.

Fix tentative 1

J'ai essayé d'écrire deux versions de blocage des fonctions de chat en C, du pain et bwrite, comme ceci:

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

Ils travaillent bien parce qu'ils bloquent et ne quittez pas EOF, mais il n'a pas tout à fait encore résolu le problème. En ce moment, en utilisant l'un, l'autre, ou les deux, les travaux en théorie, mais dans la pratique, Zenity montre rien du tout maintenant.

Fix tentative 2

@mvds a suggéré que l'utilisation d'un fichier régulier, en combinaison avec tail -f plutôt que cat, peut le faire. Surpris à une telle solution simple (merci!) Je l'ai essayé mais malheureusement, seule la première ligne a montré dans zenity et rien d'autre.

Fix tentative 3

Après avoir fait quelques strace'ing et inspecter le code source de git, je me rends compte que git sorties toutes ses informations de progression (quoi que ce soit passé le message « Initialisé ») sur stderr, et le fait que ce soit la première ligne et je suppose que c'est à cause du chat de quitter tôt EOF était une coïncidence / hypothèse erronée (git ne EOF jusqu'à la fin du programme).

La situation semblait devenir beaucoup plus simple, comme je ne devrais pas avoir à quoi que ce soit le changement du code d'origine (au début de la question) et il devrait fonctionner. Mystérieusement, cependant, la sortie stderr « disparaît » quand redirigée -. Et ce n'est quelque chose qui se passe dans git

cas de test? Essayez ceci, et voyez si vous voyez quoi que ce soit dans le fichier (vous ne):

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

Cela va contre tout ce que je sais stderr et redirection; J'ai même écrit un petit programme C que les sorties sur stderr et stdout pour me prouver que la redirection ne fonctionne tout simplement pas git.

Fix tentative 4

Conformément à la réponse de Jakub Narębski, ainsi que des réponses aux e-mails que j'envoyées à la liste de diffusion git, --progress est l'option que j'ai besoin. Notez que cette option ne fonctionne que après la commande, et pas avant clone.

Succès!

Merci beaucoup pour votre aide. Ceci est la ligne fixe:

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

Était-ce utile?

La solution

Je pense qu'au moins certains des rapports d'avancement réduits au silence lorsque la sortie obtient est pas un terminal (TTY). Je ne sais pas si elle applique à votre cas, mais essayez de passer --progress option 'clone git' (à savoir l'utilisation de git clone --progress <repository>).

Bien que je ne sais pas si c'est ce que vous voulez avoir.

Autres conseils

D'une part, la redirection de sortie est analysée de droite à gauche, donc

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

est pas égal à

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

Ce dernier redirigera stderr vers stdout, puis stdout (y compris stderr) dans le fichier. L'ancien Redirigera stdout au fichier, puis montrer stderr sur la sortie standard.

En ce qui concerne la tuyauterie à zenity (que je ne sais pas), je pense que vous pouvez faire des choses trop compliquées avec le tube nommé. L'utilisation strace peut faire la lumière sur le fonctionnement interne des processus vous tir vers le haut. Pour les novices, les pipes nommés font qu'empirer les choses par rapport à des conduites normales.

Compte tenu de l'expérience avec le FIFO appelé « a », je pense que les mensonges de problème dans la façon dont les processus zenity de son entrée. Qu'advient-il si vous tapez dans zenity à partir du clavier? (Suspicion: il se comporte comme vous voudriez, la lecture à EOF). Cependant, il se pourrait que les poignées de Zenity entrée de la borne (entrée TTY) en utilisant le blocage régulier E / S mais utilise E / S non bloquantes pour tous les autres types de périphériques. Non bloquante E / S est très bien pour la saisie de fichiers; il est moins souhaitable pour l'entrée des tuyaux ou FIFOs, etc. Si elle ne l'utilisation non bloquante E / S, zenity obtiendrait la première ligne de sortie, puis sortir de la boucle pensée il a été fait parce que sa deuxième tentative de lecture indiquerait que il n'y avait rien d'autre immédiatement disponible.

Démontrer que c'est ce qui se passe (ou non) sera délicate. Je chercherai à « ferme » ou « strace » ou autre moniteur d'appel système pour suivre ce que zenity est en train de faire.

Pour ce qui est des solutions de contournement ... si l'hypothèse est correcte, alors vous aurez besoin de convaincre zenity qu'il est en train de lire à partir d'un terminal et non une FIFO, de sorte que vous aurez probablement besoin de truquer un pseudo-TTY (ou pty); le premier processus écrirait à la fin de maître du pty et vous feriez les dispositions nécessaires pour zenity à lire à partir de l'extrémité esclave du pty. Vous pouvez toujours utiliser le FIFO trop -. Si elle fait une longue chaîne de commandement

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top