将 bash -x 输出发送到日志文件而不中断标准输出

将 bash -x 输出发送到日志文件而不中断标准输出

有没有办法将使用 -x 选项运行 bash 脚本所显示的信息发送到文件,同时不改变运行该脚本的用户看到的标准输出?

这是我想在我们使用的经常更改的 bash 脚本中实现的调试功能。

答案1

-x 的输出将发送到 stderr,而不是 stdout。但即便如此,这也可能会成为一个问题 —— 很多脚本将对 stderr 的内容具有功能依赖性,在某些情况下,将调试和 stderr 流混合在一起会有点混乱。

Bash 4.1 以上版本确实提供了不同的解决方案:BASH_XTRACEFD 环境变量允许您指定将用于发送调试流的文件描述符。这可以是文件或管道或您喜欢的任何其他 unix-y 优点。

    # Use FD 19 to capture the debug stream caused by "set -x":
    exec 19>/tmp/my-script.log
    # Tell bash about it  (there's nothing special about 19, its arbitrary)
    export BASH_XTRACEFD=19

    # turn on the debug stream:
    set -x

    # run some commands:
    cd /etc
    find 
    echo "Well, that was fun."

    # Close the output:
    set +x
    exec 19>&-

    # See what we got:
    cat /tmp/my-script.log

再多花点功夫,你就可以做其他事情——比如在 stdout 和/或 stdin 流上执行“tee”,并将它们与调试输出交错,这样你的日志就会更完整。有关这方面的更多详细信息,请参阅https://stackoverflow.com/questions/3173131/redirect-copy-of-stdout-to-log-file-from-within-bash-script-itself

与其他方法相比,这种方法的最大优势在于,您不会冒险通过将调试输出注入 stdout 或 stderr 来改变脚本的行为。

答案2

set -x不会向标准输出发送任何内容,因此不存在任何问题。执行的操作是写入标准错误,默认情况下写入控制台。

您要做的是将 stdout 重定向到另一个文件,如下所示:

/bin/sh -x /my/script/file 2>/my/log/file

答案3

man tee

您像这样运行它tee commandname filename,它将显示命令输出stdout并将其写入filename

答案4

tee命令已经提到过了,但我使用另一种方法来合并跟踪日志中的所有输出。在我看来,这简化了调试。

技巧是使用/dev/tty命令tee,因为您无法再重用 stdout/stderr 文件句柄,因为它们已被重定向到您的跟踪日志。

尝试这个:

exec 3>trace.log 2> >(tee -ia /dev/tty >&3) 1> >(tee -ia /dev/tty >&3)
BASH_XTRACEFD=3
set -x

tail -f trace.log注意:你可以与另一个学期同步阅读。

(GNU bash,版本 5.1.16(1)-release(x86_64-pc-linux-gnu))

相关内容