关于管道:Bash set -x echo重定向以及命令

Bash set -x echo redirects as well as commands

我正在编写一个bash脚本,我希望所有命令在发生时都得到响应。我知道我需要使用set -xset +x分别关闭和打开这个行为(这里是sof post)。但是,它并没有响应所有的内容,即I/O重定向。

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

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

这将是输出

1
2
+ ./command1
+ ./command2 arg1 arg2

bash没有响应我的stdout重定向到output1和output2。为什么会这样?我如何才能实现这种行为?也许在脚本中需要设置一个shopt选项?

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

1
2
set -x
./command3 | tee output3

我将得到这个输出:

1
2
+ tee output3
+ ./command3

如何使这些命令以编写它们的方式得到准确的响应,而不是让脚本对管道进行重新排序?


你最好使用set -v

-v Print shell input lines as they are read.

产出似乎符合你的预期。

1
2
3
4
5
6
7
8
9
10
$ 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


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

例子有:

EX1.SH

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

EX2.SH

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

EX3.SH

1
2
3
4
5
6
7
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版本中测试)在显示重定向信息方面做得更好:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ 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 ]


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

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

这不会像set -x会那样显示出精确的参数。组合它们应该能让您了解完整的情况,尽管它有很多调试输出。