从 git 捕获 STDOUT/STDERR

Posted

技术标签:

【中文标题】从 git 捕获 STDOUT/STDERR【英文标题】:Catching STDOUT/STDERR from git 【发布时间】:2013-04-30 11:36:10 【问题描述】:

我正在尝试通过 IPC::Run 从 perl 执行一个 git 命令,该命令在 perl 变量中捕获来自 git 的 STDOUT/STDERR-Output。

这是我所做的:

use strict;
use warnings;
use IPC::Run;
my $stderr, $stdout, @cmd;
push @cmd, "git";
push @cmd, "clone";
push @cmd, "http://my.gitserver.com/scm/tst2/abc.git";

my $success = IPC::Run::run \@cmd, '>', \$stdout, '2>', \$stderr;
1;

运行此结果:

$stdout: 正在克隆到 'abc'... $stderr: 空

从命令行直接运行 git 命令会产生以下输出:

$ git clone http://my.gitserver.com/scm/tst2/abc.git
Cloning into 'abc'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.

如您所见,git 在命令行中生成的输出比我在 perl 实现中实际捕获的输出要多。

怎么了?

【问题讨论】:

你检查 $stderr 变量了吗?另外,当我必须从 perl 管理 GIT 存储库时,我使用 Git::Repository 模块。 只有在 STDOUT 连接到终端时才会提供额外的输出。如果是这样,提供伪 TTY 可能会说服 git 输出它。请注意,它肯定会包含许多终端控制字符(回车和退格)。 @miguel-prz:正如我所说,$stderr 在我调用后是空的......在我的情况下使用Git::Repository 模块并不容易(因为我的“服务器”获取命令从远程机器执行并将结果写入共享沙箱——接收到的命令可以是“任何东西”——不仅是 git 命令……@ikegami:还不知道怎么做…… 当你使用 Run3 而不是 Run 时会发生什么?即:Run3(\@cmd,\$stdin,\$stdout,\$stderr); 【参考方案1】:

好消息是您的代码是正确的。令人困惑的部分是 git 根据标准错误是否连接到终端来更改其输出。

要从 shell 重现 Perl 程序的输出,请在 bash 提示符下运行以下命令。

$ git clone http://my.gitserver.com/scm/tst2/abc.git |& cat
克隆到 'abc'...

|& 重定向将 git 的标准错误(预期的进度输出所在的位置)和标准输出连接到管道而不是终端。

要查看通常的输出,您必须将 git 的标准错误连接到 pseudo terminal,也称为 pty。 IPC::Run 支持伪终端,在其文档的Pseudo Terminals section 中进行了描述。不要使用2> 重定向标准错误,而是使用2>pty>。请注意,这会增加对IO::Pty 的依赖。

调整run 重定向并添加调试输出,如下面的代码所示

#! /usr/bin/env perl

use strict;
use warnings;

use IPC::Run;

my $cloneurl = 'http://my.gitserver.com/scm/tst2/abc.git';

my($stderr,$stdout);
my @cmd = (qw/ git clone /, $cloneurl);

my $success = IPC::Run::run \@cmd, '>', \$stdout, '2>pty>', \$stderr;
print "success=[$success]\n";
print "stdout=[$stdout]\n";
print "stderr=[$stderr]\n";

产生类似于

的输出
成功=[1]
标准输出=[]
stderr=[正在克隆到 'abc'...
远程:计数对象:2818,完成。
远程:压缩对象:100% (1965/1965),完成。
远程:总计 2818(增量 1200),重复使用 770(增量 287)
接收对象:100% (2818/2818), 2.19 MiB | 1.19 MiB/s,完成。
解决增量:100% (1200/1200),完成。
检查连接...完成。
]

【讨论】:

以上是关于从 git 捕获 STDOUT/STDERR的主要内容,如果未能解决你的问题,请参考以下文章

捕获stdout以获取远程进程的子进程

使用参数 + stdout + stderr 从命令行调用 MFC 应用程序

如何从 Raspbian 上的 systemd 服务正确重定向 stdout/stderr?

命令输出(stdout,stderr)未重定向到管道

如何捕获从 python 子进程运行的 git clone 命令的输出

重定向stdin stdout stderr |