1.1 条件表达式

1.1.0 条件表达式语法

[ 测试表达式 ]

好习惯:先敲一对[ ],然后退格输入2个空格[ ],最后再退回一个空格开始输入[ -f file ]

1.1.1 文件判断

常用文件测试操作符

常用文件测试操作符

说明

-d文件,d的全拼为directory

文件存在且为目录则为真,即测试表达式成立

-f文件,f的全拼为file

文件存在且为普通文件则为真,即测试表达式成立

-e文件,e的全拼为exist

文件存在则为真,即测试表达式成立。注意区别于“-f”,-e不辨别是目录还是文件

-r文件,r的全拼为read

文件存在且可读则为真,即测试表达式成立(针对当前用户这个文件的权限判断)

-s文件,s的全拼为size

文件存在且文件大小不为0则为真,即测试表达式成立

-w文件,w的全拼为write

文件存在且可写则为真,即测试表达式成立(针对当前用户这个文件的权限判断)

-x文件,x的全拼为executable   

文件存在且可执行则为真,即测试表达式成立

-L文件,L的全拼为link

文件存在且为链接文件则为真,即测试表达式成立

fl -nt f2nt 的全拼为 newer than

文件fl比文件f2新则为真,即测试表达式成立。根据文件的修改时间来计算

fl -ot f2ot 的全拼为 older than

文件fl比文件f2旧则为真,即测试表达式成立。根据文件的修改时间来计算

判断文件是否存在

[root@kai scripts]# [ -f /etc/hosts ]

[root@kai scripts]# echo $?0

[root@kai scripts]# [ -f /etc/hosts1 ]

[root@kai scripts]# echo $?

1

判断文件是否存在,返回方式

[root@kai scripts]# [ -f /etc/hosts ] && echo "文件存在" || echo "文件不存在" 文件存在

[root@kai scripts]# [ -f /etc/hosts1 ] && echo "文件存在" || echo "文件不存在"

文件不存在

判断目录是否存在

[root@kai scripts]# [ -d /tmp ] && echo "目录存在" || echo "目录不存在" 目录存在

[root@kai scripts]# [ -d /tmp1 ] && echo "目录存在" || echo "目录不存在"

目录不存在

使用变量的方法进行判断

dir=/etc1/;[ -d $dir ] && tar zcf etc.tar.gz $dir || echo "$dir目录不存在"

1.1.2 字符串判断

字符串测试操作符 

常用字符串测试操作符

说明

-n "字符串"

若字符串的长度不为0,则为真,即测试表达式成立,n可以理解为no zero

-Z "字符串"

若字符串的长度为0,则为真,即测试表达式成立,z可以理解为zero的缩写

" 1"== " 2"

若字符串1等于字符串2,则为真,即测试表达式成立,可使用"=="代替"="

" 1" = "2"        

若字符串1不等于字符串2,则为真,即测试表达式成立,但不能用"!=="代替"!="

1.对于字符串的测试,一定要将字符串加双引号之后再进行比较。

2.空格非空,也是一个字符

-z 判断字符串长度(一般用来判断变量内容的长度)

[root@kai scripts]# x= ; [ -z "$x" ] && echo "输入为空" || echo '输入有内容'输入为空

[root@kai scripts]# x=12 ; [ -z "$x" ] && echo "输入为空" || echo '输入有内容'

输入有内容

-n 判断字符串长度

[root@kai scripts]# x=12 ; [ -n "$x" ] && echo "输入有内容" || echo '输入为空'输入有内容

[root@kai scripts]# x= ; [ -n "$x" ] && echo "输入有内容" || echo '输入为空'

输入为空

"串 1" == " 串 2 "       使用定义变量的方式进行判断

cmd=$1

[ "$cmd" == "start" ] && echo start

# 测试

[root@kai scripts]# cmd=start;[ "$cmd" == "start" ] && echo start

start

1.1.3 整数判断

整数二元比较操作符参考

[]以及test

使用的比较符号

(())[[]]

使用的比较符号

说明

-eq

===

相等,全拼为equal

-ne

=

不相等,全拼为not equal

-gt

大于,全拼为greater than

-ge

>=

大于等于,全拼为greater equal

-lt

小于,全拼为丨ess than

-le

<=

小于等于,全拼为less equal

判断两数是否相等

[root@kai scripts]# [ 1 -eq 1 ]

[root@kai scripts]# echo $?0

[root@kai scripts]# [ 1 -eq 2 ]

[root@kai scripts]# echo $?

1

大于等于

[root@kai ~]# [ 11 -ge 1 ] && echo "成立" || echo "不成立"

成立

小于

[root@kai ~]# [ 11 -lt 1 ] && echo "成立" || echo "不成立"

不成立

大于

[root@kai ~]# [ 11 -gt 1 ] && echo "成立" || echo "不成立"

成立

不等于

[root@kai ~]# [ 11 -ne 1 ] && echo "成立" || echo "不成立"

成立

1.1.4 逻辑符号

常用逻辑操作符 

[]test中使用的操作符

说明

[[]]和中使用的操作符

说明

-a

[ 条件A -a  条件B ]

AB都要成立,整个表达式才成立

&&

and,与,两端都为真,则结果为真

-o

[ 条件A -o  条件B]

AB都不成立,整个表达式才不成立

||

or,或,两端有一个为真,则结果为真

 把整个表达式结果取反

!

not,非,两端相反,则结果为真

逻辑操作符与整数判断配合

[root@kai ~]# [ 11 -ne 1 ] && echo "成立" || echo "不成立"

成立

 取反

[root@kai ~]# [ ! 11 -ne 1 ] && echo "成立" || echo "不成立"

不成立

两边都为真

[root@kai ~]# [ 11 -ne 1 -a 1 -eq 1 ] && echo "成立" || echo "不成立"

成立

至少有一边为真

[root@kai ~]# [ 11 -ne 1 -o 1 -eq 1 ] && echo "成立" || echo "不成立"

成立

感叹号的特殊用法

         使用历史命令,感叹号加上history中的序号,即可执行

[root@kai ~]# !516 ls

anaconda-ks.cfg bootime.avg setup.sh vim

1.1.5 【练习题】开发3个shell脚本比较2个整数大小

要求:

1. 分别以定义变量,脚本传参以及read读入的方式写3个脚本。

2. 用条件表达式(禁止if语句)进行判断。

3. 2个整数的比较结果输出到屏幕,出错需要提示。

使用定义变量方法

[root@kai panduan1]# cat panduan1.sh

#!/bin/bash

NUM1=6

NUM2=2

expr 1 + $NUM1 &>/dev/null

[ $? -eq 2 ] && echo "$NUM1 不是整数 " && exit 2

expr 1 + $NUM2 &>/dev/null

[ $? -eq 2 ] && echo "$NUM2 不是整数 " && exit 2

[ "$NUM1" -eq "$NUM2" ] && echo $NUM1 = $NUM2 && exit

[ "$NUM1" -gt "$NUM2" ] && echo $NUM1 \> $NUM2 && exit

[ "$NUM1" -lt "$NUM2" ] && echo $NUM1 \< $NUM2

使用传参方法

[root@kai panduan1]# cat panduan_chuanchan.sh

#!/bin/bash

[ $# -ne 2 ] && echo "UASGE $0 num1 num2 " && exit

NUM1=$1

NUM2=$2

expr 1 + $NUM1 &>/dev/null

[ $? -eq 2 ] && echo "$NUM1 不是整数 " && exit 2

expr 1 + $NUM2 &>/dev/null

[ $? -eq 2 ] && echo "$NUM2 不是整数 " && exit 2

[ "$NUM1" -eq "$NUM2" ] && echo $NUM1 = $NUM2 && exit

[ "$NUM1" -gt "$NUM2" ] && echo $NUM1 \> $NUM2 && exit

[ "$NUM1" -lt "$NUM2" ] && echo $NUM1 \< $NUM2

使用read读入

[root@kai panduan1]# cat panduan_read.sh

#!/bin/bash

read -p "please input integer NO.1:" num1

expr $num1 + 1 &>/dev/null

[ $? -eq 2 ] && echo -e "\033[41;33m $num1不是整数 \033[0m" && exit 2

[ -z $num1 ] && echo "不能为空" && exit 2

read -p "please input integer NO.2:" num2

expr $num1 + 1 &>/dev/null

[ $? -eq 2 ] && echo -e "\033[41;33m $num2不是整数 \033[0m" && exit 2

[ -z $num2 ] && echo "不能为空" && exit 2

[ $num1 -eq $num2 ] && echo -e "\033[34m $num1 = $num2 \033[0m" && exit 0

[ $num1 -gt $num2 ] && echo -e "\033[35m $num1 > $num2 \033[0m" && exit 0

[ $num1 -lt $num2 ] && echo -e "\033[36m $num1 < $num2 \033[0m"

1.2 if 条件语句

  # 条件表达式和if语句可以互相转换

1.2.1 三种语法

单分支语句

if [ -f /etc/hosts ]

then

echo '文件存在'

fi

双分支语句

if [ -f /etc/hosts ]

then

echo "文件存在"

else

echo "文件不存在"

echo "..." >>/tmp/test.log

fi

多分支语句

if [ -f /etc/hosts ]

then

echo " hosts文件存在"

elif [ -f /etc/host ]

then

echo " host文件存在"

fi

1.2.2 if条件语句小结

  单分支:一个条件一个结果

  双分支:一个条件两个结果

  多分支:多个条件多个结果

1.2.3 【练习题1】输入2个数字,比较大小(使用if语句结合条件表达式实现) 

说明:

3个脚本:使用直接赋值,传参,read任一种方法写3种脚本(单分支,双分支,多分支)

示例脚本一:

[root@kai panduan1]# cat if_panduan_1.sh 

#!/bin/bash 

read -p "请输入第一个整数:" NUM1

 expr 1 + $NUM1 &>/dev/null

if [ $? -eq 2 ]

then

echo "$NUM1 不是整数 "17 exit 2

fi

read -p "请输入第二个整数:" NUM2

expr 1 + $NUM2 &>/dev/null

if [ $? -eq 2 ]

then

echo "$NUM2 不是整数 "

exit 2

 fi

# 判断输入数值大小

if [ $NUM1 -eq $NUM2 ]

then

echo "$NUM1 = $NUM2"

 exit

fi

if [ $NUM1 -gt $NUM2 ]

 then

 echo "$NUM1 > $NUM2"

exit

 fi

if [ $NUM1 -lt $NUM2 ]

then

echo "$NUM1 < $NUM2"44 fi

示例脚本二:

[root@kai panduan1]# cat if_panduan_2.sh

#!/bin/bash

12 read -p "请输入第一个整数:" NUM1

13 expr 1 + $NUM1 &>/dev/null

14 if [ $? -eq 2 ]

15 then

16 echo "$NUM1 不是整数 "17 exit 2

18 fi

19

20 read -p "请输入第二个整数:" NUM2

21 expr 1 + $NUM2 &>/dev/null

22 if [ $? -eq 2 ]

23 then

24 echo "$NUM2 不是整数 "

25 exit 2

26 fi

27

28 # 判断输入数值大小

29 if [ $NUM1 -eq $NUM2 ]

30 then

31 echo "$NUM1 = $NUM2"

32 exit

33 else

34 if [ $NUM1 -gt $NUM2 ]

35 then

36 echo "$NUM1 > $NUM2"

37 exit

38 else

39 if [ $NUM1 -lt $NUM2 ]

40 then

41 echo "$NUM1 < $NUM2"42 fi

43 fi

44 fi

示例脚本三:

[root@kai panduan1]# cat if_panduan_3.sh 2 

#!/bin/bash

read -p "please input integer NO.1:" num1

expr $num1 + 1 &>/dev/null

if [ $? -eq 2 ]

  then

    echo -e "\033[41;33m $num1不是整数 \033[0m"

    exit 2

else

    read -p "please input integer NO.2:" num2

    expr $num2 + 1 &>/dev/null

  if [ $? -eq 2 ]

    then

      echo -e "\033[41;33m $num2不是整数 \033[0m"

      exit 2

  fi

fi

if [ -z $num1 -o -z $num2 ]

  then

    echo "不能为空"

    exit 2

fi

if [ $num1 -eq $num2 ]

  then

    echo -e "\033[34m $num1 = $num2 \033[0m"

elif [ $num1 -gt $num2 ]

  then

    echo -e "\033[35m $num1 > $num2 \033[0m"

else

    echo -e "\033[36m $num1 < $num2 \033[0m"

fi

1.2.4 【练习题2】系统内存低于100M邮件报警,加入计划任务,3分钟检查一次。

对于开发程序而言,一般来说应该遵循下面的3步法则。

1)分析需求

    明白开发需求,是完成程序的大前提,因此,分析需求至关重要,一切不以需求为主的程序开发,都是耍流氓的!

2)设计思路

设计思路就是根据需求,把需求进行拆解,分模块逐步实现,例如本题可以分为如下几步:

1)获取当前系统剩余内存的值(先在命令行实现)。

2)配置邮件报警(可采用第三方邮件服务器)。

3)判断取到的值是否小于100MB,如果小于100MB,就报警(采用if语句)。

4)编码实现Shell脚本。

5)加入crond定时任务,每三分钟检查一次。

3)编码实现

    编码实现就是具体的编码及调试过程,工作中很可能需要先在测试环境下调试,调试好了,再发布到生产环境中。

第一步 先配置邮件服务,保证能够发生邮件

echo 'set from= smtp=smtp.znix.top smtp-auth-user= smtp-auth-password=****** smtp-auth=login' >> /etc/mail.rc

发送测试邮件发送

echo "`date +%F_%T`" |mail -s "这是测试邮件"

 image.png

第二步编写检查脚本

[root@kai scripts]# cat mem_info.sh

#!/bin/bash

Mem=`free -m |awk 'NR==2{print $NF}'`

host=`hostname`

Ip=`hostname -I`

Date=`date +%F_%T`

mail_file=/tmp/mail.s

dest_user=

if [ $Mem -lt 100 ]

then

echo "发生时间: $Date" >$mail_file

echo "发生主机: $host 主机IP地址: $Ip " >> $mail_file

echo "内存余量: $Mem M" >> $mail_file

mail -s "【警告】内存不足了呀!" $dest_user < $mail_file

fi

第三步测试脚本(可以修改判断的值)

[root@kai scripts]# sh mem_info.sh

image.png 

第四步 脚本测试成功,写入定时任务

[root@kai panduan1]# crontab -l

# 检查内存剩余大小

*/3 * * * * /bin/sh /server/scripts/panduan/mem_info.sh &>/dev/null

至此,一个监控脚本就写好了

1.2.5 【练习题3】模拟编写启动nginx脚本

注:编写restart状态时候,stop后先seelp 1,然后在start

脚本内容

[root@kai scripts]# cat nginx.sh 

 #!/bin/bash 

11 . /etc/init.d/functions

12

13 StartCheck=`netstat -lntup |grep -c 80`

14 StartCMD='/application/nginx/sbin/nginx '

15 StopCMD='/application/nginx/sbin/nginx -s stop '

16 StatusCheck=`netstat -lntp|grep -c nginx`

17 ReloadCMD='/application/nginx/sbin/nginx -s reload'

18 CheckCMD='/application/nginx/sbin/nginx -t'

19 UsaGe="Usage: $0 {start|stop|status|reload|check}"

20

21

22 COMMAND=$1

23

24 if [ $# -ne 1 ]

25 then

26 echo $UsaGe && exit 2

27 fi

28

29 if [ $COMMAND = start ]

30 then

31 if [ $StartCheck == 1 ]

32 then

33 action "启动Nginx失败,端口被占用" /bin/false

34 else

35 $StartCMD

36 action "启动Nginx" /bin/true

37 fi

38 elif [ $COMMAND = stop ]

39 then

40 $StopCMD &>/dev/null

41 if [ $? -eq 0 ]

42 then

43 action "停止Nginx" /bin/true

44 else45 action "停止Nginx" /bin/false

46 fi

47 elif [ $COMMAND = status ]

48 then

49 if [ $StatusCheck -eq 1 ]

50 then

51 echo "nginx 正在运行..."52 else53 echo "Nginx 未运行."54 fi

55 elif [ $COMMAND = reload ]

56 then

57 $ReloadCMD

58 action "reload" /bin/true

59 elif [ $COMMAND = check ]

60 then

61 $CheckCMD

62 else

63 echo $UsaGe

64 exit 2

65 fi

1.2.6 【练习题5】Web及MySQL服务异常监测案例

用if条件语句实现对Nginx Web服务以及MySQL数据库服务是否正常进行检测,如果服务未启动,则启动相应服务。

注意:

1.变量名不要和系统名冲突

2.像端口,配置文件这种多用变量,经常会变动的多用变量

  变量名不能望名生意

脚本编写思路:

判断web服务器正常 ↓

  1、进程 ps -ef |grep [n]ginx   #进程名和脚本名不能一样

  2、端口 netstat ss losf telnet nc nmap

  3、curl 页面 返回值    #curl -s -o /dev/null -I -w "%{http_code}\n"

  4、curl check.html 的内容

判断mysql服务器正常 ↓

1、端口 netstat ss losf telnet nc nmap

2、进程 ps -ef |grep [m]ysql

3、mysql 登录访问看一下

4、mysql insert一个数据 select一个数据(mysql -e "select version();")

web服务监控脚本示例

[root@kai scripts]# cat web_check.sh 

#!/bin/bash

11 . /etc/init.d/functions

12

13 JinChen=`ps -ef |grep -c [n]ginx`

14 QiDong='/server/scripts/nginx.sh start'

15 StatuS=`curl -I -w "%{http_code}\n" -o /dev/null -s 10.0.0.180`

16 StatuS2=`curl -s 10.0.0.180/check.html|grep -c ok`

17 StartNginx='/server/scripts/nginx.sh start'

18

19 if [ $JinChen -ge 2 ]

20 then

21 if [ "$StatuS" -eq 200 ]

22 then

23 if [ "$StatuS2" -eq 1 ]

24 then

25 action "Nginx 服务运行正常" /bin/true

26 else

27 action "请检查chenk.html文件!" /bin/false

28 fi

29 else

30 action "请检查首页文件!" /bin/false

31 fi

32 else

33 action "Nginx 未正常运行!" /bin/false

34 $StartNginx

35 fi

if 的其他用法:

if 后面不一定非得用[ ],还可以接命令进行判断

方法1:if ps -ef |grep [m]ysqld;then echo 1;else echo 0;fi

方法2:if ss -lntup |grep mysqld &> /dev/null

方法3:if ss -lnptu|grep mysqld &>/dev/null;then echo 1;else echo 0;fi

方法4:if ! ss -lntup |grep mysqld &> /dev/null;then echo 1;else echo 0;fi

方法5:if 

表达式  : 表达式值为1  表达式成立  

表达式值(布尔值)  

真1(成立) 命令执行成功     表达式值不为0

假0(不成立) 命令执行失败   表达式值为0  变量值为空

if ! 表达式  (可以是逻辑表达式、命令、变量)

then

  语句1

else

   语句2

fi

取出命令结果的错误的信息:

spacer.gifimage.png

01.取出nginx的错误信息

     nginx -t 2>&1|awk 'NR==1{print $NF}'

02.取出curl的状态码

     curl -I 10.0.0.8 2>&1|awk 'NR==4{print $2}'

03.把mysql的警告或错误信息定向到空

    /application/mysql-5.6.34/bin/mysql -uroot -  poldboy123 -  e 'show databases;' 2> /dev/null |grep oldboy

1.3 case条件结构语句

1.3.1 case语法结构

case "字符串变量" in

值1)

指令1

;;

值2)

指令2

;;

*)

指令

esac

1.3.2 case与if的对比

case书写方式

case $name in

值1)

指令1

;;

值2)

指令2

;;

*)

指令

esac

if书写方式

if [ $name == "值1" ]

then

指令1

elif [ $name == "值2" ]

then

指令2

else

指令

fi

1.3.3 case值的书写方式

apple)

echo -e "$RED_COLOR apple $RES"

;;

也可以这样写,输入2种格式找同一个选项

apple|APPLE)

echo -e "$RED_COLOR apple $RES"

;;

1.3.4 case语句小结

   1、  case语句就相当于多分支的if语句。case语句的优势是更规范、易读。

   2、case语句适合变量的值少,且为固定的数字或字符串集合。(1,2,3)或(start,stop,restart)。

      3、 菜单、系统服务启动脚本传参的判断多用case语句,多参考rpcbind/nfs/crond脚本;菜单脚本也可以使用case