条件测试和捕获信号
一、退出状态
在Linux系统中,无论是命令、脚本还是程序,执行完成退出后都存在退出状态,退出状态通常保存在预定义变量$?中。大多数情况下,预定义变量只会使用两个数字表示命令、脚本和程序的退出状态。
数字0表示命令、脚本或程序成功执行,没有发生错误。
数字1表示在执行过程中发生了某些错误,没有成功执行。
由于退出状态由程序编写者定义,因此退出状态也可能不是0或1,遇到这种情况时,可能需要查阅其说明文件了解具体含义。
说明:虽然退出状态的值可能会有许多,但只要退出状态不是数字0,就可以认为程序、命令发生了错误。
【设置退出状态命令】
在编写较为复杂的脚本时,应该考虑错误捕捉机制,即当脚本中的语句执行出现错误时,脚本能够处理错误。一个简单的例子:如果用户使用脚本没有给出必要的参数,脚本应该能够检查到这个错误,并提示用户。
在脚本中设置退出状态需要使用exit命令,其常见的使用形式及对应的含义如下:
exit 0:表示返回脚本执行成功,无错误返回。这种情况有时也称为返回为真(true)。
exit 1:表示执行失败,有错误返回。这种情况有时也称为返回为假(false)。
除了以上的0和1之外,还可以使用其他一些数字,但只要返回的状态非0,系统就认为脚本执行失败。
使用exit命令设置退出状态时需要注意,无论脚本执行到何处,只要遇到exit命令,脚本会立即设置退出状态并退出脚本。
注意:函数返回状态命令return与退出状态命令exit的区别:exit直接退出程序,后面不再执行;return只是所在函数返回,后面会继续执行。
二、文件测试
对文件的测试包括两个方面:(1)文件基本测试,包括文件、目录是否存在、文件类型、文件长度等;(2)文件权限测试,包括文件是否可读、可写、可执行等。
1、文件基本测试
文件基本测试大多用在创建文件、目录之前,这样做的目的是让脚本拥有更好的容错性。
【文件测试命令】
文件基本测试常用的命令及其含义如下:
d:测试目标是否存在,并且是一个目录。
f:测试目标文件是否存在,并且是一个普通文件。
L:测试目标文件是否存在,并且是一个链接文件。
b:测试目标文件是否存在,并且是一个块设备文件。
c:测试目标文件是否存在,并且是一个字符设备文件。
e:测试指定文件或目录是否存在。
S:测试目标文件是否存在,并且是一个Socket文件。
p:测试目标文件是否存在,并且是一个FIFO(pipe)文件。
【文件测试命令的格式】
[ -command parameter ]
上面的基本格式中,command为测试命令,parameter是需要测试的目标文件或目录。需要注意的是,文件测试的命令、参数都要放在中括号内。
注:条件测试命令允许在命令提示符下使用。
注意:与C语言类似,在shell脚本中也使用数字0表示真,非0数字表示假。
2、文件权限测试
【文件权限测试命令】
常用的文件权限测试命令及其含义如下:
w:判断指定的文件是否存在,并且拥有可写入权限。
r:判断指定的文件是否存在,并且具有可读取权限。
x:判断目标文件是否存在,并且具有可执行权限。
u:判断目标文件是否存在,并且具有SUID属性。
g:判断目标文件是否存在,并且具有SGID属性。
k:判断目标文件是否存在,并且具有Sticky bit属性。
s:判断目标文件是否存在,并且是非空白文件。
三、字符串和数值测试
1、字符串测试
【字符串测试的操作符和命令】
字符串测试的操作符及其含义如下:
=:判断两个字符串是否相等,如果相等,则返回真(0).
!=:判断两个字符串是否不相等,如果不相等,则返回真。
z:测试字符串是否为空null(长度为0),为空则返回真。
n:测试字符串是否为非空,非空则返回真。
2、数值测试
【数值测试操作符】
eq:如果两个数相等,则返回真。
ne:如果两个数不相等,则返回真。
lt:如果第1个数小于第2个数,则返回真。
le:如果第1个数小于等于第2个数,则返回真。
gt:如果第1个数大于第2个数,则返回真。
ge:如果第1个数大于等于第2个数,则返回真。
使用上面的命令进行数值测试时,如果要判断两个数是否相等,也可以使用字符串测试中的“=”和“!=”进行测试。
四、逻辑操作符
【常用的逻辑操作符】
a:逻辑与,操作符两边都为真,结果为真,否则为假。
o:逻辑或,操作符两边至少有一个为真,结果为真,否则为假。
!:逻辑非。
五、捕获系统信号
在编写脚本时,可能会担心由于脚本的使用者发出来一个终止脚本运行的信号,Shell脚本就会终止运行,从而无法完成正在处理的工作。如果脚本正在处理一些无关紧要的工作,脚本终止可能不会有任何损失。但如果正在执行一项非常重要的工作,脚本终止就可能会带来损失。因此在重要的脚本中,应该捕获系统发出的终止信号并作出相应的动作,以免脚本终止带来不必要的损失。
【可以捕获的信号】
通常情况下,可以捕获的信号编号、名称及其含义如下:
1(SIGHUP):来自控制终端的挂起或来自控制进程的死亡信号。
2(SIGINT):来自键盘的中断信号。
3(SIGQUIT):来自键盘的退出信号。
15(SIGTERM):终止信号。
如果不确定脚本会捕获到那种信号,建议在重要的脚本中,捕获所有可以捕获的信号,以免带来不必要的损失。
【捕获信号后的措施】
在捕获到系统信号之后,脚本应该立即采取措施。通常可以采取以下3种措施:
不捕获信号,由系统处理这些信号。这会导致脚本结束执行、暂停等后果,这个办法通常用于不重要的脚本中。
捕获但忽略信号,即捕获到信号后部采取任何措施。
捕获信号并采取措施,这通常用于比较重要的脚本中。通常操作是提示用户是否需要中断脚本的执行,也可以向用户发出脚本正在执行不能退出的消息等。
【捕获信号的格式】
捕获系统信号使用命令trap,其基本格式如下:
trap “command” signals
在上面的格式中,command表示捕获到信号之后需要执行的命令或函数,如果为空(使用“”表示)则表示忽略信号,否则表示采取相应措施处理信号。signals表示要捕获的信号列表,可以使用数字表示,也可以使用信号名称表示。多个信号,空格分隔。
【用法示例】
在下面这个示例脚本中,将要捕获的是用户从键盘上发送的结束信号(案件为Ctrl+C,对应的信号为2),捕获到信号后脚本将调用函数trap,输出提示信息并退出:
[root@localhost shell]# cat ex_trap.sh #!/bin/bash #This is a exmaple script. #2013-12-19 trap "trap" 2 function trap() { echo "You press the Ctrl+C." echo "Exiting,please wait 3 seconds..." sleep 1 echo -n "->" sleep 1 echo -n "->" sleep 1 echo "->" exit 1 } sleep 60
运行结果:
[root@localhost shell]# ./ex_trap.sh You press the Ctrl+C. Exiting,please wait 3 seconds... ->->-> [root@localhost shell]#
按下快捷键Ctrl+C时,可以看到脚本捕获了用户从键盘发出的中断信号,并调用trap函数,显示提示信息并等待3秒后退出。