1.11.1 实战演练

我们可以利用Bash内建的调试工具或者按照易于调试的方式编写脚本,方法如下所示。

跟踪调试

使用选项-x,启用shell脚本的跟踪调试功能

  1. bash -x script.sh

运行带有-x选项的脚本可以打印出所执行的每一行命令以及当前状态。

你也可以使用sh -x script

部分调试

使用set -xset +x对脚本进行部分调试。例如:

  1. #!/bin/bash
  2. #文件名: debug.sh
  3. for i in {1..6};
  4. do
  5. set -x
  6. echo $i
  7. set +x
  8. done
  9. echo "Script executed"
  1. [root@dev workspace]# vi debug.sh
  2. [root@dev workspace]# chmod +x debug.sh
  3. [root@dev workspace]# ./debug.sh
  4. + echo 1
  5. 1
  6. + set +x
  7. + echo 2
  8. 2
  9. + set +x
  10. + echo 3
  11. 3
  12. + set +x
  13. + echo 4
  14. 4
  15. + set +x
  16. + echo 5
  17. 5
  18. + set +x
  19. + echo 6
  20. 6
  21. + set +x
  22. Script executed
  23. [root@dev workspace]#

在上面的脚本中,只会打印出echo $i的调试信息,因为使用-x+x对调试区域进行了限制。

该脚本并没有使用上例中的seq命令,而是用{start..end}来迭代从startend之间的值。这个语言构件(construct)在执行速度上要比seq命令略快。

自定义的调试信息

前面介绍的调试方法是Bash内建的。它们以固定的格式生成调试信息。但是在很多情况下,我们需要使用自定义的调试信息。可以通过定义_DEBUG环境变量来启用或禁止调试及生成特定形式的信息。请看下面的代码:

  1. #!/bin/bash
  2. function DEBUG()
  3. {
  4. [ "$_DEBUG" == "on" ] && $@ || :
  5. }
  6. for i in {1..10}
  7. do
  8. DEBUG echo "I is $i"
  9. done

可以将调试功能设置为on来运行上面的脚本:

  1. $ _DEBUG=on ./script.sh
  1. [root@dev workspace]# vi script.sh
  2. [root@dev workspace]# chmod +x script.sh
  3. [root@dev workspace]# _DEBUG=on ./script.sh
  4. I is 1
  5. I is 2
  6. I is 3
  7. I is 4
  8. I is 5
  9. I is 6
  10. I is 7
  11. I is 8
  12. I is 9
  13. I is 10
  14. [root@dev workspace]#

我们在每一条需要打印调试信息的语句前加上DEBUG。如果没有把_DEBUG=on传递给脚本,那么调试信息就不会打印出来。在Bash中,命令:告诉shell不要进行任何操作。

1.11.2 工作原理

-x选项会输出脚本中执行过的每一行。不过,我们可能只关注其中某一部分代码。针对这种情况,可以在脚本中使用set builtin来启用或禁止调试打印。

  • set -x:在执行时显示参数和命令。
  • set +x:禁止调试。
  • set -v:当命令进行读取时显示输入。
  • set +v:禁止打印输入。

1.11.3 补充内容

还有其他脚本调试的便捷方法,我们甚至可以巧妙地利用shebang来进行调试。

shebang的妙用

shebang#!/bin/bash改成#!/bin/bash -xv,这样一来,不用任何其他选项就可以启用调试功能了。

如果每一行前面都加上+,那么就很难在默认输出中跟踪执行流程了。可以将环境变量PS4设置为’$LINENO:‘,显示出每行的行号:

  1. PS4='$LINENO: '

调试的输出信息可能会很长。如果使用了-xset -x,调试输出会被发送到stderr。可以使用下面的命令将其重定向到文件中:

  1. sh -x testScript.sh 2> debugout.txt

Bash 4.0以及后续版本支持对调试输出使用自定义文件描述符:

  1. exec 6> /tmp/debugout.txt
  2. BASH_XTRACEFD=6