在 Bash 变量中捕获 Git 输出

在 Bash 变量中捕获 Git 输出

我想要捕获如下命令执行输出:

$ o=$( git clone [email protected]:my-repo/demo.git )
Cloning into 'demo'...
remote: Counting objects: 176, done.
remote: Compressing objects: 100% (94/94), done.
remote: Total 176 (delta 84), reused 162 (delta 77)
Receiving objects: 100% (176/176), 32.98 KiB | 2.75 MiB/s, done.
Resolving deltas: 100% (84/84), done.

$ echo "$o"
    # Empty.

好吧,你可以说我笨,我还没有重定向输出。所以:

$ o=$( git clone [email protected]:my-repo/demo.git 2>&1 )

我的控制台上没有打印任何内容,所以我开始乐观起来并继续:

$ echo "$o"
Cloning into 'demo'...

这就是全部了。 打印的其他许多行git根本没有存储到我的o变量中。

然后我尝试在子 shell 中运行该命令然后重定向:

$ o=$( (git clone [email protected]:my-repo/demo.git) 2>&1 )

$ echo "$o"
Cloning into 'demo'...

这里发生了什么事?


注意:我试着做功课,但帖子如下如何将 git 命令的输出存储在变量中?只需告诉我我尝试过并失败的第一件事。许多其他链接只是重复相同的内容。

答案1

答案:

添加--progressgit clone强制打印进度。

解释:

好的,我现在已经做了很多作业。

Git 文档相当微妙:

--progress 默认情况下在标准错误流上报告进度状态当它连接到终端时,除非指定了 --quiet。即使标准错误流未定向到终端,此标志也会强制显示进度状态。

因此,不是印刷进度,,git无论出于何种原因,被认为是不是连接至终端。

我天真的理解是这样的:

$ o=$( git clone [email protected]:my-repo/demo.git 2>&1 )

仿佛两者stdout stderr会映射到相同的pts所以我lsof在 3 种不同的场景中运行了一些。

1:只运行命令,不捕获

$ git clone [email protected]:my-repo/demo.git
$ bash -c '{ lsof -a -p $(pidof git)  -d0,1,2; }'
COMMAND   PID         USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
git     39542         j4x    0u   CHR  136,7      0t0     10 /dev/pts/7
git     39542         j4x    1w  FIFO   0,13      0t0 233734 /dev/pts/7
git     39542         j4x    2w  FIFO   0,13      0t0 233734 /dev/pts/7

2:捕获输出,无重定向

$ o=$( git clone [email protected]:my-repo/demo.git )
~ $ bash -c '{ lsof -a -p $(pidof git)  -d0,1,2; }'
COMMAND   PID         USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
git     39859         j4x    0u   CHR  136,7      0t0     10 /dev/pts/7
git     39859         j4x    1w  FIFO   0,13      0t0 233734 /dev/pts/7
git     39859         j4x    2w  FIFO   0,13      0t0 233734 pipe

我愚蠢地期望它以与“1:”相同的方式打印,但我错了,发现 Bash 使用来pipe捕获进程输出并将其写入变量。

我不知道!

3:捕获输出,重定向stderr

$ o=$( git clone [email protected]:my-repo/demo.git 2>&1 )
~ $ bash -c '{ lsof -a -p $(pidof git)  -d0,1,2; }'
COMMAND   PID         USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
git     40170         j4x    0u   CHR  136,7      0t0     10 /dev/pts/7
git     40170         j4x    1w  FIFO   0,13      0t0 233734 pipe
git     40170         j4x    2w  FIFO   0,13      0t0 233734 pipe

现在一切都说得通了!

Apipe不是 tty (isatty()),由于git会检查 tty stderr,所以不会打印进度。您需要使用 强制执行此操作--progress

我希望这对其他人有用。

参考

相关内容