我尝试捕获输出并发现奇怪的行为。某些输出仅在未使用重定向时才会显示。可以使用此 docker 示例可靠地复制:
FROM alpine
RUN apk add git
RUN \
echo "echo \"----NO REDIRECT:\" && no_redirection=\$(git clone http://github.com/srfrnk/jabos-examples.git /tmp1)" >> test &&\
echo "echo \"----NO REDIRECT CAPTURED: \${no_redirection}\"" >> test &&\
echo "echo \"----REDIRECT:\" && redirection=\$(git clone http://github.com/srfrnk/jabos-examples.git /tmp2 2>&1)" >> test &&\
echo "echo \"----REDIRECT CAPTURED: \${redirection}\"" >> test &&\
cat test &&\
chmod +x test
ENTRYPOINT [ "/bin/sh","-c"]
CMD ["./test"]
这实际上是在容器中运行以下脚本:
echo "----NO REDIRECT:" && no_redirection=$(git clone http://github.com/srfrnk/jabos-examples.git /tmp1)
echo "----NO REDIRECT CAPTURED: ${no_redirection}"
echo "----REDIRECT:" && redirection=$(git clone http://github.com/srfrnk/jabos-examples.git /tmp2 2>&1)
echo "----REDIRECT CAPTURED: ${redirection}"
因此,有两个案例在运行git
- 一个有重定向,一个没有。两个输出都被捕获到一个变量中,然后被打印出来。
如果你构建并运行此程序(docker build . -t test && docker run -it test
),你会看到以下输出:
----NO REDIRECT:
Cloning into '/tmp1'...
warning: redirecting to https://github.com/srfrnk/jabos-examples.git/
remote: Enumerating objects: 195, done.
remote: Counting objects: 100% (195/195), done.
remote: Compressing objects: 100% (137/137), done.
remote: Total 195 (delta 106), reused 122 (delta 44), pack-reused 0
Receiving objects: 100% (195/195), 40.92 KiB | 498.00 KiB/s, done.
Resolving deltas: 100% (106/106), done.
----NO REDIRECT CAPTURED:
----REDIRECT:
----REDIRECT CAPTURED: Cloning into '/tmp2'...
warning: redirecting to https://github.com/srfrnk/jabos-examples.git/
PS 这不是 docker 的问题 - 在我的 Ubuntu 机器上的 bash 中也会出现这种情况。我使用 docker 来获得一个与环境无关的示例。
所以我的问题是输出之后warning: ...
到哪里以及如何重定向/捕获它?
答案1
您希望捕获的文本将进入STDERR
(文件流 2)。
在情况 1 中,您STDERR
默认放手到终端。
在情况 2 中,您没有运行git
。
在情况 3 中,您正在捕获变量中STDERR
的。 在情况 4 中,您没有运行。STDOUT
no_redirection
git
您的STDERR
文本未在“捕获”案例中被捕获,因为您的“捕获”案例实际上并未运行,这git
是因为您在行echo
上的嵌套语句中使用了引号----CAPTURED
。双引号转义了单引号,因此单引号是不是逃避变量扩展,因此变量在“测试”脚本文件被扩展时被扩展创建,而不是当它被执行。因此,no_redirection
和redirection
变量在测试脚本创建时扩展时不存在,因此它们被简单地删除并替换为空。因此,如果您查看“测试”脚本文件,我想您会发现它不包含您认为应该包含的内容。
STDERR
在非捕获“重定向”情况下,文本被捕获;它全部被指定为shell变量的值。redirection
这是因为您使用重定向到STDERR
,并且您捕获了(因此)通过使用分配给变量。STDOUT
2>&1
STDOUT
STDERR
redirection=$(…)
STDOUT
redirection