【发布时间】:2017-07-04 05:39:42
【问题描述】:
我有一个 shell 脚本,我想将其 stdout 和 stderr 写入日志文件。我知道这可以通过
sh script.sh >> both.log 2>&1
但是,我还想同时将标准错误写入一个单独的文件“error.log”。这可以实现吗?
【问题讨论】:
我有一个 shell 脚本,我想将其 stdout 和 stderr 写入日志文件。我知道这可以通过
sh script.sh >> both.log 2>&1
但是,我还想同时将标准错误写入一个单独的文件“error.log”。这可以实现吗?
【问题讨论】:
您可以使用tee 将输出复制到两个位置。结合一些棘手的重定向,然后......
script.sh 2>&1 >> both.log | tee -a both.log >> error.log
这会将 stderr 重定向到 stdout,然后将 stdout 重定向到 both.log。 stderr 仍然存在,并通过管道传送到 tee,后者将其复制到两个日志文件中。
【讨论】:
error.log 文件中只保留std-err msgs。然后不与` 2>&1` 混合在一起(并且无法区分)。 ?
>> both.log 2>&1,那么它们将混合在一起。重定向是违反直觉的。 2>&1 并不意味着“stderr 进入标准输出”。它的意思是“stderr 去任何 stdout 去的地方”。把它想象成变量赋值。 x = 5; y = x; x = 7; -- y 的值为 5,而不是 7。
2>&1的位置与标准做法交换。多么棒的把戏! Tnx 回复。
为此需要先切换stdout和stderr,这需要额外的文件描述符:
sh script.sh 3>&2 2>&1 1>&3 3>&-
最后一个操作符关闭辅助文件描述符。
之后,您可以使用tee 复制错误流(现在在标准输入上)并将其附加到您的错误日志中:
sh script.sh 3>&2 2>&1 1>&3 3>&- | tee -a error.log
然后您可以将 stdin 和 stderr 都指向您的组合日志:
(sh script.sh 3>&2 2>&1 1>&3 3>&- | tee -a error.log) >> both.log 2>&1
命令周围的括号对于捕获整个命令的错误流很重要。如果没有它们,则只会捕获 tee 命令的(空)错误流,其余的仍将转到终端。
注意:这不会检查文件描述符 3 之前是否正在使用(打开)。在 bash 中,您可以使用它来选择以前未使用的文件描述符并在最后一次重定向时将其关闭:
sh script.sh {tmpfd}>&2 2>&1 1>&${tmpfd}-
【讨论】: