【问题标题】:Capturing stderr, but not stdout [duplicate]捕获标准错误,但不捕获标准输出 [重复]
【发布时间】:2016-04-09 20:46:57
【问题描述】:

在我的 bash 脚本中,我读到了一组看起来像这样的行

arg $PROG arg arg

我希望能够运行该行,将 STDERR 作为变量捕获,并防止 STDOUT 或 STDERR 打印到屏幕上。到目前为止,这是我的解决方案,但错误变量始终为空。

$PROG=/c/Program1
{ error=$($(eval $line) 2>&1 1>&$out); } {out}>&1
echo $error

请彻底解释解决方案。我是 bash shell 脚本和尝试学习的新手。

【问题讨论】:

标签: bash shell


【解决方案1】:

对于像这样同时打印到 stdout 和 stderr 的命令:

mycommand () { echo "stdout"; echo "stderr" >&2; }

如果我正常发出,我会看到所有输出:

$ mycommand
stdout
stderr

我可以将 stdout 或 stderr 重定向到 /dev/null,这样它就不会被打印出来:

$ mycommand >/dev/null    # Equivalent to 1>/dev/null
stderr
$ mycommand 2>/dev/null
stdout

如果我只想捕获 stderr,我首先必须将 stderr 重定向到 stdout out 目前指向的位置,然后将 stdout 重定向到 /dev/null:

error="$(2>&1 1>/dev/null mycommand)"

现在error 只包含来自 stderr 的输出:

$ echo "$error"
stderr

行的位置并不重要,但重定向的顺序很重要,所以效果是一样的:

error="$(mycommand 2>&1 1>/dev/null)"

但这不是:

error="$(1>/dev/null 2>&1 mycommand)"

最后一个命令会将 stdout 和 stderr 都重定向到/dev/null,而error 将为空。

Bash Hackers Wiki 上有一个很好的重定向资源。


您尝试过的一些建议:

  • 赋值要求参数名中不能使用$,所以应该是PROG=/c/Program1而不是$PROG=/c/Program1
  • 不鼓励使用大写变量名,因为它们更有可能与环境变量发生冲突。
  • 在 99% 的情况下,有一个避免 eval 的解决方案,请参阅 BashFAQ/048 为什么这是一个好主意。

【讨论】:

  • 在某些情况下不起作用?喜欢进程替换diff -u <(2>&1 1>/dev/null echo Hello stderr) <(echo Hello stdout)
  • @Sandburg 2>&1 1>/dev/null echo Hello stderr 不打印任何内容,因为 echo 打印到标准输出,然后重定向到 /dev/null。所有示例都使用mycommand,这是一个将输出打印到 stdout 和 stderr 的命令。
猜你喜欢
  • 2013-05-11
  • 2012-11-28
  • 2018-11-25
  • 1970-01-01
  • 2017-07-21
  • 2018-08-10
  • 2011-04-17
  • 1970-01-01
相关资源
最近更新 更多