在使用gcc编译keepalived源码的时候,需要运行configure生成Makefile,然后用make命令编译。但是在这个过程中,configure文件却一直无法扫描到一个已经安装的三方库。无奈,只能查看configure源码。configure其实就是一个shell脚本,为了帮助理解脚本,使用了一些调试技术。在此做个介绍。
以下内容绝大部分参考:
Shell脚本调试技术
测试脚本test.sh
copbint@debian2:~$ cat test.sh
a=1
if [ "$a" -eq 1 ]
then
b=2
else
b=1
fi
c=3
echo "end"
使用sh -x test.sh运行脚本。
默认会直接输出到屏幕,使用以下命令重定向到文件。
sh -x test.sh &> log.txt
输出如下:
copbint@debian2:~$ sh -x test.sh
+ a=1
+ [ 1 -eq 1 ]
+ b=2
+ c=3
+ echo end
end
在上面的结果中,前面有“+”号的行是shell脚本实际执行的命令,前面有“++”号的行是执行trap机制中指定的命令(如果脚本不使用trap语句就不会打印++吗?输出不是由PS4变量决定的吗?不太懂),其它不带+的行则是输出信息。
-x 增强
“-x”执行选项是目前最常用的跟踪和调试shell脚本的手段,但其输出的调试信息仅限于进行变量替换之后的每一条实际执行的命令以及行首的一个”+”号提示符,居然连行号这样的重要信息都没有,对于复杂的shell脚本的调试来说,还是非常的不方便。幸运的是,我们可以巧妙地利用shell内置的一些环境变量来增强”-x”选项的输出信息,下面先介绍几个shell内置的环境变量:
$LINENO
代表shell脚本的当前行号,类似于C语言中的内置宏LINE
$FUNCNAME
函数的名字,类似于C语言中的内置宏func,但宏func只能代表当前所在的函数名,而
FUNCNAME的功能更强大,它是一个数组变量,其中包含了整个调用链上所有的函数的名字,故变量
F
U
N
C
N
A
M
E
的
功
能
更
强
大
,
它
是
一
个
数
组
变
量
,
其
中
包
含
了
整
个
调
用
链
上
所
有
的
函
数
的
名
字
,
故
变
量
{FUNCNAME[0]}代表shell脚本当前正在执行的函数的名字,而变量
FUNCNAME[1]则代表调用函数
F
U
N
C
N
A
M
E
[
1
]
则
代
表
调
用
函
数
{FUNCNAME[0]}的函数的名字,余者可以依此类推。
PS4主提示符变量 P S 4 主 提 示 符 变 量 PS1和第二级提示符变量 PS2比较常见,但很少有人注意到第四级提示符变量 P S 2 比 较 常 见 , 但 很 少 有 人 注 意 到 第 四 级 提 示 符 变 量 PS4的作用。我们知道使用“-x”执行选项将会显示shell脚本中每一条实际执行过的命令,而 PS4的值将被显示在“−x”选项输出的每一条命令的前面。在BashShell中,缺省的 P S 4 的 值 将 被 显 示 在 “ − x ” 选 项 输 出 的 每 一 条 命 令 的 前 面 。 在 B a s h S h e l l 中 , 缺 省 的 PS4的值是”+”号。(现在知道为什么使用”-x”选项时,输出的命令前面有一个”+”号了吧?)。
利用 PS4这一特性,通过使用一些内置变量来重定义 P S 4 这 一 特 性 , 通 过 使 用 一 些 内 置 变 量 来 重 定 义 PS4的值,我们就可以增强”-x”选项的输出信息。例如先执行export PS4=’+{ LINENO: L I N E N O : {FUNCNAME[0]}} ‘, 然后再使用“-x”选项来执行脚本,就能在每一条实际执行的命令前面显示其行号以及所属的函数名。
在设置了这个PS4这个变量之后,再执行sh -x test.sh,一直报错:
Bad substitution
执行bash -x test.sh即OK,输出了行号加函数。没有深入去了解其中原因以及sh与bash具体的不同。
copbint@debian2:~$ bash -x test.sh
+{2:main} a=1
+{3:main} '[' 1 -eq 1 ']'
+{5:main} b=2
+{9:main} c=3
+{10:main} echo end
end
有了这个利器,还有啥问题搞不定,太赞了。果然是工欲善其事,必先利其器。
其他调试技术
虽然觉得-x 就可以搞定一切了。但是还是记一些其他的调试技术,以防将来用到。
-n 不真正执行脚本,只检查语法。
trap 满足某些条件时,打印日志
使用调试钩子 即定义DEBUG变量,通过这个变量的值来决定是否打印日志。
具体都请参考原文:
Shell脚本调试技术