将 STDERR 发送到控制台和文件,将 STDOUT 仅发送到文件

将 STDERR 发送到控制台和文件,将 STDOUT 仅发送到文件

我有一些带有 STDOUT 和 STDERR 输出的脚本。默认情况下,STDOUT 和 STDERR 都转到控制台:

./script.sh

我可以将 STDOUT 重定向到文件,将 STDERR 输出留在控制台中:

./script.sh > log.txt

我可以将 STDOUT + STDERR 重定向到同一个文件,而控制台中没有输出:

./script.sh > log.txt 2>&1

我可以在控制台和日志文件中同时拥有 STDOUT 和 STDERR:

./script.sh 2>&1 | tee -a log.txt

我不想看到 STDOUT,但我想看到 STDERR,而且我必须将所有内容保存在日志文件中。我怎么能把 STDERR 放在控制台和日志文件中,而把 STDOUT 只放在日志文件中呢?比如(伪代码,无效)

./script.sh > log.txt 2 > /dev/tty | tee -a log.txt

答案1

你必须附加将 STDERR 和 STDOUT 都写入文件。否则,另一个流会覆盖另一个流。

./script.sh >> log.txt 2> >(tee -a log.txt >&2)

在哪里:

  1. >> log.txt将 STDOUT 附加到log.txt
  2. 2> >将 STDERR 发送到 进行处理(tee -a log.txt >&2)
  3. tee -a log.txtlog.txt以 append ( ) 模式将其拆分为文件-a并拆分为>&2
  4. 由于 STDERR 被临时发送到 STDOUT,因此>&2将其放回 STDERR。

注意事项

由于附加,如果您运行两次,文件中就会有两次输出 - 鉴于它是一个日志文件,我认为这就是目标。如果您希望日志文件中只有最新的运行,您必须先清空它,例如,

> log.txt && ./script.sh >> log.txt 2> >(tee -a log.txt >&2)

这些行不会按时间顺序出现,因为后者>>的工作速度要快一些tee -a。因为后者必须派生另一个进程,所以 STDERR 的输出会延迟到达文件。如果正确的顺序至关重要,则不能使用此解决方案。

相关内容