12

我正在编写一个 Bash 脚本,我希望所有命令在它们发生时都被回显。我知道我需要分别使用set -xset +x切换此行为(此处为 SOF 帖子)。但是,它并没有回显所有内容,即 I/O 重定向。

例如,假设我有这个非常简单的 Bash 脚本:

set -x
./command1 > output1
./command2 arg1 arg2 > output2

这将是输出

+ ./command1
+ ./command2 arg1 arg2

Bash 没有将我的 stdout 重定向回显到output1output2。为什么是这样?我怎样才能实现这种行为?也许shopt我必须在脚本中设置一个选项?

注意:我还注意到管道不会按预期打印。例如,如果我要使用这个命令:

set -x
./command3 | tee output3

我会得到这个输出:

+ tee output3
+ ./command3

如何使命令完全按照它们的编写方式回显,而不是让脚本重新排序管道?

4

3 回答 3

6

当使用某些构造时,调试陷阱和调试陷阱都set -x不会提供完整的信息。

例子是:

ex1.sh

for i in a b c
do
  echo $i # Where does the output go?
done > outfile # Here!

ex2.sh

c="this"
case "$c" in
  this) echo sure ;; # Where does the output go?
  that) echo okay ;;
esac > choice # Here!

ex3.sh

what="up"
while [ "$what" = "up" ]
do
    echo "Going down!" # Where does the output go?
    what="down"
    echo "Newton rulezzz!" > thelaw
done > trying # Here!

还有更多类似的,更不用说各种嵌套的变体了。我不知道有什么简单的方法来处理这些,除了进入完整的 Bash 脚本解析领域,这是一个雷区......

编辑:如果不需要特定于 Bash 的功能,并且可以与 Bourne shell 向后兼容,则 Korn shell(ksh,使用版本 93u+ 2012-08-01 测试)在显示重定向信息方面做得更好:

$ ksh -x ex1.sh 
+ 1> outfile
+ echo a
+ echo b
+ echo c

$ ksh -x ex2.sh 
+ c=this
+ 1> choice
+ echo sure

$ ksh -x ex3.sh 
+ what=up
+ 1> trying
+ [ up '=' up ]
+ echo 'Going down!'
+ what=down
+ echo 'Newton rulezzz!'
+ 1> thelaw
+ [ down '=' up ]
于 2013-07-04T22:56:53.127 回答
6

你应该使用set -v.

-v 在读取 shell 输入行时打印它们。

输出似乎符合您的期望。

$ set -v
$ ./command1 > output1
./command1 > output1
sh: ./command1: No such file or directory
$ ./command2 arg1 arg2 > output2
./command2 arg1 arg2 > output2
sh: ./command2: No such file or directory
$ ./command3 | tee output3
./command3 | tee output3
sh: ./command3: No such file or directory
于 2015-10-13T08:59:49.577 回答
4

这是不可能的set -x。您唯一的选择是通过DEBUG陷阱查看当前命令。

trap 'printf %s\\n "$BASH_COMMAND" >&2' DEBUG

这不会显示精确的论点set -x。将它们结合起来应该会给你一个完整的画面,尽管它有很多调试输出。

于 2013-03-12T16:30:10.660 回答