выход 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 &