Shell脚本应用 - 条件测试操作
通过博文Shell脚本应用(一),可以在简单的Shell脚本程序中,各类语句将按先后顺序依次执行,从而实现批处理的自动化过程,然而,单一的顺序结构使得脚本国语机械化,不够“智能”,难以处理更加灵活的系统任务。
今天我们将认识并掌握如何进行条件测试操作,并通过正确使用if语句,使Shell脚本具有一定的“判断”能力,以根据不同的条件来完成不同的管理任务。
一、条件测试操作
要使Shell脚本具有一定的“智能”,面临的第一个问题就是如何区分不同的情况已确定执行何种操作。例如:当磁盘使用率达到某个点时,发出警告信息等操作。
Shell环境根据命令执行后的返回状态值($?)来判断是否执行成功,当返回值为0时,表示成功;当返回值为非0时,则表示失败。使用专门的测试工具——test命令,可以对特定条件进行测试。
使用test测试命令时,两种语法:
格式1:test 条件表达式
或者
格式2:[ 条件表达式 ]
这两种方式的作用完全相同,但通常第二种语法格式较为适用。
但是需要注意:第二种语法格式中括号“[ 条件表达式 ]”与条件表达式至少需要一个空格进行分隔!
根据需要测试的条件类型不同,条件表达式也不同,比较常用的条件操作包括:
1.文件测试
文件测试指的是根据特定的路径,判断对应的文件是目录还是文件,或者是否可读、可写、可执行等操作。常用的选项有:
-d:测试是否为目录(Directory) -e:测试目录或文件是否存在(Exist) -f:测试是否为文件(File) -r:测试当前用户是否有权限读取(Read) -w:测试当前用户是否有权限写入(Write) -x:测试当前用户是否有权限执行(eXcute)
执行条件测试操作以后,通过预定义变量$?来获得测试命令的返回值,从而判断该条件是否成立。比如:
[root@localhost ~]# [ -d /mnt ] //测试/mnt是不是一个目录 [root@localhost ~]# echo $? //查看前一条命令的返回值 0 //0表示条件成立,非0则表示条件不成立
为了更直观的查看测试效果,可以结合“&&”和“echo”命令一起使用。比如:
[root@localhost ~]# [ -d /etc ] && echo "yes" yes //输出“yes”表示条件成立,不输出“yes”则表示条件不成立
2.整数值比较
整数值比较指的是根据给定的两个整数值,判断第一个数与第二个数的关系,比如等于、大于、小于等。常用的选项有:
-eq:等于(Equal) -ne:不等于(Not Equal) -gt:大于(Greater Than) -lt:小于(Lesser Than) -le:小于或等于(Lesser or Equal) -ge:大于或等于(Greater or Equal)
整数值比较在Shell甲苯编写中的应用较多。例如,用来判断已登录用户数量、开启的进程数等。比如:
[root@localhost ~]# A=`who | wc -l` [root@localhost ~]# [ $A -eq 3 ] && echo "nice" nice //查看当前登录用户为3的话输出“nice”
3.字符串比较
字符串比较通常用力啊检查用户输入、系统环境等是否满足条件,在提供交互式操作的S我回来了脚本中,也可以用来判断用户输入的位置参数是否符合要求。常用的参数有:
=:字符串内容相同 !=:字符串内容不同,! 号表示相反的意思 -z:字符串内容为空
语法格式:
[ 字符串1 = 字符串2 ] [ 字符串1 != 字符串2 ] [ -z 字符串 ]
4.逻辑测试
逻辑测试指的是判断两个或多个条件之间的依懒关系。当系统任务取决于多个不同的条件时,根据这些条件是否同时成立或其中一个成立等情况,需要有一个测试过程,常用的参数有:
-a或&&:逻辑与,“而且”的意思 -o或||:逻辑或,“或者”的意思 !:逻辑否
语法格式:
格式1:[ 表达式1 ] 操作符 [ 表达式2 ] ... 格式2:命令1 操作符 命令2 ...
二、使用if语句结构
通过刚才的条件测试可以完成简单的判断并执行相应的曹组,但是当需要选择执行的命令语句较多时,这种方式会使代码显得复杂且不好理解。我们可以适当的使用if语句,来整理脚本结构,使得层次分明、清晰易懂。
1)if语句的结构
在Shell脚本应用中,if语句是最常用的一种流程控制方式,用力啊根据特定的条件测试结果,分别执行不同的操作(如果……那么……)。根据不同的复杂程度,if语句的选择结构可以分为三种基本类型,适用于不同的应用场合。
1.单分支if语句
if语句的:“分支”指的是不同测试结果所对应的执行语句(一条或多条)。对于if但分支的选择结构,只有在“条件成立”时才会执行相应的代码,否则不执行任何操作。
1)单分支if语句的语法结构:
if 条件测试操作 then 命令序列 fi
语句结构中,条件测试操作可以是“[ 条件表达式 ]”语句,也可以是其他可指定的命令语句,命令序列指的是一条或多条可执行的命令行,也包括嵌套使用的if语句或其他流程控制语句。
2)单分支if语句的流程图:
3)单分支if语句应用示例:
[root@localhost ~]# vim a.sh //随便定义脚本名称 #!/bin/bash //声明使用什么Shell A="/mnt/cdrom" //定义变量 if //关键字(如果) [ !-d $A ] //$A变量不是一个目录的话 then //关键字(那么) mkdir -p $A //创建这个变量所对应的目录 fi //关键字(结束) [root@localhost ~]# sh a.sh //执行脚本 [root@localhost ~]# ll /mnt 总用量 0 drwxr-xr-x. 2 root root 6 7月 30 12:19 cdrom //验证效果
2.多分支if语句
对于多分支的选择结构,要求针对“条件成立”、“条件不成立”两种情况分别执行不同的操作。
1)双分支if语句的语法结构:
if 条件测试操作 then 命令序列1 else 命令序列2 fi
2)双分支if语句流程图:
3)双分支if语句应用示例:
[root@localhost ~]# vim b.sh #!/bin/bash ping -c 3 -i 0.2 -W 3 $1 &>/dev/null //检查目标主机是否可以连通 if //关键字(如果) [ $? -eq 0 ] //测试上一条命令的返回结果 then //关键字(那么) echo "Host $1 is up" else //关键字(否则) echo "Host $1 is down" fi //关键字(结束) #(注释)代码中,为了提高ping命令的测试率,使用“-c”表示只发送三个测试包;“-i”表示间隔时间为0.2秒;“-W”表示超时时间3秒。另外使用 “ &> /dev/null”屏蔽ping命令执行过程的输出信息。 [root@localhost ~]# sh b.sh 192.168.1.1 Host 192.168.1.1 is down //执行脚本测试返回结果
3.多分支if语句
由于if语句可以根据测试结果的成立、不成立分别进行操作,所以能够嵌套使用,进行多次判断。
1)多分支if语句语法结构:
if 条件测试操作1 then 命令序列1 elif 条件测试操作2 then 命令序列2 else 命令序列3 fi
2)多分支if语句流程图:
3)多分支if语句应用示例:
(1) 应用示例(一)
[root@localhost ~]# vim c.sh #!/bin/bash read -p "请输入您的分数(0——100):" A if [ $A -ge 85 ] && [ $A -le 100 ] //85~100分,优秀 then echo "$A分,优秀!" elif [ $A -ge 70 ] && [ $A -le 84 ] //70~84分,及格 then echo "$A分,及格!" else echo "$A分,不及格!" //其他分数,不及格 fi [root@localhost ~]# sh c.sh 请输入您的分数(0——100):66 66分,不及格! [root@localhost ~]# sh c.sh 请输入您的分数(0——100):79 79分,及格! [root@localhost ~]# sh c.sh 请输入您的分数(0——100):99 99分,优秀! //验证执行脚本效果
(2)应用示例(二)
示例要求:
(1)使用df命令提取出根分区的磁盘占用率,赋值给变量DUG。
(2)使用mpstat命令提取CPU使用率(需安装sysstat软件包),赋值给变量CUG。
(3)使用free命令提取出内存使用率,赋值给变量MUG。
(4)判断上述监控项目是否超标,将需要告警的信息保存到/tmp/alert.txt文件。
(5)判断/tmp/alert.txt文件是否存在,若存在则作为告警邮件发送。
[root@localhost ~]# vim 1.sh #!/bin/bash # 提取性能监控指标(磁盘占用、CPU使用、内存使用) DUG=$(df -hT | grep "/$" | awk '{print $6}' | awk -F% '{print $1}') CUG=$(expr 100 - $(mpstat | tail -1 | awk '{print $12}' | awk -F. '{print $1}')) MUG=$(expr $(free | grep "Mem:" | awk '{print $3}') \* 100 / $(free | grep "Mem:" | awk '{print $2}')) # 设置告警日志文件、告警邮箱 ALOG="/tmp/alert.txt" AMAIL="root" # 判断是否记录告警 if [ $DUG -ge 0 ] then echo "磁盘占用率:$DUG %" >> $ALOG fi if [ $CUG -ge 0 ] then echo "CPU使用率:$CUG %" >> $ALOG fi if [ $MUG -ge 0 ] then echo "内存使用率:$MUG %" >> $ALOG fi # 判断是否发送告警邮件,最后删除告警日志文件 if [ -f $ALOG ] then cat $ALOG | mail -s "Host Alert" $AMAIL rm -rf $ALOG fi [root@localhost ~]# sh 1.sh [root@localhost ~]# mail //查看邮件 Heirloom Mail version 12.5 7/5/10. Type ? for help. "/var/spool/mail/root": 1 message 1 new N 1 root Tue Jul 30 13:01 20/662 "Host Alert" & …………………… //省略部分内容 磁盘占用率:26 % CPU使用率:1 % 内存使用率:18 % //验证结果 #(注释)实验环境,大于等于0就发送邮件,实际生产环境视情况而定!
也可以这样查看邮件:
[root@localhost ~]# cat /var/spool/mail/root …………… //省略部分内容 磁盘占用率:26 % CPU使用率:1 % 内存使用率:18 %
您在 /var/spool/mail/root 中有邮件