Bash中的set -x命令可以将echo重定向以及其他命令一起输出。

13
我正在编写一个 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

如何使命令显示的方式与它们书写时完全一致,而不是被脚本重新排序?

3个回答

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

这对我来说完美地运作,并且似乎是这个问题的最佳答案。感谢您。 - Nickolai
请注意,这对于更复杂的带有函数的Bash脚本不起作用,因为在这些情况下,输入只会被读取一次。 - Edward Z. Yang

6

无论何时使用某些结构,set -x 和 DEBUG trap 都无法提供完整的信息。

例如:

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 ]

4

set -x 无法实现此功能。您唯一的选择是通过 DEBUG 陷阱查看当前命令。

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

这不像使用set -x那样显示精确参数,但将它们组合在一起应该能够给你完整的图片,虽然会有很多调试输出。


但是FreeBSD系统怎么办呢?由于缺少DEBUG信号,我无法在那里执行这样的技巧。有什么建议吗? - vwvolodya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接