【发布时间】:2011-05-03 01:10:04
【问题描述】:
我正在为带有 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 和重定向的一切背道而驰;我什至写了一个小 C 程序,它在 stderr 和 stdout 上输出,以向自己证明重定向对 git 不起作用。
修复尝试 4
根据 Jakub Narębski 的回答,以及对我发送到 git 邮件列表的电子邮件的回复,--progress 是我需要的选项。请注意,此选项仅在命令之后有效,而在 clone 之前无效。
成功了!
非常感谢您的所有帮助。这是固定线路:
git clone "$1" "$target" --progress > /tmp/githandler-fifo 2>&1 &
【问题讨论】:
-
天哪……你救了我的命……碰巧遇到了同样的问题
-
成功!感谢那。 --progress 对我来说是拼图中缺失的部分。
标签: git bash pipe named-pipes zenity