Linux Shell脚本调试的四种办法
Linux脚本调试前言bash自身特性-v-n-x-x的增强$LINENO$FUNCNAME$[PS4](https://blog.51cto.com/kusorz/1968827)功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是
Linux脚本调试
前言
Linux的shell脚本上手简单但是调试起来就颇为麻烦,二者间的抉择就像编辑器上轻量级与功能丰富的不可兼得一般。在这里提出一些Linux上脚本调试的小技巧,希望有所帮助。
bash自身特性
众所周知,bash相对于dash而言是更重量级的存在,其中一部分便是这种调试辅助信息。以下的特性都是在bash上验证的,dash下无说明便是没有测试过。
了解一个命令的最好办法自然是man手册:
手册本身命令很多,这次只介绍几个我常用的参数:
-v
一边执行脚本,一边将执行过的脚本命令打印。
注意: 脚本命令本身是被定义到标准错误输出打印,而真实结果是在标准输出打印。
-n
读一遍脚本中的命令但不执行,用于检查脚本中的语法错误。
注意:这里的检查主要是针对语法格式缺少(例如,if语句少了then),但是还有很多是没有检查的(比如,if语句没加空格、函数未定义)。
-x
提供跟踪执行信息,将执行的每一条命令和结果依次打印出来。这个的功能超级强大,将会重点介绍。
-
如果有多个脚本嵌套关系,可以进入次级脚本检查(比如a.sh调用b.sh,b.sh调用c.sh,只会显示a.sh和b.sh的内容)
所以最好是哪个脚本想追踪就在哪个脚本里加上set -x。
-
行首显示+,+后面显示经过替换之后的命令行内容,有助于分析实际执行的是什么命令。++代表函数或脚本进一步的调用。
示例:
root@hik-PC:/tmp# cat test.sh
#!/bin/bash
echo 111
SER="/usr/lib/dconf/dconf-service"
fun(){
pp=`ps -ef | grep $SER`
}
fun
bash a.sh
root@hik-PC:/tmp# cat a.sh
#!/bin/bash
echo aaa
dd=`ps -ef |grep a.sh`
root@hik-PC:/tmp# bash -x test.sh
+ echo 111
111
+ SER=/usr/lib/dconf/dconf-service
+ fun
++ ps -ef
++ grep /usr/lib/dconf/dconf-service
+ pp='hikvisi+ 3348 3016 0 5月13 ? 00:00:00 /usr/lib/dconf/dconf-service
root 32422 32420 0 11:22 pts/1 00:00:00 grep /usr/lib/dconf/dconf-service'
+ bash a.sh
aaa
-x的增强
$LINENO
代表shell脚本的当前行号
$FUNCNAME
函数的名字,它是一个数组变量,其中包含了整个调用链上所有的函数的名字,所以变量${FUNCNAME[0]}
代表shell脚本当前正在执行的函数的名字,而变量${FUNCNAME[1]}
则代表调用函数${FUNCNAME[0]}
的函数的名字,余者可以依此类推。
$PS4
$PS4
的值将被显示在“-x”选项输出的每一条命令的前面,在Bash Shell中,缺省的$PS4
的值是"+"号。所以默认执行bash -x时前面有“+”号。进一步介绍,可以参照上面我的参考文献。
示例:
root@hik-PC:/tmp# cat -n test.sh
1 #!/bin/sh
2 export PS4='+$LINENO: {${FUNCNAME[0]}}'
3 echo 111
4 SER="/usr/lib/dconf/dconf-service"
5 fun(){
6 pp=`ps -ef | grep $SER`
7 }
8 funn(){
9 fun
10 }
11 funn
12 bash a.sh
root@hik-PC:/tmp# bash -x test.sh
+ export 'PS4=+$LINENO: {${FUNCNAME[0]}}'
+ PS4='+$LINENO: {${FUNCNAME[0]}}'
+3: {}echo 111
111
+4: {}SER=/usr/lib/dconf/dconf-service
+11: {}funn
+9: {funn}fun
++6: {fun}ps -ef
++6: {fun}grep /usr/lib/dconf/dconf-service
+6: {fun}pp='hikvisi+ 3348 3016 0 5月13 ? 00:00:00 /usr/lib/dconf/dconf-service
root 5476 5474 0 13:55 pts/1 00:00:00 grep /usr/lib/dconf/dconf-service'
+12: {}bash a.sh
aaa
最后,这些命令有多种实现方式:
- 命令行:bash -x xx.sh
- 在脚本开头提供参数#!/bin/bash -x
- 脚本中,set -x (启用) / set +x (禁用)
trap
定义:用于捕获指定的信号并执行预定义的命令。
语法:trap ‘command’ signal
注意:
- signal主要使用shell内部的伪信号(exit,err,debug
debug是脚本中每一条命令执行之前),很多资料也写可以捕获系统信号,但没有测试过。 - dash没有这种伪信号,所以必须用bash。
示例:
root@hik-PC:/tmp# cat -n trap.sh
1 #!/bin/bash
2 trap 'echo “before execute line:$LINENO, a=$a,b=$b,c=$c”' DEBUG
3 a=1
4 if [ "$a" -eq 1 ]
5 then
6 b=2
7 else
8 b=1
9 fi
10 c=3
11 echo "end"
root@hik-PC:/tmp# bash trap.sh
“before execute line:3, a=,b=,c=”
“before execute line:4, a=1,b=,c=”
“before execute line:6, a=1,b=,c=”
“before execute line:10, a=1,b=2,c=”
“before execute line:11, a=1,b=2,c=3”
end
调试钩子
用途:当测试环境和部署环境不同时,不同的要求和判定能把人折磨疯,利用export DEBUG=true既可以执行判断语句内内容,不用一条条删语句了。
示例:
if [ “$DEBUG” = “true” ]; then
echo “debugging” #此处可以输出调试信息
fi
bashdb
bashdb是一个类GDB的调试工具,可以完成对shell脚本的断点设置,单步执行,变量观察等许多功能。
使用bashdb进行debug的常用命令:
1. 列出代码和查询代码类:
l 列出当前行以下的10行
\- 列出正在执行的代码行的前面10行
. 回到正在执行的代码行
w 列出正在执行的代码行前后的代码
/pat/ 向后搜索pat
?pat?向前搜索pat
2. Debug控制类:
h 帮助
help 命令 得到命令的具体信息
q 退出bashdb
x 算数表达式 计算算数表达式的值,并显示出来
!!空格Shell命令 参数 执行shell命令
使用bashdb进行debug的常用命令(cont.)
控制脚本执行类:
n 执行下一条语句,遇到函数,不进入函数里面执行,将函数当作黑盒
s n 单步执行n次,遇到函数进入函数里面
b 行号n 在行号n处设置断点
(经验证,bashdb的break设置断点命令必须s、s、c然后到这个断点以后,还得重新设置下一个断点,否则不生效,===>即再次s、s、c才行)
del 行号n 撤销行号n处的断点
c 行号n 一直执行到行号n处
R 重新启动
Finish 执行到程序最后
cond n expr 条件断点
更多推荐
所有评论(0)