выход git stderr не может передать

Я пишу графический обработчик URI для ссылок git: // с bash и zenity, и я использую диалоговое окно zenity 'text-info', чтобы показать вывод клона git во время его работы, используя FIFO-конвейер. Сценарий длиной около 90 строк, поэтому я не буду публиковать его здесь, но вот самые важные строки:

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

Я использую FIFO вместо прямой трубы, чтобы позволить им работать асинхронно и убивать git, если окно zenity закрыто.

Проблема в том, что единственная строка, которая появляется из вывода git, является первой:

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

Другие строки с подсчетом объектов и т. Д. Не отображаются или отображаются на терминале.

Текущая причина

Нынешний консенсус относительно того, почему это не работает, кажется, чтоcat является неблокирующим и выходит после первой строки, передавая его только zenity, а не остальным. Моя цель состоит в том, чтобы принудительно блокировать чтение, и чтобы текстовое диалоговое окно zenity показывало все результаты постепенно.

git выводит сообщения о ходе выполнения (все, кроме сообщения «Initialized») на stderr, но в тот момент, когда я пытаюсь передать stderr в файл или объединить с stdout, сообщения исчезают.

Исправить попытку 1

Я попытался написать две блокирующие версии функций cat на C, bread и bwrite, например:

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

Они хорошо работают, потому что блокируют и не выходят из EOF, но это еще не решило проблему. В настоящее время использование одного, другого или обоих работает в теории, но на практике zenity сейчас вообще ничего не показывает.

Исправить попытку 2

@mvds предложил использовать обычный файл в сочетании сtail -f скорее, чемcatможет сделать это. Удивленный таким простым решением (спасибо!), Я попробовал его, но, к сожалению, только первая строка показалась в зените и больше ничего.

Исправить попытку 3

После некоторого изучения и проверки исходного кода git, я понимаю, что git выводит всю свою информацию о прогрессе (что-либо после сообщения «Initialized») на stderr, а также тот факт, что это первая строка и мое предположение, что это из-за cat преждевременное завершение EOF было совпадением / ошибочным предположением (git не EOF, пока программа не завершится).

Ситуация, казалось, стала намного проще, поскольку мне не нужно было ничего менять по сравнению с исходным кодом (в начале вопроса), и это должно работать. Однако при загадочных обстоятельствах вывод stderr «исчезает» при перенаправлении - и это только то, что происходит в git.

Прецедент? Попробуйте это, и посмотрите, видите ли вы что-нибудь в файле (вы не увидите):

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

Это противоречит всему, что я знаю о stderr и перенаправлении; Я даже написал небольшую C-программу, которая выводит на stderr и stdout, чтобы доказать себе, что перенаправление просто не работает для git.

Исправить попытку 4

В соответствии с ответом Якуба Наренбского, а также ответами на электронные письма, которые я отправил в список рассылки git,--progress это вариант, который мне нужен. Обратите внимание, что эта опция работает только после команды, а не доclone.

Успех!

Большое спасибо за вашу помощь. Это фиксированная линия:

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

Ответы на вопрос(3)

Ваш ответ на вопрос