【问题标题】:Redirecting stderr to stdout as well as to stderr将 stderr 重定向到 stdout 以及 stderr
【发布时间】:2022-01-18 19:10:07
【问题描述】:

我通常有以下几点: ./myscript > myfile.log 2>&1

我希望将 stderr 和 stdout 写入 myfile.log 并让 stderr 进入“stderr”(终端)。

我在看 tee,但 tee 仅用于标准输出。

【问题讨论】:

  • tee 适用于您可以写入其标准输入的任何内容。棘手的是,大多数 shell 不提供将一个进程的标准错误连接到另一个进程的标准输入的运算符,类似于 |(将一个进程的标准输出连接到另一个进程的标准输入)。

标签: bash logging error-handling


【解决方案1】:

你可以使用tee:

{ ./myscript 2>&1 >&3 | tee /dev/stderr >&3; } 3> myfile.out

{ ./myscript 2>&1 >&3 | tee /dev/fd/2 >&3; } 3> myfile.out

你也可以试试:

rm myfile.out; { ./myscript 2>&1 >&3 | tee -a myfile.out >&2; } 3>> myfile.out

但这感觉有点笨拙。我相信这也应该有效:

{ ./myscript 2>&1 >&3 | tee -a myfile.out >&2; } 3> myfile.out

感觉不像是一个杂物。

【讨论】:

  • 可以确认第一个版本有效。我可以看到 FD "3" 正在保存 stdout 和 stderr 并且有些东西正在通过管道传送到 tee,但任何解释都将不胜感激。
  • 在第一个命令中,您将 fd 3 重定向到输出文件。然后你重定向myscript的fd 2进入到tee的管道,但你不希望它与fd 1混合,所以你将fd 1重定向到3。这样teemyscript得到stderr,将其写入 stderr 和 fd 3,将其与之前重定向到 myfile.out 的 myscript 的 stdout 混合。
【解决方案2】:

试试这个方法:

$: ./myscript 2> >( tee myfile.log >&2 ) 1>&2

注意2>>( 之间需要空格以保持语法明确。

要证明它按预期工作,请使用grep 进行过滤。
(我使用ls 作为在两个流上获取输出的简单方法。)

$: ls -ld . bogus 2> >( tee err.log >&2 ) 1>&2 | grep foo >stdout.log
ls: cannot access 'bogus': No such file or directory
drwxr-xr-x 1 P2759474 1049089 0 Dec 15 11:19 .

来自tee 的输出发送到err.log 和控制台流2,或stderr。流 1 (stdout) 发送到流 2 所到之处,同样发送到 tee,它将所有它的输出发送到它自己的流 2,即控制台的 stderr

grep 也看不到,因为流 1 上没有任何内容通过,因此它无法过滤不匹配的行。

$: ls -l err.log stdout.log
-rw-r--r-- 1 P2759474 1049089 113 Dec 15 11:19 err.log
-rw-r--r-- 1 P2759474 1049089   0 Dec 15 11:19 stdout.log

一切都进入tee的日志,没有任何东西进入grep的日志。

$: cat err.log
ls: cannot access 'bogus': No such file or directory
drwxr-xr-x 1 P2759474 1049089 0 Dec 15 11:19 .

【讨论】:

    猜你喜欢
    • 2014-07-22
    • 1970-01-01
    • 2012-08-07
    • 2011-07-22
    • 2012-07-14
    • 2016-04-21
    • 1970-01-01
    • 2011-12-28
    • 1970-01-01
    相关资源
    最近更新 更多