对话 UNIX: 更多 shell 脚本技术( 五 )


 fi
 _X=${_Y}
done
再次运行这个脚本:
# ./make_errors
X is less than 5!
X is less than 5!
X is less than 5!
X is less than 5!
Y is now equal to 6
恭喜!这个脚本现在正常工作了!
set -x 选项
有时候,对 shell 脚本执行基本的错误排除步骤并不像前一个示例那么容易 。如果所有努力都失败了,并且想不出脚本的错误之处在哪里,那么最后一招就是动用 “杀手锏!Ksh、Bash 和其他现代 shell 都支持在 set 命令中使用 -x 开关 。如果使用 set –x 选项,执行的每个命令都显示在 stdout 中 。为了突出显示执行的代码,set –x 把 PS4 变量的值加在显示的每行代码前面 。请记住,这种做法会产生大量文本,所以在查看输出时要有耐心 。
减小前一个示例中的循环计数值,在脚本的开头添加 set -x 和一个注释,见清单 12 。
清单 12. set -x 示例
#!/bin/bash
set -x
# loop through and display some test statements
_X=1
while [[ ${_X} -le 4 ]]
do
 [[ ${_X} -lt 2 ]] && echo "X is less than 2!
 _Y=`expr ${_X}1`
 if [[ ${_Y} -eq 3 ]]
 then
echo "Y is now equal to ${_Y}"
 fi
 _X=${_Y}
done
在执行这个脚本之前,把 PS4 变量改为某个看起来醒目的字符串:
# export PS4="DEBUG => "
接下来,执行这个脚本,就会看到可能非常有价值的信息,见清单 13 。
清单 13. set -x 的输出
# ./make_errors
DEBUG => _X=1
DEBUG => [[ 1 -le 4 ]]
DEBUG => [[ 1 -lt 2 ]]
DEBUG => echo 'X is less than 2!'
X is less than 2!
DDEBUG => expr 11
DEBUG => _Y=2
DEBUG => [[ 2 -eq 3 ]]
DEBUG => _X=2
DEBUG => [[ 2 -le 4 ]]
DEBUG => [[ 2 -lt 2 ]]
DDEBUG => expr 21
DEBUG => _Y=3
DEBUG => [[ 3 -eq 3 ]]
DEBUG => echo 'Y is now equal to 3'
Y is now equal to 3
DEBUG => _X=3
DEBUG => [[ 3 -le 4 ]]
DEBUG => [[ 3 -lt 2 ]]
DDEBUG => expr 31
DEBUG => _Y=4
DEBUG => [[ 4 -eq 3 ]]
DEBUG => _X=4
DEBUG => [[ 4 -le 4 ]]
DEBUG => [[ 4 -lt 2 ]]
DDEBUG => expr 41
DEBUG => _Y=5
DEBUG => [[ 5 -eq 3 ]]
DEBUG => _X=5
DEBUG => [[ 5 -le 4 ]]
可以看到这里有大量信息:处理并执行的每个命令都显示出来了 。还要注意,在调试信息中没有显示 shell 脚本中的注释 。这是因为 shell 在读取注释之后并不执行它 。还好,在完成前面的修改之后,这个脚本没有错误了!
在使用 set -x 时还要记住一点:如果脚本有内部函数,而且 set -x 放在代码的主体部分,那么它的输出会包含子函数的运算过程 。但是,如果 set -x 只放在内部函数中,那么 debug 选项的影响范围只包含这个内部函数中的代码和在其中调用的子函数;shell 脚本的主体并不包含在内,这是因为它不知道它的内部函数会调用这个例程 。
结束语
无论是使用 shell 脚本、C、Java? 语言或其他语言,我们都在不断地改进编程方法 。坚持简单化的基本规则,保持代码简洁灵活,给代码加上适当的注释,再借助调试工具的帮助,您很快就能编写出出色的 shell 脚本 。祝您好运!

推荐阅读