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


12

有没有一种方法可以通过运行带有-x选项的bash脚本将显示的信息发送到文件,而不会更改运行该脚本的用户看到的标准输出?

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

非常感激。

Answers:


21

-x的输出转到stderr,而不是stdout。但这甚至可能是一个问题-许多脚本将对stderr的内容具有功能依赖性,并且在某些情况下将调试流和stderr流混合在一起也很麻烦。

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

# 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”,然后将它们与debug输出交错,这样您的日志就更完整了。有关更多信息,请参见/programming/3173131/redirect-copy-of-stdout-to-log-file-from-within-bash-script-itself

与其他方法相比,这种方法的最大优点是,您无需冒着通过将调试输出注入到stdout或stderr中而改变脚本行为的风险。


另请参阅此处有关如何查找文件的未使用文件描述符的信息。
jarno

是否有必要关闭文件描述符(即第行exec 19>&-)?以我的经验,脚本完成后会自动关闭。
jarno

1
上面显示的代码未假设您正在运行脚本,或者脚本可能运行了多长时间等等。确实,如果您只执行此代码段的工作并将其放在脚本中,则文件句柄将仅因为整个外壳在脚本末尾消失而被关闭。因此,在该用例中,您不必严格关闭手柄。但是总的来说,当针对资源进行编码时,最好关闭已打开的内容,因为这样您的代码可以在较大的情况下使用,在这种情况下,看家更可能重要。
马able

为什么要导出BASH_XTRACEFD?为什么不只是为其设置值?
jarno

无论如何,关闭文件描述符的另一种方法是为BASH_XTRACEFD设置新值(例如null)或取消设置它。
jarno

4

set -x不会将任何内容发送到标准输出,因此那里没有问题。它所确实做的是写标准错误,它默认到控制台。

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

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

1

请参阅man tee

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.