将 stdout 和 stderr 复制到日志文件并将它们留在脚本本身的控制台上

将 stdout 和 stderr 复制到日志文件并将它们留在脚本本身的控制台上

使用 bash,如何将 stderr 和 stdout 复制到日志文件并将它们显示在控制台上?

我想使用 exec 在脚本本身中执行此操作。

我尝试过

exec &>> log.out

echo "This is stdout"
echo "This is stderr" >&2

但上面的内容在控制台上没有打印任何内容。我怎样才能在 bash 中实现这一目标?

答案1

您正在寻找tee.

man tee详情请参阅。

要将其与 结合起来exec,您必须使用流程替代。 (man bash详情请参阅。)

exec &> >(tee  log.out)
echo "This is stdout"
echo "This is stderr" >&2

答案2

我知道这是一篇旧文章,但为什么不这样做呢?

echo "hi" >> log.txt #stdout -> log
echo "hi" | tee -a log.txt #stdout -> log & stdout
echo "hi" &>> log.txt #stdout & stderr -> log
echo "hi" |& tee -a log.txt #stdout & stderr -> log & stdout

当然,如果你想要标准输出,你可以定期打印。

您可以使用您希望的任意流组合来执行此操作,只需使用这两个基本命令即可。

我知道我来到这里并没有得到一个易于理解/实施的答案,希望这对其他人有帮助。

顺便说一句,对于像我以前那样的菜鸟来说,所有命令tee所做的就是将 stdin 输入输出到 stdout 和指定为后续参数的文件。-a代表追加,因此每次使用该命令时都不会覆盖该文件。如果您还有其他问题,我发现成为快速学习 bash 非常有用的资源。

答案3

你可以做:

: > log # empty log file if necessary
{ { {

  ...the script

} 3>&- | tee -a log >&3 3>&-
exit "${PIPESTATUS[0]}"
} 2>&1 | tee -a log >&2 3>&-
} 3>&1
exit "${PIPESTATUS[0]}"

您也可以将其写为:

: > log # empty log file if necessary
exec 2> >(tee -a log >&2) > >(tee -a log)

...the script

但是因为 bash 不等待那些以>(...) 开头的进程,所以有时会在命令返回后向终端输出一些东西,这会产生令人讨厌的效果,如果终端“tostop”属性,这可能会产生更糟糕的效果(例如默默地丢弃该输出)已开启。

无论如何,通过stdout在两个解决方案中创建管道,并且由于两个命令独立输出输出和错误消息,这将影响输出缓冲以及输出和错误消息的显示顺序。

答案4

另一种方法是在函数内使用重定向。

#!/bin/bash

function1 () {
    echo 'STDOUT from function 1'
    echo 'STDERR from function 1' >&2
}

function2 () {
    echo 'STDOUT from function 2'
    echo 'STDERR from function 2' >&2
}


function3 () {
    echo 'STDOUT from function 3'
    echo 'STDERR from function 3' >&2
}

main() {
    function1
    function2
    function3
}

main 2>&1 |tee log.txt

这里我们有一个main调用所有其他函数的函数。现在将STDOUTand函数STDERR重定向maintee.

相关内容