git stderr output cannot pipe

Я пишу графический обработчик 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' &

I ' m, используя FIFO вместо прямого канала, чтобы позволить им работать асинхронно и разрешить уничтожение git, если окно zenity закрыто.

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

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

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

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

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

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

Попытка исправления 1

Я попытался написать две блокирующие версии функций cat на C, хлеб и 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 , может это сделать. Удивленный таким простым решением (спасибо!), Я попробовал его, но, к сожалению, в zenity появилась только первая строка и ничего больше.

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

После некоторого strace'ing и проверки исходного кода git я поймите, что git выводит всю информацию о своем прогрессе (что-либо, кроме "Initialized" message) на 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 &

13
задан Delan Azabani 2 November 2010 в 02:41
поделиться