五、流程控制语句-if选择结构

 

 

if选择结构

 

 箴言1:只要正确,就要一直向前冲

if选择结构-单分支

 

 

 

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

 

 

格式1:

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

 

格式2

 

 

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

 

 

 或者:

if [ condition ];then
        command
        command
fi

if test 条件;then
    命令
fi

if [[ 条件 ]];then
    命令
fi

[ 条件 ] && command

 

 

 

 

例子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选择结构-双分支

 箴言2:分叉路口,二选一

 

 

 

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

 

 

格式1:

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

 

 

 

格式2

 

 

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

 

或者:

if [ condition ];then
        command1
    else
        command2
fi

[ 条件 ] && command1 || command2

 

 

 特殊写法:

 

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

 

小试牛刀:

让用户自己输入字符串,如果用户输入的是hello,请打印world,否则打印“请输入hello”

 

    read定义变量
    if....else...

 

实现:

#!/bin/env bash

read -p '请输入一个字符串:' str
if [ "$str" = 'hello' ];then
    echo 'world'
 else
    echo '请输入hello!'
fi

  1 #!/bin/env bash
  2
  3 read -p "请输入一个字符串:" str
  4 if [ "$str" = "hello" ]
  5 then
  6     echo world
  7 else
  8     echo "请输入hello!"
  9 fi
  
  echo "该脚本需要传递参数"
  1 if [ $1 = hello ];then
  2         echo "hello"
  3 else
  4         echo "请输入hello"
  5 fi

#!/bin/env bash

A=hello
B=world
C=hello

if [ "$1" = "$A" ];then
        echo "$B"
    else
        echo "$C"
fi


read -p '请输入一个字符串:' str;
 [ "$str" = 'hello' ] && echo 'world' ||  echo '请输入hello!'

 

 

 

 

if选择结构-多分支

 箴言3:选择很多,能走的只有一条

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

 

 

 

 

 

 

 

格式1

 

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

 

或者:

if [ condition1 ];then
        command1      结束
    elif [ condition2 ];then
        command2       结束
    else
        command3
fi

 

 注释:

如果条件1满足,执行命令1后结束;如果条件1不满足,再看条件2,如果条件2满足执行命令2后结束;如果条件1和条件2都不满足执行命令3结束.

 

 

 

 

 

语法:

 

if [ condition1 ];then
        command1        
        if [ condition2 ];then
            command2
        fi
    else
        if [ condition3 ];then
            command3
        elif [ condition4 ];then
            command4
        else
            command5
        fi
fi

 

 

 

注释:
如果条件1满足,执行命令1;如果条件2也满足执行命令2,如果不满足就只执行命令1结束;
如果条件1不满足,不看条件2;直接看条件3,如果条件3满足执行命令3;如果不满足则看条件4,如果条件4满足执行命令4;否则执行命令5

 

 

 

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

学生成绩的分数范围在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 

 

层层嵌套结构

 

箴言4:多次判断,带你走出人生迷雾。

 

if [ condition1 ];then
        command1        
        if [ condition2 ];then
            command2
        fi
 else
        if [ condition3 ];then
            command3
        elif [ condition4 ];then
            command4
        else
            command5
        fi
fi
注释:
如果条件1满足,执行命令1;如果条件2也满足执行命令2,如果不满足就只执行命令1结束;
如果条件1不满足,不看条件2;直接看条件3,如果条件3满足执行命令3;如果不满足则看条件4,如果条件4满足执行命令4;否则执行命令5

 

 

2. 应用案例

 

㈠ 判断两台主机是否ping通

**需求:**判断当前主机是否和远程主机是否ping通

① 思路

 

    使用哪个命令实现 ping -c次数
    根据命令的执行结果状态来判断是否通$?
    根据逻辑和语法结构来编写脚本(条件判断或者流程控制)

 

② 落地实现

 

#!/bin/env bash
# 该脚本用于判断当前主机是否和远程指定主机互通

# 交互式定义变量,让用户自己决定ping哪个主机
read -p "请输入你要ping的主机的IP:" ip

# 使用ping程序判断主机是否互通
ping -c1 $ip &>/dev/null

if [ $? -eq 0 ];then
    echo "当前主机和远程主机$ip是互通的"
 else
     echo "当前主机和远程主机$ip不通的"
fi

 

或者:


#!/bin/bash
# Name:ping.sh
# Path:/shell02/
# Usage:/shell02/ping.sh
# ...

#使用ping命令来判断是否和远程主机互通
if [ $# -ne 1 ];then
        echo "Usage:$0 remote_ip" && exit

fi
或者
[ $# -ne 1 ] && echo "Usage:$0 remote_ip" && exit

ping -c1 $1 &>/dev/null
[ $? -eq 0 ] && echo "当前主机和远程主机$1是互通的。" ||echo "当前主机和远程主机$1是不通的。"

说明:exit直接退出程序

 

 

㈡ 判断一个进程是否存在

**需求:**判断web服务器中httpd进程是否存在

 

① 思路

 

    查看进程的相关命令 ps pgrep
    根据命令的返回状态值来判断进程是否存在
    根据逻辑用脚本语言实现

 

② 落地实现

 

#!/bin/env bash
# 判断一个程序(httpd)的进程是否存在
pgrep httpd &>/dev/null
if [ $? -ne 0 ];then
    echo "当前httpd进程不存在"
else
    echo "当前httpd进程存在"
fi

或者
test $? -eq 0 && echo "当前httpd进程存在" || echo "当前httpd进程不存在"

 


 

 

③ 补充命令

 

pgrep命令:以名称为依据从运行进程队列中查找进程,并显示查找到的进程id
选项
-o:仅显示找到的最小(起始)进程号;
-n:仅显示找到的最大(结束)进程号;
-l:显示进程名称;
-P:指定父进程号;pgrep -p 4764  查看父进程下的子进程id
-g:指定进程组;
-t:指定开启进程的终端;
-u:指定进程的有效用户ID。

 

㈢ 判断一个服务是否正常

**需求:**判断门户网站是否能够正常访问

 

① 思路

 

1.可以判断进程是否存在,用/etc/init.d/httpd status判断状态等方法

2.最好的方法是直接去访问一下,通过访问成功和失败的返回值来判断

Linux环境,wget curl elinks -dump

 

② 落地实现

 

#!/bin/env bash
# 判断门户网站是否能够正常提供服务

#定义变量
web_server=www.itcast.cn
#访问网站
wget -P /shell/ $web_server &>/dev/null
[ $? -eq 0 ] && echo "当前网站服务是ok" && rm -f /shell/index.* || echo "当前网站服务不ok,请立刻处理"

 

3. 课堂练习

 

 

㈠ 判断用户是否存在

**需求1:**输入一个用户,用脚本判断该用户是否存在

 

 #!/bin/env bash
  2 read -p "请输入一个用户名:" user_name
  3 id $user_name &>/dev/null
  4 if [ $? -eq 0 ];then
  6     echo "该用户存在!"
  7 else
  8     echo "用户不存在!"
  9 fi
  
  
#!/bin/bash
# 判断 用户(id) 是否存在
read -p "输入壹个用户:" id
id $id &> /dev/null
if [ $? -eq 0 ];then
        echo "该用户存在"
else
        echo "该用户不存在"
fi

#!/bin/env bash
read -p "请输入你要查询的用户名:" username
grep -w $username /etc/passwd &>/dev/null
if [ $? -eq 0 ]
then
    echo "该用户已存在"
else
    echo "该用户不存在"
fi

#!/bin/bash
read -p "请输入你要检查的用户名:" name
id $name &>/dev/null
if [ $? -eq 0 ]
then
echo 用户"$name"已经存在
else
echo 用户"$name"不存在
fi

#!/bin/env bash
#判断用户是否存在
read -p "请写出用户名" id
id $id
if [ $? -eq 0 ];then
        echo "用户存在"
else
        echo "用户不存在"
fi

#!/bin/env bash
read -p '请输入用户名:' username
id $username &>/dev/null
[ $? -eq 0 ] && echo '用户存在' || echo '不存在'

 

㈡ 判断软件包是否安装

**需求2:**用脚本判断一个软件包是否安装,如果没安装则安装它(假设本地yum已配合)

 

㈢ 判断当前主机的内核版本

**需求3:**判断当前内核主版本是否为2,且次版本是否大于等于6;如果都满足则输出当前内核版本

思路:
1. 先查看内核的版本号    uname -r
2. 先将内核的版本号保存到一个变量里,然后再根据需求截取出该变量的一部分:主版本和次版本
3. 根据需求进步判断


#!/bin/bash
kernel=`uname -r`
var1=`echo $kernel|cut -d. -f1`
var2=`echo $kernel|cut -d. -f2`
test $var1 -eq 2 -a $var2 -ge 6 && echo $kernel || echo "当前内核版本不符合要求"
或者
[ $var1 -eq 2 -a $var2 -ge 6 ] && echo $kernel || echo "当前内核版本不符合要求"
或者
[[ $var1 -eq 2 && $var2 -ge 6 ]] && echo $kernel || echo "当前内核版本不符合要求"

或者
#!/bin/bash
kernel=`uname -r`
test ${kernel:0:1} -eq 2 -a ${kernel:2:1} -ge 6 && echo $kernel || echo '不符合要求'

其他命令参考:
uname -r|grep ^2.[6-9] || echo '不符合要求'

 

4、判断ftp服务是否已启动,如果已启动输出以下信息:

vsftpd服务器已启动...

vsftpd监听的端口是:

vsftpd的进程PID是:

参考1:
#!/bin/bash
service vsftpd status &>/dev/null
if [ $? -eq 0 ];then
    port=`netstat -tnltp|grep vsftpd|cut -d: -f2|cut -d' ' -f1`
    pid=`pgrep -l vsftpd|cut -d ' ' -f1`
    echo -e "vsftpd服务器已启动...\nvsftpd监听的端口是:$port\nvsftpd的进程PID是:$pid"
else
    service vsftpd start &>/dev/null
    port=`netstat -tnltp|grep vsftpd|cut -d: -f2|cut -d' ' -f1`
   pid=`pgrep -l vsftpd|cut -d ' ' -f1`
   echo -e "vsftpd服务器已启动...\nvsftpd监听的端口是:$port\nvsftpd的进程PID是:$pid"
fi


参考2:
[root@server shell02]# cat liufeng.sh 
#!/bin/bash
service $1 status
if [ $? -eq 0 ];then
        echo " '$1'服务器已启动..."
        a=$( netstat -tnulp | grep $1 )
        array=($a)
        echo "$1的监听端口是:$(echo ${array[3]} | cut -d: -f2) "
        echo "$1的进程ID为:$(echo ${array[6]}| cut -d/ -f1)"
else
        echo "$1进程未启动!"
fi

参考3:
vim /lt/2.sh
#! /bin/bash
duankou=`netstat -ntlp|grep vsftpd|cut -d: -f2|cut -d" " -f1`
pid=`pgrep -o vsftpd`

vim 1.sh
pgrep -l vsftpd >/dev/null
if [ $? -eq 0 ];then
        echo "vsftpd服务器已启动..."
        echo "vsftpd监听的端口是:$duankou"
        echo "vsftpd的进程PID是:$pid"
else
        echo "vsftpd服务器没启动"
        service vsftpd start
        source /lt/2.sh
fi

 

 

 

 

参考:https://note.youdao.com/ynoteshare1/index.html?id=b402ca42248d060e7bdd5ee145f47cc5&type=notebook##/0367BDF68CCB4774B3846EE70F9B5237

 

 

 

posted @ 2018-05-03 08:28  钟桂耀  阅读(318)  评论(0编辑  收藏  举报