bash:将 -x 日志设置到文件

bash:将 -x 日志设置到文件

set -x我有一个用于显示详细/调试输出的shell 脚本:

#!/bin/bash

set -x
command1
command2
...

输出如下所示:

+ command1
whatever output from command1
+ command2
whatever output from command2

我的问题是,shell 输出(由 引起set -x)进入 stderr,与命令的输出(command1command2、...)混合在一起。我很乐意在屏幕上显示“正常”输出(就像脚本在没有 的情况下运行一样set -x),并在文件中单独显示 bash 的“额外”输出。

所以我想在屏幕上显示这个:

whatever output from command1
whatever output from command2

日志文件中如下内容:

+ command1
+ command2

(如果日志文件包含所有内容也很好)

set -x 2> file显然不会产生正确的效果,因为它不是 set 命令的输出,但它改变了 bash 的行为。

对整个脚本使用bash 2> file也做不到正确,因为它会重定向在此 shell 中运行的每个命令的 stderr,所以我看不到命令​​的错误消息。

答案1

基于此 ServerFault 答案将 bash -x 输出发送到日志文件而不中断标准输出,现代版本的 bash 包含一个BASH_XTRACEFD专门用于指定输出的备用文件描述符set -x

例如你可以这样做

#!/bin/bash

exec 19>logfile
BASH_XTRACEFD=19

set -x
command1
command2
...

将输出发送set -x到文件,logfile同时为以下命令保留常规标准输出和标准错误流。

请注意,fd 19 的使用是任意的 - 它只需要是一个可用的描述符(即不是 0、1、2 或您已经分配的其他数字)。

答案2

经过一年多的时间,我找到了正确的解决方案,将“正常”输出(stdout + stderr - bash trace)同时显示在屏幕上,并将所有内容(stdout + stderr + bash trace)一起显示在文件(bash.log)中:

exec   > >(tee -ia bash.log)
exec  2> >(tee -ia bash.log >& 2)
exec 19> bash.log

export BASH_XTRACEFD="19"
set -x

command1
command2

答案3

钢铁司机给你一种方法。或者,您可以简单地将 STDERR 重定向到文件:

script.sh 2> logfile

但是,这意味着选项产生的输出set -x和产生的任何其他错误消息都将进入文件。Steeldriver 的解决方案只会重定向输出,set -x这可能正是您想要的。

答案4

自动文件描述符

只是为了稍微改进一下所接受的答案,并且我会保持它的完整性,在这里您可以使用 Bash 4.1+ 自动文件描述符分配{any_var}来使用最低可用的文件描述符 - 无需对其进行硬编码。

exec  1> >(tee -ia bash.log)
exec  2> >(tee -ia bash.log >& 2)

# Notice no leading $
exec {FD}> bash.log

# If you want to append instead of wiping previous logs
exec {FD}>> bash.log

export BASH_XTRACEFD="$FD"
set -x

# Just for fun, add this to show the file descriptors in this context
# and see the FD to your bash.log file
filan -s

command1
command2

相关内容