关闭

shell脚本的调试(trap、tee、shell选项)

标签: shell脚本的调试teetrapshell选项
136人阅读 评论(0) 收藏 举报
分类:

shell脚本的调试,主要有4种:trap命令、tee命令、调试钩子和shell选项

一.使用trap命令

1.基本格式

trap command sig1 sig2....

功能描述:trap命令收到指定信号sign(EXIT,ERR,DEBUG)时,执行command

2.shell脚本的三种“伪信号”

“伪信号”是因为这三个信号是由Shell产生的,其他的信号都是由操作系统产生

EXIT          :从函数中退出,或整个脚本执行完毕

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

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

3.举例:

例1:利用trap命令捕捉DEBUG信号来跟踪变量的取值变化

#!/bin/bash 

trap 'echo "before execute line:$LINENO,a=$a,b=$b,c=$c"' DEBUG

a=0
b=2
c=100
while :
do
        if ((a >= 10))
        then
                break
        fi
        let "a=a+2"
        let "b=b*2"
        let "c=c-10"


done

运行部分结果:

[root@nn shell]# ./trapdebug.sh 
before execute line:5,a=,b=,c=
before execute line:6,a=0,b=,c=
before execute line:7,a=0,b=2,c=
before execute line:8,a=0,b=2,c=100
before execute line:10,a=0,b=2,c=100
before execute line:14,a=0,b=2,c=100
before execute line:15,a=2,b=2,c=100
before execute line:16,a=2,b=4,c=100
before execute line:8,a=2,b=4,c=90
before execute line:10,a=2,b=4,c=90
before execute line:14,a=2,b=4,c=90
before execute line:15,a=4,b=4,c=90
before execute line:16,a=4,b=8,c=90
before execute line:8,a=4,b=8,c=80
before execute line:10,a=4,b=8,c=80
before execut

解析:根据DEBUG产生的条件(脚本中的每一条命令执行之前产生DEBUG信号),因此,每当执行一个语句之前trap捕捉到DEBUG信号,进而打印a b c的值


例2:利用trap命令捕捉EXIT信号跟踪函数结束

#!/bin/bash 


fun1()
{
        echo "this is an correct function"
        var=2010
        return 0

}

trap 'echo "Line:$LINENO,var=$var"' EXIT
fun1
运行结果:

[root@nn shell]# ./trapexit.sh
this is an correct function
Line:1,var=2010

例3:利用trap命令捕捉ERR信号

#!/bin/bash 


trap 'echo "Line:$LINENO,var=$var"' ERR
fun2()
{
        echo "this is an err function"
        var=2010
        return 1

}

fun2
ipll

运行结果:

[root@nn shell]# ./traperr.sh 
this is an err function
Line:9,var=2010
./traperr.sh: line 14: ipll: command not found
Line:14,var=2010
代码解析:

fun2函数返回值是1,非零返回值的函数都被认为是异常函数,因此在调用fun2函数时会产生ERR信号,输出

Line:9,var=2010
下面执行ipll,但是这个是错误语句,因此也会产生ERR信号

二、使用tee命令

使用tee命令可以将管道的东西写进文件

下面举个例子就可以看出tee的作用了:

tee -a file    将标准输出追加到文件末尾,而不会覆盖file

[root@nn shell]# cat /etc/sysconfig/network-scripts/ifcfg-br0 |grep IPADDR | cut -d= -f2
192.168.40.223
[root@nn shell]# cat /etc/sysconfig/network-scripts/ifcfg-br0 |tee /home/a.txt|grep IPADDR |tee -a /home/a.txt | cut -d= -f2
192.168.40.223
[root@nn shell]# cat /home/a.txt 
DEVICE=br0
NM_CONTROLLED=no
TYPE=Bridge
ONBOOT=yes
BOOTPROTO=none
IPADDR=192.168.40.223
GATEWAY=192.168.40.1
NETMASK=255.255.255.0
DNS1=192.168.10.11
DEFROUTE=yes
IPV4_FAILURE_FATAL=yes
IPV6INIT=no
NAME="br0"
IPADDR=192.168.40.223
[root@nn shell]# 

三、使用调试钩子

其实与一相似,不再多写

四、使用shell选项

前面三种方法都是通过修改shell脚本源代码,来定位错误,使用shell选项是一种不修改源代码也能定位错误信息

1.set   -n      :只进行语法检测,并不会真正执行代码

#!/bin/bash 

set  -n    #set -o noexec 与set -n等价

echo "starting...."

var=0;
while :
        if [ $var -gt 3 ]
        then
                break

        fi
let "var=var+1"
done
运行结果:

[root@nn shell]# chmod +x misskey.sh 
[root@nn shell]# ./misskey.sh 
./misskey.sh: line 15: syntax error near unexpected token `done'
./misskey.sh: line 15: `done'

当然你也可以利用sh 命令直接对脚本进行语法检测     语法:  sh -n 脚本文件

#!/bin/bash 


echo "starting...."

var=0;
while :
        if [ $var -gt 3 ]
        then
                break

        fi
let "var=var+1"
done
运行结果:

[root@nn shell]# sh -n ./misskey.sh    
./misskey.sh: line 14: syntax error near unexpected token `done'
./misskey.sh: line 14: `done'

2. -x

在执行每个命令之前,将每个命令打印到标准输出

#!/bin/bash 


echo "starting...."

var=0;
while :
do
        if [ $var -gt 3 ]
        then
                break

        fi
let "var=var+1"
echo var=$var
done

运行结果:
[root@nn shell]# sh -x ./misskey.sh 
+ echo starting....
starting....
+ var=0
+ :
+ '[' 0 -gt 3 ']'
+ let var=var+1
+ echo var=1
var=1
+ :
+ '[' 1 -gt 3 ']'
+ let var=var+1
+ echo var=2
var=2
+ :
+ '[' 2 -gt 3 ']'
+ let var=var+1
+ echo var=3
var=3
+ :
+ '[' 3 -gt 3 ']'
+ let var=var+1
+ echo var=4
var=4
+ :
+ '[' 4 -gt 3 ']'
+ break

3.shell用于调试的内部变量

LINENO     :表示shell脚本的行号

FUNCNAME     :数组变量,表示整个调用链上所有的函数名   #FUNCNAME[0]:表示当前正在运行的函数,FUNCNAME[1]:表示调用函数$FUNCNAME[0]的函数名字

PS4      :设置-x选项的提示符。默认值是“+”号       ;#export PS4=   

4.-c 

[root@nn shell]# a=10;b=20;c=$a*$b;echo $c
10*20
[root@nn shell]# a=10;b=20;let c=$a*$b;echo $c
200
[root@nn shell]# sh -c 'a=10;b=20;let c=$a*$b;echo $c'
200
sh -c实际上就是将后面的字符串作为命令来执行,一个字符串可以包含多个命令,命令之间需要用分号隔开










0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:47655次
    • 积分:1233
    • 等级:
    • 排名:千里之外
    • 原创:60篇
    • 转载:67篇
    • 译文:0篇
    • 评论:3条
    最新评论