我有一些带有 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)
在哪里:
>> log.txt
将 STDOUT 附加到log.txt
。2> >
将 STDERR 发送到 进行处理(tee -a log.txt >&2)
。tee -a log.txt
log.txt
以 append ( ) 模式将其拆分为文件-a
并拆分为>&2
。- 由于 STDERR 被临时发送到 STDOUT,因此
>&2
将其放回 STDERR。
注意事项
由于附加,如果您运行两次,文件中就会有两次输出 - 鉴于它是一个日志文件,我认为这就是目标。如果您希望日志文件中只有最新的运行,您必须先清空它,例如,
> log.txt && ./script.sh >> log.txt 2> >(tee -a log.txt >&2)
这些行不会按时间顺序出现,因为后者>>
的工作速度要快一些tee -a
。因为后者必须派生另一个进程,所以 STDERR 的输出会延迟到达文件。如果正确的顺序至关重要,则不能使用此解决方案。