Вопрос

Я пишу графический обработчик URI для Git: // ссылки с Bash и Zenity, и я использую диалоговое окно «Текстовое сообщение Zenity», чтобы показать выход клона 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 Выводит сообщения о ходе прогресса (что-то кроме «инициализированного» сообщения) на STDERR, но в тот момент, когда я пытаюсь трусить 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, но она еще не решила проблему. На данный момент, используя один, другой или оба, работает в теории, но на практике Зенити ничего не показывает вообще ничего.

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

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

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

После выполнения некоторого исходного кода Raceing и проверки GIT я понимаю, что GIT выводит всю свою информацию о прогрессе (что-либо прошедшее «инициализированное» сообщение) на СтДерре, и тот факт, что это первая линия и мое предположение, что это из-за кота Выхождение в начале EOF было совпадение / ошибочное предположение (Git не EOF, пока программа не заканчивается).

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

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

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

Это происходит против всего, что я знаю о Стдерре и перенаправлении; Я даже написал небольшую программу C, которая выводит на STDERR и Stdout, чтобы доказать себе, что перенаправление просто не работает для Git.

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

В соответствии с ответом Jakub Narębski, а также ответы на электронные письма, которые я отправил в список рассылки Git, --progress Является ли вариант, который мне нужен. Обратите внимание, что эта опция работает только после команды, а не раньше clone.

Успех!

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

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

Это было полезно?

Решение

Я думаю, что, по крайней мере, некоторые отчеты о ходе работы захотется, когда вывод не терминал (tty). Я не уверен, применяется ли это к вашему делу, но попытаться пройти --progress Возможность «Git Clone» (IE Использование git clone --progress <repository>).

Хотя я не знаю, если это то, что вы хотели иметь.

Другие советы

Для одной вещи выходное перенаправление анализируется влево налево, так

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

не равно

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

Последний будет перенаправлять STDERR в STDOUT, а затем stdout (включая STDERR) в файл. Первый будет перенаправлять stdout к файлу, а затем показать STDERR на STDOUT.

Что касается трубопровода к zenity (который я не знаю), я думаю, вы можете сделать вещи чрезмерно сложными с именованной трубой. С использованием strace Может пролить свет на внутреннюю работу процессов, которые вы стремитесь. Для неопытных, названных труб делают вещи хуже по сравнению с обычными трубами.

Учитывая эксперимент с ФИФО «А», я думаю, что проблема заключается в том, как ранец обрабатывает свой вклад. Что произойдет, если вы введете в Zenity с клавиатуры? (Подозрение: он ведет себя так, как вы хотели, читая EOF.) Однако это может быть то, что Zenity обрабатывает вход клеммы (вход TTY), используя обычную блокировку ввода / вывода, но использует неблокирующие ввод / вывод для всех других типов устройств. Неблокирующий ввод / вывод для ввода из файлов; Он менее желательна для входа из труб или FIFOS и т. Д. Если он использовал неблокирующий ввод / вывод, ZENITY получит первую строку вывода, а затем выйти из петли, думая, что это было сделано, потому что его вторая попытка чтения укажет, что Не было ничего не было немедленно доступно.

Демонстрируя, что это то, что происходит (или нет) будет сложно. Я бы искал «ферму» или «stroace» или другой монитор системного вызова для отслеживания того, что делает Zenity.

Что касается обработки ... Если гипотеза верна, то вам нужно убедить Зенита, что это чтение от терминала, а не пофокуссированного, поэтому вам, вероятно, нужно будет запустить псевдо- TTY (или PTY); Первый процесс напишет на главный конец PTY, и вы договорились о Zenity, чтобы прочитать из рабского конца PTY. Вы все равно можете использовать ФИФО - хотя это делает длинную цепочку командования.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top