六、流程控制语句

选择结构if    只有条件判断结果为真时才执行相应的操作
循环结构
forwhile/until 反复执行相同操作时,使用循环结构
分支结构case 根据变量值的匹配结果执行相应的操作

if选择结构

if选择结构-单分支

 

当'条件成立'时执行相应的操作
否则,不执行任何操作

格式1:

if  条件判断表达式;then
    条件判断成立时,要执行的操作
 fi 

格式2

if  条件判断表达式
then
    条件判断成立时,要执行的操作
fi 

 或者:

if [条件]
    then 
        指令    #条件判断成立时,要执行的操作
fi
或者
if [条件];then
    指令
fi

例子1:

#!/bin/bash
ping -c 3 localhost &> /dev/null
if [ $? -eq 0 ];then
   echo aaaaa
   
fi

例子2:

#!/bin/bash
read -p "please input ip address " addr
if [ -z $addr ];then
    echo "你没有输入要ping的ip地址"
    exit
fi 
ping -c 3 $addr &> /dev/null
if [ $? -eq 0 ];then
   echo "$addr is onlines"
fi
echo "script over!!!"

 提示:分号相当于命令分号,上面两种语法等同。

特殊写法:if [ -f "$file1" ];then echo 1;fi相当于[ -f "$file1" ] && echo 1

 

下面举几个使用if条件句的例子

范例1:单分支if条件句整数比较大小

[root@localhost ~]#cat if_01.sh

a=$1

b=$2

if [ $a -gt $b ]

    then

    echo "yes,$a >= $b"

fi

 

if [ $a -le $b ]

    then

    echo "yes,$a<=$b"

fi

[root@localhost ~]# sh if_01.sh 4 5

yes,4<=5

范例2:使用read及脚本传参如何实现上述比较

解答:

[root@localhost ~]# cat if_01.sh

read -p "pls input two numbers:" a b

if [ $a -gt $b ]

    then

    echo "yes,$a >= $b"

fi

 

if [ $a -le $b ]

    then

    echo "yes,$a<=$b"

fi

[root@localhost ~]# sh  if_01.sh

pls input two numbers:100 99

yes,100 >= 99

提示:思考以上脚本有什么缺点?

范例3:实现如果/server/scripts下面存在if3.sh就打印if3.sh存在。(如果执行脚本后发现文件不存在,就创建这个脚本)

方法1:if条件句实现

[root@localhost scripts]# cat if4.sh

#!/bin/bash

 

FILEPATH="server/scripts"

if [ -e "$FILEPATH/if3.sh" ]

    then

    echo "$FILEPATH/if3.sh is exist."

fi

 

if [ ! -e "$FILEPATH/if3.sh" ]

    then

   [ ! -d $FILEPATH ] && mkdir -p $FILEPATH

[ -d $FILEPATH ] && {

cd $FILEPATH

touch if3.sh

echo "if3.sh is touched."

}

fi

[root@localhost scripts]# sh -x if4.sh

+ FILEPATH=server/scripts

+ '[' -e server/scripts/if3.sh ']'

+ '[' '!' -e server/scripts/if3.sh ']'

+ '[' '!' -d server/scripts ']'

+ mkdir -p server/scripts

+ '[' -d server/scripts ']'

+ cd server/scripts

+ touch if3.sh

+ echo 'if3.sh is touched.'

if3.sh is touched.

 

范例4:判断系统内存大小,低于100M就进行邮件报警

[root@localhost scripts]# free -m

             total       used       free     shared    buffers     cached

Mem:           988        769        218          0         97        313

-/+ buffers/cache:        358        629

Swap:         2047          0       2047

[root@localhost scripts]# free -m|awk '/buffers// {print $NF}'

629

[root@localhost scripts]# cat judge_system.sh

cur_free=`free -m|awk '/buffers// {print $NF}'`

chars="current memory is $cur_free."

if [ $cur_free -lt 650 ]

    then

    echo $chars

    echo $chars|mail -s "chars" 12345678@qq.com

fi

[root@localhost scripts]# sh judge_system.sh

current memory is 629.

用定时任务每分钟检查(如果每分钟检查的话,就不用输出了):

[root@localhost scripts]# cat judge_system.sh

chars="current memory is $cur_free."

if [ $cur_free -lt 650 ]

    then

    echo $chars|mail -s "chars" 12345678@qq.com

fi

[root@localhost scripts]# crontab -e

#judge.....

* * * * * /bin/bash /server/scripts/judge_system.sh >&/dev/null

if选择结构-双分支

 

当'条件成立'时执行命令序列1
否则,执行命令序列2

格式1:

if 条件判断表达式;then
  条件判断成立时,要执行的操作
else
  条件判断不成立时,要执行的操作
fi

格式2

if 条件判断表达式
then
  条件判断成立时,要执行的操作
else
  条件判断不成立时,要执行的操作
fi

 特殊写法:

if [ -f “$file1” ];then echo 1;else echo 0;fi相当于:[ -f “$file1” ] && echo 1 || echo 0

例子1:

如果httpd服务在运行着就输出 "网站服务正在运行"

如果httpd服务没有运行 就把网站服务开启

#!/bin/bash
service  httpd status  &> /dev/null
if [ $? -eq 0  ];then
   echo "网站服务正在运行"
else
   service httpd start 
fi

例子2:

#!/bin/bash
service sshd status &> /dev/null
if [ $? -eq 0 ];then
   echo "sshd in running"
else
    service sshd start
fi

例子3:

检查任意一个服务的状态

如果服务是运行着的就输出服务名is running

如果服务没有运行,就启动服务。

#!/bin/bash
service  $1  status  &>  /dev/null
if [ $? -eq 0 ];then
    echo "$1 is running!!!!"
else
    service $1 start
fi

只检查服务vsftpd httpd sshd crond mysql中的任意一个服务的状态如果不是这5就提示用户能够检查服务名并退出脚本

#!/bin/bash
read -p "请输入服务名" servername
if [ $ servername=="vsftpd" -o $servername=="httpd" -o $servername="sshd" -o $servername="crond" -o $servername=mysql];then
  service $servicename status &> /dev/null
 if [ $? -eq 0 ];then
   echo $ servicename is running
  else 
    service $servicename start
  fi 
fi

根据学生输入的成绩判断学生成绩的优劣。学生成绩的分数范围在1~100区间。成绩分数小于60输出不及格;成绩分数大于等于60输出 及格

read -p "请输入学生成绩:" chengji
if [ -z $chengji ];then
   exit
fi
if [ $chengji -ge 1 ]&&  [ $chengji -le 100 ]
then
    if [ $cengji -lt 60 ]
    then 
       echo "不及格"
    else 
       echo "及格"
    fi
else
    echo "输入格式错误"
fi

#ifelse_exam1脚本用于判断输入的文件名是否有对应的文件存在

#!/bin/bash
#if语句用于判断输入的文件是否不存在,不存在则执行then和else间的命令
if [ ! -e "$1" ]
then 
  echo "file $1 do not exist."
  exit 1
#输入的文件存在时,执行else和fi间的命令
else
    echo "file $1 exist."
fi

#ifelse_exam2脚本用于删除一个文件并判断是否执行了该操作

#!/bin/bash
#提示用户输入要删除的文件
echo "Please input the file which you want to delete:" read file
#通过if/else结构判断文件是否被删除
if rm -f "$file"
then 
   echo "Delete the file $file successfully!"
else
   echo "Delete the file $file failed!"
fi

每周一的 23:30 备份当前数据库服务器上所有的binlog日志文件到系统的/binlogdir目录里.

#!/bin/bash
mysql="/var/lib/mysql"
date=(date +\%Y\%m\%d)
cd $mysql
if [ -e /binlogdir ];then
   tar -zcf /binlogdir/binlog-$date.tar.gz data-bin.* &> /dev/null
else
    mkdir /binlogdir
  tar -zcf /binlogdir/binlog-$date.tar.gz data-bin.* &> /dev/null
fi

if选择结构-多分支

相当于if语句嵌套
针对多个条件分别执行不同的操作

 

格式1

if 条件判断表达式1;then
  条件1判断成立时,要执行的操作
elif 条件判断表达式2;then   条件2判断成立时,要执行的操作
if 条件判断表达式N;then   条件N判断成立时,要执行的操作
else   以上所有的条件判断都不成立时,要执行的操作 fi

根据学生输入的成绩判断学生成绩的优劣。

学生成绩的分数范围在1~100区间

成绩 分数小于60 输出 不及格

成绩 分数大于等于60且小于80 输出 良好

成绩 分数大于80且小于100 输出 优秀

如果输入的成绩超出成绩区间,就输出提示信息:成绩的分数范围在1~100区间

#!/bin/bash
read -p "输入成绩"  cj
if [ -z $cj ];then
    echo "你没有输入成绩分数"
    exit
else
   if [ $cj -eq 0 ];then
         echo "补考"
   elif [ $cj -lt 0 ];then
        echo "输入的成绩超过范围,有效范围在1-100"

elif [ $cj -ge 1 ]&&[ $cj -lt 60 ];then echo "不及格"

elif [ $cj -ge 60 ]&&[ $cj -lt 80 ];then echo "良好"

elif [ $cj -ge 80 ]&&[ $cj -le 100 ];then echo "优秀"

elif [ $cj -gt 1 ];then echo "输入的成绩超过范围,有效范围在1-100" fi fi

练习:写一个脚本
传递一个参数(单字符就行)给脚本,如参数为q、Q、quit或Quit,就退出脚本;否则,就显示用户的参数;

#!/bin/bash
#
if [ $1 = 'q' ];then
  echo "Quiting..."
  exit 1
elif [ $1 = 'Q' ];then
  echo "Quiting..."
  exit 2  
elif [ $1 = 'quit' ];then
  echo "Quiting..."
  exit 3 
elif [ $1 = 'Quit' ];then
  echo "Quiting..."
  exit 4  
else
  echo $1
fi

#ifelifelse_exam1.sh脚本

#!/bin/bash
#提示用户输入分数(0100)
echo "Please Input a integer(0-100): "
read score
#判断学生的分数类别
if [ "$score" -lt 0 -o "$score" -gt 100 ]
then
       echo "The score what you input is not integer or score is not in (0-100)"
elif [ "$score" -ge 90 ]
then
       echo "The grade is A!"
elif [ "$score" -ge 80 ]
then 
       echo "The grade is B! "
elif [ "$score" -ge 70 ]
then
       echo  "The grade is C!"
elif [ "$score" -ge 60 ]
then
       echo "The grade is D! " 
else
       echo "The grade is E! "
fi

判断是否是闰年

#ifelifelse-exam2.sh脚本的执行结果
#!/bin/bash
#提示输入年份
echo "Please input a year: "
read year
#设置取余参数
let "n1=$year % 4"
let "n2=$year % 100"
let "n3=$year % 400"
#判断输入的年份是否是闰年
if [ ! "$n1" -eq 0 ]
then 
   leap=0
elif [ ! "$n2" -eq 0 ]
then 
   leap=1
elif [ ! "$n3" -eq 0 ]
then 
   leap=0
else
   leap=1
fi
#输出用户输入的年份是否是闰年
if [ "$leap" -eq 1 ]
then 
    echo "$year is a leap year!"
else
    echo "$year is not a leap year!"
fi

范例5:多分支if条件句整数比较大小

[root@localhost scripts]# cat if_02.sh
read -p "pls input two numbers:" a b
if [ $a -gt $b ]
    then
            echo "yes,$a > $b"
elif [ $a -eq $b ]
    then
            echo "yes,$a=$b"
else
    echo "yes,$a<$b"
fi

[root@localhost scripts]# sh if_02.sh

pls input two numbers:4 5

yes,4<5

范例6:以命令行脚本传参的方式比较两个数的大小,请用多分支if语句来实现。

1:多分支if语句实现对传入的参数进行判断的方法

[root@localhost scripts]# cat if_02.sh

a=$1
b=$2
if [ $# -ne 2 ]
    then
    echo "Usage:sh $0 num1 num2"
exit 1
fi
 
if [ $a -gt $b ]
    then
            echo "yes,$a > $b"
elif [ -eq $b ]
    then
            echo "yes,$a=$b"
else
    echo "yes,$a<$b"
fi

 

2:多分支if语句实现对参数个数及类型严格判断的方法

[root@localhost scripts]# cat if_02.sh
a=$1
b=$2
if [ $# -ne 2 ]
    then
    echo "Usage:sh $0 num1 num2"
exit 1
fi
[ -n "`echo $1|sed ' s/[0-9]//g'`" ]&& echo "第一个参数必须为数字" && exit 1
[ -n "`echo $2|sed ' s/[0-9]//g'`" ]&& echo "第二个参数必须为数字" && exit 1
 
if [ $a -gt $b ]
    then
            echo "yes,$a > $b"
elif [ -eq $b ]
    then
            echo "yes,$a=$b"
else
    echo "yes,$a<$b"
fi

 

扩展:判断字符串是否为数字的多种方法

1:sed加正则表达式

命令行传参:

组合语法判断1:

[ -n "`echo $num|sed ' s/[0-9]//g'`" -a -n "`echo $2|sed ' s/[0-9]//g'`" ] &&

echo "两个参数都必须为数字" && exit 1

组合语法判断2:

[ -n "`echo $num|sed ' s/[0-9]//g'`" -a -n "`echo $2|sed ' s/[0-9]//g'`" ] &&{

echo "两个参数都必须为数字

exit 1

}

单个判断语法:

[ -n "`echo $1|sed ' s/[0-9]//g'`" ] && echo "第一个参数必须为数字" && exit 1

[ -n "`echo $2|sed ' s/[0-9]//g'`" ] && echo "第二个参数必须为数字" && exit 1

普通变量判断:

[ -n "`echo $num|sed ' s/[0-9]//g'`" ] && echo "第二个参数必须为数字" && exit 1

条件表达式,大括号的用法:

[ -n "`echo $num|sed ' s/[0-9]//g'`" ] && {

echo "第二个参数必须为数字"

exit 1

}

2:变量的子串替换加正则表达式

[root@localhost scripts]# num=oldboy512

[root@localhost scripts]# [ -z "`echo "${num//[0-9]/}"`" ] && echo 1 || echo 0

0

[root@localhost scripts]# num=512old512

[root@localhost scripts]# [ -z "`echo "${num//[0-9]/}"`" ] && echo 1 || echo 0

0  #这个说明前面的结果不为0,即有非数字字符

[root@localhost scripts]# num=521

[root@localhost scripts]# [ -z "`echo "${num//[0-9]/}"`" ] && echo 1 || echo 0

1  #这个说明前面的结果去掉数字后为0,即没有非数字字符

3:变量的子串替换加正则表达式(特殊判断思路)

思路:如果num长度不为0,并且把num中的非数字部分删除,然后看结果是不是等于num本身,如果两者都成立就是数字。

-z “$num”  #如果num长度不为0表达式

 “$num” ="${num//[^0-9]/}"  #把num中的非数字部分删除,然后结果是不是等于num本身,如果两者都成立就是数字。

完整表达式:

[root@localhost scripts]# [ -n "$num" -a "$num" = "$num//[^0-9]/" ] && echo "it is num"

4:expr计算判断

expr $1 + 0>/dev/null 2>&1  #把变量和整数相加看是否成功执行

[ $? -eq 0 ] && eccho init

范例5:通过read读入变量方式的多分支if语句比较整数大小

[root@localhost scripts]#cat if-multi.sh

#!/bin/bash

#this scripts is created by oldboy

#fun:compare two num

read -t 10 -p "pls input two num:"  a b

if [ $a -gt $b ];then

    echo "yes,$a > $b"

elif [ -eq $b ];then

    echo "yes,$a=$b"

else

    echo "yes,$a<$b"

fi

另一种写法:用(())代替[]

[root@localhost scripts]#cat if-multi.sh

#!/bin/bash

#this scripts is created by oldboy

#fun:compare two num

read -t 10 -p "pls input two num:"  a b

if (( $a > $b ));then

    echo "yes,$a > $b"

elif [ -eq $b ];then

    echo "yes,$a=$b"

else

    echo "yes,$a<$b"

fi

特别提示:一般生产运维中的脚本,使用read的方式很少,除非为用户写交互式程序脚本。一般为传参或者定义变量的方式。

范例6:生产环境监控MySQL服务的实战例子

问题描述:监控MySQL服务是否正常启动,如果没有正常启动,就启动MySQL服务。这里需要大家实现准备MySQL服务的基本环境。

1:本方法的实现思路是过滤出MySQL端口3306进行判断。具体脚本如下:

[root@localhost script]# cat check_db.sh

#!/bin/bash

###

portNum=`netstat -lnt | grep 3306|awk -F '[ :]+' '{print $5}'`   #这里的思路不是最佳的

if [ #portNum -eq 3306 ];then   #这里的判断最好用字符串判断的语法;假如端口不存在,显示[: -eq: unary operator expected

    echo "db is running"

else

    /data/3306/mysql restart   #这是多实例MySQL启动脚本

fi

思考:本脚本的好处和局限是什么?

或者:

[root@localhost script]# cat check_db.sh

#!/bin/bash

###

 

portNum=`netstat -lnt | grep 3306|awk -F '[ :]+' '{print $5}'`

if [ $portNum -eq 3306 ];then

    echo "db is running"

else

    /etc/init.d/mysqld restart   #普通MySQL服务启动

fi

 

解决-eq: unary operator expected的方法:不规范;对于多实例脚本启动有效,但对普通MYSQL启动问题仍然存在

[root@localhost script]# cat check_db01.sh

 

#!/bin/bash

###

 

portNum=`netstat -lnt | grep 3306|awk -F '[ :]+' '{print $5}'`

if [ $portNum == “3306” ];then

    echo "db is running"

else

    /data/3306/mysql restart

fi

通过端口判断更简易实现脚本

[root@localhost script]# cat check_db02.sh

 

#!/bin/bash

###

 

portNum=`netstat -lnt | grep 3306|wc -l`

if [ #portNum -eq 1 ];then

    echo "db is running"

else

    /data/3306/mysql restart

fi

 

2:本方法的实现思路是如果MySQL端口和端口同时存在,即认为MySQL服务正常。

(1)写脚本前首先人工检查MySQL服务是否OK

[root@localhost script]# /data/3306/mysql start

正在启动 mysqld:

[root@localhost ~]# netstat -lnt | grep 3306

tcp        0      0 0.0.0.0:3306                0.0.0.0:*                   LISTEN   

[root@localhost script]# ps -ef|grep mysql|grep -v grep|wc -l

2   #通过把进程转换成为行数,即进程个数,方便做判断。

[root@localhost ~]# netstat -lnt | grep 3306|wc -l

1  #通过把端口转换为行数,即端口个数,方便做判断

提示:根据以上结果可以知道MySQL服务是正常的(多数情况下)。

2)实际的脚本监控内容

方法1:

[root@localhost script]# cat check_db03.sh

#!/bin/bash

###

 

portNum=`netstat -lnt | grep 3306|wc -l`

mysqlProcessNum=`ps -ef|grep mysql|grep -v grep|wc -l`

 

if [ #portNum -eq 1 -a $mysqlProcessNum -eq 2 ];then

    echo "db is running"

else

    /data/3306/mysql restart

fi

或者

[root@localhost script]# cat check_db03.sh

 

#!/bin/bash

###

 

portNum=`netstat -lnt | grep 3306|wc -l`

mysqlProcessNum=`ps -ef|grep mysql|grep -v grep|wc -l`

 

if [ #portNum -eq 1 ] && [ $mysqlProcessNum -eq 2 ];then

    echo "db is running"

else

    /data/3306/mysql restart

fi

方法2:

[root@localhost script]# cat if-judge-db0.sh

#!/bin/bash

###

MYSQL=/data/3306/mysql

LogPath=/tmp/mysql.log

portNum=`netstat -lnt | grep 3306|wc -l`

mysqlProcessNum=`ps -ef|grep mysql|grep -v grep|wc -l`

 

if [ #portNum -eq 1 ] && [ $mysqlProcessNum -eq 2 ];then

    echo "db is running"

else

    $MYSQL start >$LogPath

    sleep 10

    portNum=`netstat -lnt | grep 3306|wc -l`

    mysqlProcessNum=`ps -ef|grep mysql|grep -v grep|wc -l`

    if [ #portNum -ne 1 ] && [ $mysqlProcessNum -ne 2 ];then

    while true

    do

        killall mysqld >/dev/null 2>&1

        [ $? -ne 0 ] && break

        sleep 1

    done

        $MYSQL start >>$LogPath && status="successful" || status="failure"

        mail -s "mysql startup status is $status" 1092327070@qq.com < $LogPath

    fi

fi

3:本方法的实现思路是:模拟web服务器,通过mysql账户连接mysql,然后根据返回命令状态或返回内容确认mysql是否正常(推荐)

(1)手动检查(写脚本之前都离不开手工检查):

[root@localhost script]# mysql -uroot -p 'oldboy' -S /data/3306/mysql.sock -e "select version();"

(1)简单的脚本实现:

1:

 2:

[root@localhost script]# cat check_db.sh
#!/bin/bash
###
mysqlStatus=`mysql -uroot -p 'oldboy' -S /data/3306/mysql.sock -e "select version();" >& /dev/null`

if [ $? -eq 0 ];then
    echo "db is running"
else
    /data/3306/mysql restart
fi

 复杂点的脚本实现:

#!/bin/bash
###
MYSQL=/data/3306/mysql
LogPath=/tmp/mysql.log
mysqlStatus=`mysql -uroot -p 'oldboy' -S /data/3306/mysql.sock -e "select version();" >&/dev/null`

if [$? -eq 0 ];then
echo "db is running"
exit 0
else
    $MYSQL start >$LogPath
     sleep 10
    
    mysqlStatus=`mysql -uroot -p 'oldboy' -S /data/3306/mysql.sock -e "select version();" >&/dev/null`
    if [ $? -ne 0 ];then
     while true
     do 
        killall mysqld >/dev/null 2>&1
        [ $? -ne 0 ] && break
        sleep 1
    done
        $MYSQL start >>$LogPath && status="successful" || status="failure"
        mail -s "mysql startup status is $status" 12345678@qq.com < $LogPath
    fi
fi 

4:更专业的监控数据库生成脚本解决方案

#!/bin/bash
###
MYSQL=/data/3306/mysql
LogPath=/tmp/mysql.log
mysqlStatus=`mysql -uroot -p 'oldboy' -S /data/3306/mysql.sock -e "select version();" >&/dev/null`

if [$? -eq 0 ];then
    echo "db is running"
else
    [ -x $MYSQL ] && $MYSQL start >$LogPath
    sleep 10
    
    mysqlStatus=`mysql -uroot -p 'oldboy' -S /data/3306/mysql.sock -e "select version();" >&/dev/null`
    if [ $? -ne 0 ];then
    while true
    do 
        killall mysqld >/dev/null 2>&1
        [ $? -ne 0 ] && break
        sleep 1
    done
        [ -x $MYSQL ] && $MYSQL start >>$LogPath && status="successful" || status="failure"
        mail -s "mysql startup status is $status" 1092327070@qq.com < $LogPath
    fi
fi 
原文地址:https://www.cnblogs.com/zhongguiyao/p/8983649.html