shell脚本的调试(trap、tee、shell选项)
2016-05-31 11:37
686 查看
shell脚本的调试,主要有4种:trap命令、tee命令、调试钩子和shell选项
trap command sig1 sig2....
功能描述:trap命令收到指定信号sign(EXIT,ERR,DEBUG)时,执行command
2.shell脚本的三种“伪信号”
“伪信号”是因为这三个信号是由Shell产生的,其他的信号都是由操作系统产生
EXIT :从函数中退出,或整个脚本执行完毕
ERR :当一条命令返回非零状态码,即命令执行不成功
DEBUG :脚本中的每一条命令执行之前
3.举例:
例1:利用trap命令捕捉DEBUG信号来跟踪变量的取值变化
运行部分结果:
解析:根据DEBUG产生的条件(脚本中的每一条命令执行之前产生DEBUG信号),因此,每当执行一个语句之前trap捕捉到DEBUG信号,进而打印a b c的值
例2:利用trap命令捕捉EXIT信号跟踪函数结束
[root@nn shell]# ./trapexit.sh
this is an correct function
Line:1,var=2010
例3:利用trap命令捕捉ERR信号
运行结果:
fun2函数返回值是1,非零返回值的函数都被认为是异常函数,因此在调用fun2函数时会产生ERR信号,输出
下面举个例子就可以看出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]#
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
运行结果:
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实际上就是将后面的字符串作为命令来执行,一个字符串可以包含多个命令,命令之间需要用分号隔开
一.使用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实际上就是将后面的字符串作为命令来执行,一个字符串可以包含多个命令,命令之间需要用分号隔开
相关文章推荐
- Tee(Linux命令)
- Linux命令之trap
- tee命令
- 移动电子商务:五个技术标准与Trustonic TEE解决方案
- Linux常用文本处理命令
- Linux 系统中的 SNMP Trap
- 什么是Trap消息?
- 用iptables做端口镜像(复制报文)
- Windows PowerShell 捕获错误
- 【Linux编程】零拷贝之splice( )函数和tee( )函数
- linux shell trap功能介绍
- tee命令用法小结
- shell编程——日志输出的同时显屏
- linux命令之tee
- 利用sshpass解决ssh与scp交互密码验证,tee -a 写日志与终端
- Linux - 命令行 管道(Pipelines) 详解
- Linux的tee命令
- Trap in Unix
- 我使用过的Linux命令之trap - 在脚本中处理信号
- 浅谈 Linux 系统中的 SNMP Trap