我正在为带有 bash 和 zenity 的 git:// 链接编写一个图形 URI 处理程序,并且我正在使用 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 而不是直接管道来允许它们异步运行并允许在 zenity 窗口关闭时杀死 git。
问题是,从 git 的输出中出现的唯一一行是第一行:
Initialized empty Git repository in /home/delan/a/.git/
带有计数对象等的其他行不显示或显示在终端上。
当前原因
目前关于为什么这不起作用的共识似乎cat
是非阻塞并在第一行之后退出,仅将其传递给 zenity 而不是其余的。我的目标是强制阻止阅读,并让 zenity 的文本信息对话框逐步显示所有输出。
git
在 stderr 上输出进度消息(除了“初始化”消息之外的任何内容),但是当我尝试将 stderr 传输到文件或与 stdout 合并时,消息消失了。
修复尝试 1
我尝试用 C 语言编写 cat 函数的两个阻塞版本,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
,可以做到这一点。对如此简单的解决方案感到惊讶(谢谢!)我试过了,但不幸的是,只有第一行出现在 zenity 中,没有别的。
修复尝试 3
在做了一些 strace'ing 并检查了 git 的源代码之后,我意识到 git 在 stderr 上输出了它的所有进度信息(任何超出“初始化”消息的内容),事实上这是第一行,我假设这是因为 cat在 EOF 早期退出是一个巧合/错误的假设(git 直到程序结束才 EOF)。
情况似乎变得简单多了,因为我不应该对原始代码进行任何更改(在问题的开头),它应该可以工作。然而,奇怪的是,stderr 输出在重定向时会“消失”——这只是 git 中发生的事情。
测试用例?试试这个,看看你是否在文件中看到任何东西(你不会):
git clone git://anongit.freedesktop.org/xorg/proto/dri2proto 2> hurr
这与我所知道的关于标准错误和重定向的一切背道而驰;我什至编写了一个在 stderr 和 stdout 上输出的小 C 程序,以向自己证明重定向对 git 不起作用。
修复尝试 4
根据 Jakub Narębski 的回答,以及对我发送到 git 邮件列表的电子邮件的回复,--progress
是我需要的选项。请注意,此选项仅在命令之后有效,而在clone
.
成功!
非常感谢您的帮助。这是固定线路:
git clone "$1" "$target" --progress > /tmp/githandler-fifo 2>&1 &