saída git stderr não pode canalizar
Estou escrevendo um manipulador gráfico de URI para o git: // links com bash e zenity, e estou usando uma caixa de diálogo 'text-info' do zenity para mostrar a saída do clone do git enquanto estiver em execução, usando a tubulação FIFO. O script tem cerca de 90 linhas, por isso não me incomodo em publicá-lo aqui, mas aqui estão as linhas mais importantes:
git clone "$1" "$target" 2>&1 | cat >> /tmp/githandler-fifo &
cat /tmp/githandler-fifo | zenity --text-info --text='Cloning git repository' &
Estou usando o FIFO em vez de um canal direto para permitir que eles sejam executados de forma assíncrona e permitem matar o git se a janela do zenity estiver fechada.
O problema é que a única linha que aparece na saída do git é a primeira:
Initialized empty Git repository in /home/delan/a/.git/
As outras linhas com objetos de contagem etc. não são exibidas ou são mostradas no terminal.
Razão atual
O consenso atual sobre por que isso não está funcionando parece sercat
é sem bloqueio e sai após a primeira linha, passando apenas para o zenity e não para o resto. Meu objetivo é forçar o bloqueio para a leitura e exibir o diálogo de informações de texto do zenity progressivamente.
git
gera mensagens de progresso (qualquer coisa que não seja a mensagem "Initialized") no stderr, mas no momento em que tento canalizar o stderr para um arquivo ou mesclar com o stdout, as mensagens desaparecem.
Corrigir tentativa 1
Eu tentei escrever duas versões de bloqueio das funções do gato em C, bread e bwrite, assim:
#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);
}
}
Eles funcionam bem porque bloqueiam e não param no EOF, mas isso ainda não resolveu o problema. No momento, usando um, o outro, ou ambos, funciona na teoria, mas na prática, a zenidade não mostra nada agora.
Corrigir tentativa 2
O @mvds sugeriu que o uso de um arquivo comum, combinado comtail -f
ao invés decat
, pode fazer isso. Surpreso com uma solução tão simples (obrigado!) Eu tentei, mas infelizmente, apenas a primeira linha apareceu em zenity e nada mais.
Corrigir tentativa 3
Depois de rastrear e inspecionar o código-fonte do git, percebo que o git gera todas as suas informações de progresso (qualquer coisa após a mensagem "Inicializada") no stderr, e o fato de que essa é a primeira linha e minha suposição de que é por causa do gato encerrar o EOF no início era uma suposição coincidente / equivocada (o git não faz EOF até o programa terminar).
A situação parecia se tornar muito mais simples, pois eu não deveria ter que alterar nada do código original (no início da pergunta) e deve funcionar. Misteriosamente, no entanto, a saída stderr 'desaparece' quando redirecionada - e isso é apenas algo que acontece no git.
Caso de teste? Tente isso e veja se você vê algo no arquivo (não verá):
git clone git://anongit.freedesktop.org/xorg/proto/dri2proto 2> hurr
Isso vai contra tudo o que sei sobre stderr e redirecionamento; Eu até escrevi um pequeno programa em C que sai no stderr e stdout para provar para mim mesmo que o redirecionamento simplesmente não funciona para o git.
Corrigir tentativa 4
De acordo com a resposta de Jakub Narębski, bem como as respostas aos e-mails que enviei à lista de discussão git,--progress
é a opção que eu preciso. Observe que esta opção funciona apenas após o comando, e não antesclone
.
Sucesso!
Muito obrigado por toda sua ajuda. Esta é a linha fixa:
git clone "$1" "$target" --progress > /tmp/githandler-fifo 2>&1 &