Chinaunix首页 | 论坛 | 博客
  • 博客访问: 389876
  • 博文数量: 40
  • 博客积分: 1004
  • 博客等级: 准尉
  • 技术积分: 469
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-01 17:02
文章分类

全部博文(40)

文章存档

2011年(40)

分类: Python/Ruby

2011-10-14 21:02:51

Shell调试技术总结

学习没种语言都会在编写程序中遇到错误,当然shell也不例外。Shell脚本的错误主要可分为两类:第一类是shell脚本中的语法错误,脚本无法执行到底,第二类是shell脚本能够执行完毕,但并不能按照我们预期的结果那样,也就是存在逻辑错误。

第一类错误主要包括漏掉关键字、漏掉引号、空格符该有而未有、变量大小写没去分等。这一类错误一般通过自己的仔细检查都能够检查出来,关键是第二种错误。

在逻辑错误中Shell有几种调试方法。常见的Shell调试方法有traptee、调试钩子和Shell选项。

(一)trapLinux的内建命令,不要用于捕捉信号,trap命令可以指定收集某种信号所执行的命令,基本形式为:

trap command sign1 sign2 、、、signN

对于上述命令的解释为当trap收到sign1 sign2 、、、signN 中的任意一个信号时就执行command命令,当command命令执行完后脚本继续收到信号进行操作,直到脚本执行结束。

Shell脚本在执行时,会产生三个“伪信号”(原因是这三个信号是有Shell产生的,而其他信号是由操作系统产生的),利用trap命令可以捕捉到这三个“伪信号”并输出相关信息是Shell调试的一种重要技巧。三种“伪信号”分别为EXITERRDEBUG

     Shell伪信号即产生的条件

信号名称

 产生条件

EXIT

从函数中推出,或从整个脚本中退出

ERR

当一条命令返回非零状态码,即命令执行不成功

DEBUG

脚本中的每条命令执行之前

举例:

  1. 1 #!/bin/sh
  2. 2 fun()
  3. 3 {
  4. 4 echo "This is an correct function"
  5. 5 var=2011
  6. 6 return 0
  7. 7 }
  8. 8 trap 'echo "Line is $LINENO ,var=$var "' EXIT
  9. 9 fun
  10. [root@localhost Shell]# sh trap1
  11. This is an correct function
  12. Line is 1 ,var=2011

这个脚本先执行fun函数然后trap捕捉到EXIT信号后的输出,而EXIT信号是在fun函数执行完毕才产生的。 

  1. 1 #!/bin/sh
  2.   2 fun()
  3.   3 {
  4.   4 echo "This is an error function"
  5.   5 var=2011
  6.   6 return 1
  7.   7 }
  8.   8 trap 'echo "Line is $LINENO ,var=$var "' ERR
  9.   9 fun
  10.  10 ipconfig
  11. [root@localhost shell]# sh trap2
  12. This is an error function
  13. Line is 6 ,var=2011
  14. trap2: line 10: ipconfig: command not found
  15. Line is 10 ,var=2011

执行该脚本后先执行函数fun,该函数返回1,非零返回值的函数被认为是异常信号,然后trap捕捉到ERR信号然后输出行号和var的值,然后执行ipconfigipconfig不存在返回1,因此产生ERR信号故输出如上结果。

  1. 1 #!/bin/sh
  2. 2
  3. 3 trap 'echo "before execute line: $LINENO a=$a,b=$b,c=$c" ' DEBUG
  4. 4 a=6
  5. 5 b=2
  6. 6 c=30
  7. 7 while :
  8. 8 do
  9. 9 if (( $a >= 10 ))
  10. 10   then break
  11. 11 fi
  12. 12   let "a=$a+2"
  13. 13   let "b=$b*2"
  14. 14     let "c=$c-10"
  15. 15 done
  16. [root@localhost shell]# sh trapdebug
  17. before execute line: 4 a=,b=,c=
  18. before execute line: 5 a=6,b=,c=
  19. before execute line: 6 a=6,b=2,c=
  20. before execute line: 7 a=6,b=2,c=30
  21. before execute line: 9 a=6,b=2,c=30
  22. before execute line: 12 a=6,b=2,c=30
  23. before execute line: 13 a=8,b=2,c=30
  24. before execute line: 14 a=8,b=4,c=30
  25. before execute line: 7 a=8,b=4,c=20
  26. before execute line: 9 a=8,b=4,c=20
  27. before execute line: 12 a=8,b=4,c=20
  28. before execute line: 13 a=10,b=4,c=20
  29. before execute line: 14 a=10,b=8,c=20
  30. before execute line: 7 a=10,b=8,c=10
  31. before execute line: 9 a=10,b=8,c=10
  32. before execute line: 10 a=10,b=8,c=10
  33. before execute line: 16 a=10,b=8,c=10

在此脚本中先执行trapDEBUG然后接着不断的进行跟踪,通过上面运算可以分析到整个脚本的执行踪迹,能够判断吃哪些条件执行了哪些条件没有执行。

 trap命令通过捕捉三个“伪信号”能够方便的跟踪异常函数和信号,尽管echo也能实现,但是用trap更加高效、简洁。

(二)用tee命令进行Shell调试。tee命令产生的数据流分为两个,其中将一个输出到标准输出,一个到输出文件。利用tee的这种特性就可以逐步检查各条命令的执行结果来定位错误。tee还有一个选项-a,表示将Shell命令的输出追加到某文件的末尾。

  1. [root@localhost shell]# who |tee output
  2. cherish tty1 Oct 14 11:06 (:0)
  3. cherish pts/0 Oct 14 11:07 (:0.0)
  4. [root@localhost shell]# cat output
  5. cherish tty1 Oct 14 11:06 (:0)
  6. cherish pts/0 Oct 14 11:07 (:0.0)

先将who执行的结果从管道传给teetee命令将标准输出复制到文件output。因此仍然输出who命令标准输出。

  1. [root@localhost shell]# ps | tee -a output
  2. PID TTY TIME CMD
  3. 6928 pts/0 00:00:00 su
  4. 6932 pts/0 00:00:01 bash
  5. 29242 pts/0 00:00:00 ps
  6. 29243 pts/0 00:00:00 tee
  7. [root@localhost shell]# cat output
  8. cherish tty1 Oct 14 11:06 (:0)
  9. cherish pts/0 Oct 14 11:07 (:0.0)
  10. PID TTY TIME CMD
  11. 6928 pts/0 00:00:00 su
  12. 6932 pts/0 00:00:01 bash
  13. 29242 pts/0 00:00:00 ps
  14. 29243 pts/0 00:00:00 tee

将执行结果追加到output文件后边。

  1. 1 #!/bin/sh
  2. 2 localIP=`cat /etc/sysconfig/network-scripts/ifcfg-eth0 | tee dubug.txt | grep 'IPADDR' | tee -a dubug.txt | cut -d= -f2 | tee -a dubug.txt`
  3. 3 echo "the local ip is :$localIP"
  4. [root@localhost shell]# sh tee1
  5. the local ip is :192.168.1.109
  6. [root@localhost shell]# cat dubug.txt
  7. DEVICE=eth0
  8. BOOTPROTO=none
  9. NM_CONTROLLED=yes
  10. ONBOOT=yes
  11. HWADDR=00:0c:29:57:0d:1f
  12. MTU=1500
  13. TYPE=Ethernet
  14. DEFROUTE=yes
  15. PEERROUTES=yes
  16. IPV4_FAILURE_FATAL=yes
  17. IPV6INIT=no
  18. NAME="System eth0"
  19. UUID=5fb06bd0-0bb0-7ffb-45f1-d6edd65f3e03
  20. IPADDR=192.168.1.109
  21. NETMASK=255.255.255.0
  22. GATEWAY=192.168.1.1
  23. DNS1=8.8.8.8
  24. USERCTL=no
  25. IPADDR=192.168.1.109
  26. 192.168.1.109

该脚本中先找出ifcfg-eth0文件内容,然后在dubug.txt后边追加IPADDR内容,最后追加ip地址,从debug.txt可以清晰看出数据的流向。便于发现脚本中存在的逻辑错误。

阅读(3072) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~