捕获 stderr,但不捕获 stdout

Jar*_*ein 2 bash shell

在我的 bash 脚本中,我读入了一组如下所示的行

arg $PROG arg arg
Run Code Online (Sandbox Code Playgroud)

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

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

请详细说明解决方法。我是 bash shell 脚本的新手并正在尝试学习。

Ben*_* W. 5

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

mycommand () { echo "stdout"; echo "stderr" >&2; }
Run Code Online (Sandbox Code Playgroud)

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

$ mycommand
stdout
stderr
Run Code Online (Sandbox Code Playgroud)

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

$ mycommand >/dev/null    # Equivalent to 1>/dev/null
stderr
$ mycommand 2>/dev/null
stdout
Run Code Online (Sandbox Code Playgroud)

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

error="$(2>&1 1>/dev/null mycommand)"
Run Code Online (Sandbox Code Playgroud)

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

$ echo "$error"
stderr
Run Code Online (Sandbox Code Playgroud)

行上的位置并不重要,但重定向的顺序很重要,所以这具有相同的效果:

error="$(mycommand 2>&1 1>/dev/null)"
Run Code Online (Sandbox Code Playgroud)

但这不是:

error="$(1>/dev/null 2>&1 mycommand)"
Run Code Online (Sandbox Code Playgroud)

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

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


您尝试过的一些提示:

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