重定向时命令输出丢失

重定向时命令输出丢失

我尝试捕获输出并发现奇怪的行为。某些输出仅在未使用重定向时才会显示。可以使用此 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 中,您没有运行。STDOUTno_redirection
git

您的STDERR文本未在“捕获”案例中被捕获,因为您的“捕获”案例实际上并未运行,这git是因为您在行echo上的嵌套语句中使用了引号----CAPTURED。双引号转义了单引号,因此单引号是不是逃避变量扩展,因此变量在“测试”脚本文件被扩展时被扩展创建,而不是当它被执行。因此,no_redirectionredirection变量在测试脚本创建时扩展时不存在,因此它们被简单地删除并替换为空。因此,如果您查看“测试”脚本文件,我想您会发现它不包含您认为应该包含的内容。

STDERR在非捕获“重定向”情况下,文本被捕获;它全部被指定为shell变量的值。redirection这是因为您使用重定向到STDERR,并且您捕获了(因此)通过使用分配给变量。STDOUT2>&1STDOUTSTDERRredirection=$(…)STDOUTredirection

相关内容