我想要捕获如下命令执行输出:
$ 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
答案:
添加--progress
到git 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
。
我希望这对其他人有用。