这是我的full code,我使用:
char *args[] = {"git", "clone", "https://github.com/thinker3/youdao.git", "/tmp/youdao", NULL};
if (execv("/usr/bin/git", args) < 0) {
perror("error on exec");
exit(0);
}
在child中运行cmd,并使用:
捕获输出 char buffer[1024];
close(pipefd[1]); // close the write end of the pipe in the parent
while (read(pipefd[0], buffer, sizeof(buffer)) != 0) {
std::cout << buffer << std::endl;
}
在超级过程中,我得到了
Cloning into '/tmp/youdao'...
但我希望得到像终端一样的输出,怎么做?
roroco@roroco-Zhaoyang-K49 /tmp $ git clone https://github.com/thinker3/youdao.git
Cloning into 'youdao'...
remote: Counting objects: 434, done.
remote: Total 434 (delta 0), reused 0 (delta 0), pack-reused 434
Receiving objects: 100% (434/434), 221.51 KiB | 140.00 KiB/s, done.
Resolving deltas: 100% (275/275), done.
Checking connectivity... done.
更新
当然,我可以用libgit2来做,但这只是一个问题:为什么我不能得到git clone
完整的标准输出
答案 0 :(得分:3)
显然,根据git版本存在细微差别,因此我将描述我测试过的两个版本的行为。在这两个版本之间的某个时间,行为从第一个变为第二个。
git
写入stdout
的输出中唯一的部分是:
Cloning into 'youdao'...
其余部分,实际的克隆进度,只有在stderr
附加到终端时才会写入stderr
和。要使其始终将进度发送到stderr
,即使它未附加到终端(例如您的情况),也必须使用--progress
进行调用。见man git-clone
:
- 进度
默认情况下,标准错误流在连接到终端时会报告进度状态,除非指定了-q。即使标准错误流未定向到终端,此标志也会强制进度状态。
添加此参数后,您还必须:
read()
返回读取的字节数,并且不终止缓冲区); stderr
上获得的进度,因为它不会像您在终端中看到的那样格式化。从评论来看,这似乎不够明确,所以让我试着说得更清楚。
如果在终端中输入如下命令:
$ git clone "https://github.com/thinker3/youdao.git"
您将在终端获得此输出:
Cloning into 'youdao'...
Receiving objects: 100%
... (rest of progress info)
如果您输入这样的命令:
$ git clone "https://github.com/thinker3/youdao.git" 1>output.log
你会在output.log
中得到这个:
Cloning into 'youdao'...
在终端上:
Receiving objects: 100%
... (rest of progress info)
这意味着git
将Cloning into...
写入标准输出流(您已在文件中重定向)以及标准错误流上的进度信息,这些信息已保留在终端上。< / p>
如果您在终端上输入如下命令:
$ git clone "https://github.com/thinker3/youdao.git" 2>output.log
你会在终端上得到这个:
Cloning into 'youdao'...
因为我们已经确定这将是stdout,你在终端上留下了stdout。
该文件将为空!该帖子为空的原因由帖子开头的粗体文字描述。具体来说,git
仅在stderr转到终端时才会将进度信息打印到stderr
。在这种情况下,stderr
不会转到终端,因为您已将其重定向到某个文件,因此git
根本不会打印进度信息。
如果你想迫使git
将这个进度信息打印到stderr,即使stderr没有附加到终端,你必须明确地告诉它,如原始答案中所述,指定 - -progress 到git clone
,如下所示:
$ git clone --progress "https://github.com/thinker3/youdao.git" 2>output.log
现在,使用额外参数并将stderr
重定向到文件,您将在文件中找到进度信息。然而,它不会像你在终端上看到的那样格式化。这就是为什么我在原始答案中提到你必须解析并理解你从那个管道上读到的东西。
与上述描述的不同之处在于,现在输出的第一行Cloning into 'youdao'...
也转到stderr,并且此行(与进度信息文本的其余部分相对)无论是否写入stderr stderr是否连接到终端。只有当错误流进入终端时,其余的进度信息文本才会像以前一样发送到stderr。
所以现在你没有我上面几次提到的额外参数:
$ git clone "https://github.com/thinker3/youdao.git" 2>output.log
$ cat output1.log
Cloning into 'youdao'...
并使用额外的参数:
$ git clone --progress "https://github.com/thinker3/youdao.git" 2>output.log
$ cat output.log
Cloning into 'youdao'...
remote: Counting objects: 434, done.
remote: Total 434 (delta 0), reused 0 (delta 0), pack-reused 434
Receiving objects: 100% (434/434), 221.51 KiB | 135.00 KiB/s, done.
Resolving deltas: 100% (275/275), done.
Checking connectivity... done.
如果您希望能够通过该管道获取完整的进度信息文本,则必须使用 - 进度致电git clone
。
原始答案的其余部分保持不变: