2.shell脚本之条件语句

一,条件测试操作

  • 在shell脚本程序中,各条语句将按先后顺序依次执行,从而实现批量处理的自动化过程。通过正确使用if语句,进行条件测试操作,使Shell脚本具有一定的“判断”能力,以根据不同的条件来完成不同的管理任务。从而减轻了管理员本身的负担,提升工作效率

1.test命令

  • 使用专门的测试工具(test)命令,可以对特定条件进行测试,并根据返回值来判断条件是否成立(返回值为 0 表示条件成立反之)

语法格式:

格式一:test 条件表达式
格式二:[ 条件表达式 ] //中括号和表达式中间至少应有一个空格

[[ 条件表达式 ]]

  • 文件测试指的是根据给定的路径名称,判断对应的是文件还是目录,或者判断文件是否可读,可写,可执行等,文件测试的常见操作选项如下,使用时将测试对象放在操作选项之后即可

常用的测试选项:

-d:测试是否为目录(Directory)
-e:测试目录或文件是否存在(Exist)
-f:测试是否为文件(File)
-r:测试当前用户是否有权限读取(Read)
-w:测试当前用户是否有权限写入(Write)
-x:测试当前用户是否有权限执行(eXcute)
-b:测试是否为设备文件
-c:测试是否为字符设备文件
-s:测试存在且文件大小为空
-L:测试是否为链接文件

1.1文件测试
  • Shell 环境根据命令执行后的返回状态值($?)来判断是否执行成功,当返回值为 0 时表示成功,否则(非 0值)表示失败或异常

  • 要使 Shell脚本程序具备一定的"智能",面临的第一个问题就是如何区分不同的情况以确定执行何种操作。例如,当磁盘使用率超过95%时,发送告警信息;当备份目录不存在时,能够自动创建;当源码编译程序时,若配置失败则不再继续安装等

    //如果前面的命令成功了,则运行后面的命令,返回结果;&&是而且的意思
    [root@localhost opt]# test -f /etc/sysconfig/ && echo "yes" 
    [root@localhost opt]# test -d /etc/sysconfig/ && echo "yes"
    yes
    
    [root@localhost opt]# [ -f /home/qi ] && echo "yes"
    [root@localhost opt]# [ -d /home/qi ] && echo "yes"
    yes
    
    [root@localhost opt]# ls
    kgc
    [root@localhost opt]# [ -d /opt/kgc ]
    [root@localhost opt]# echo $?
    0
    [root@localhost opt]# [ -f /opt/kgc ]
    [root@localhost opt]# echo $?
    1
    [root@c7-1 home]# test -d /etc/sysconfig/ && echo "是目录"  
    是目录
    [root@c7-1 home]# echo $?
    0
    #存在此目录
    
    [root@c7-1 home]# [ -d /home/dashiji/ ]  
    [root@c7-1 home]# echo $?
    1
    #目录不存在
    
    [root@c7-1 home]# useradd dashiji
    [root@c7-1 home]# [ -d /home/dashiji/ ] && echo "YES"  
    YES
    [root@c7-1 home]# echo $?
    0
    
    

1.2整数值比较

  • 整数值比较指的是根据给定的两个整数值,判断第一个数与第二个数的关系,例如是大于,等于,小于第二个数
  • 整数值比较的常用作选项如下,使用时操作选项放在要比较的两个整数之间

常用测试操作符:

-eq:第一个数等于(Equal)第二个数
-ne:第一个数不等于(Not Equal)第二个数
-gt:第一个数大于( Greater Than)第二个数
-lt:第一个数小于(Lesser Than)第二个数
-le:第一个数小于或等于(Lesser or Equal)第二个数
-ge:第一个数大于或等于(Greater or Equal)第二个数

  • 格式:

[ 整数1 操作符 整数2 ]

[root@c7-1 home]# who | wc -l   //统计几个远程终端
3
[root@c7-1 home]# [ $(who | wc -l ) -le 5 ] && echo "用户太少"
用户太少
#判断远程终端是否小于等于五,若小于等于,则再运行后面的命令,echo "用户太少"

[root@c7-1 home]# [ $(who | wc -l ) -ge 2 ] && echo "用户太多"
用户太多

[root@c7-1 home]# Freec=$(free -m | grep "Mem:" | awk '{print $6}')
#定义变量Freec,检索Men,并打印(print)其中第六列($6)
[root@c7-1 home]# [ $Freec -lt 1024 ] && echo ${Freec}MB
416MB
#判断Freec是否小于1024,若小于;则运行 echo ${Freec}MB 

1.3字符串比较

  • 字符串比较通常用来检查用户输入,系统环境是否满足条件,在提供交互式操作的shell脚本中,也可以用来判断用户输入的位置参数是否符合要求

常用操作选项:

=:第一个字符串与第二个字符串相同

!=:第一个字符串与第二个字符串不相同,其中 “ !”符号表示取反

-z:检查字符串是否为空(zreo),对于定义或赋予空值的变量将视为空串

[root@c7-1 ~]# echo $LANG
zh_CN.UTF-8
[root@c7-1 ~]# [ $LANG != "en.US" ] && echo "not en.US"
not en.US
#测试语言环境,判断是否为英文,LANG等不等于en.US,若不等于,执行后面的命令 not en.US

[root@c7-1 ~]# read -p "yes/no: " ACK
yes/no: ^C
[root@c7-1 ~]# [ -z $ACK ] && echo "你的变量是空字符" 
你的变量是空字符

[root@localhost ~]# aaa=
[root@localhost ~]# [ -z $aaa ] && echo "是空的字符串"
是空的字符串

1.4逻辑测试

逻辑测试指的是判断两个或多个条件之间的依赖关系,当系统任务取决于多个不同的条件时,根据这些条件是否同时成立或者只要有其中一个成立等情况,需要有一个测试的过程

  • 常用的逻辑测试操作如下,使用时放在不同的测试语句或命令之间

  • 格式:

格式1: [ 表达式1 ] 操作符 [ 表达式2 ]

格式2: 命令1 操作符 命令2

  • 选项:

-a 或 && :逻辑与,“而且”的意思,只有当前后两个条件都成立时,整个测试命令的返回值﹐才为0(结果成立)。使用test命令测试时, && 可改为 -a

-o 或 || :逻辑或,“或者”的意思,只要前后两个条件中有一个成立,整个测试命令的返回值即为0(结果成立)。使用test命令测试时, || 可改为 -o

! :逻辑否,表示"不",只有当指定的条件不成立时,整个测试命令的返回值才为0(结果成立)

&&
[root@localhost ~]# [ -d /etc ] && [ -r /etc ] && echo "you can open it"
you can open it
[root@localhost ~]# echo $?
0
##只有前后两个条件都成立,才能返回0
[root@localhost ~]# [ -d /ack ] && [ -d /etc ] && echo "shimulu"  ##错误示范
[root@localhost ~]# echo $?
1

||
[root@localhost ~]# [ -d /ack ] || [ -d /etc ] && echo "shimulu"
shimulu
[root@localhost ~]# echo $?
0
##有一个条件成立即可
[root@localhost ~]# [ -d /ack ] || [ -d /grep ] && echo "shimulu"  ##错误示范
[root@localhost ~]# echo $?
1

二,if语句结构

1.单分支 if 语句结构

实际上使用 && 和 || 逻辑测试已经可以完成简单的判断并执行相应的操作,但是但需要选择执行的命令语句较多时,这种方式将使执行代码很复杂,不好分辨或理解,但使用了专用的 if 条件语句,可以更好的整理脚本结构,使得层次分明,清晰易懂

1.1语法格式

格式:

if 条件测试操作

then

​ 命令序列

fi

(if)判断条件,成立(then)命令输出 ,不成立(if)直接结束

image-20220625201250869

单分支 if 语句:对于单分支的选择结构,只有在“条件成立”时才会执行相应的代码,否则不执行任何操作

1.2例:简单使用单分支 if 判断
  • 注意判断 if 写完,后面有结尾 fi ,开头结尾要凑成一对否则会把语法错误
[root@c7-1 ~]# vim 1.sh
#!/bin/bash
if [ 4 -lt 5 ];then
echo "是的"
fi
[root@c7-1 ~]# chmod +x 1.sh   
[root@c7-1 ~]# ./1.sh
是的
##判断4是否小于5,成立输出是的,fi结束 
[root@localhost ~]# if [ 15 -gt 12 ];then echo "是的";fi
是的
##在命令行也可直接执行,使用但要用“ ;”分号隔离开
[root@c7-1 ~]# vim 1.sh
#!/bin/bash					//固定格式
if ls /opt > /dev/dull		//if条件测试判断,查看是否有opt目录,并/opt目录输出信息给黑洞
then						//条件成立
        echo "it is ok"		//则echo一个it is ok
fi							//fi 结束判断
[root@c7-1 ~]# chmod +x 1.sh    //给权限
[root@c7-1 ~]# ./1.sh 			//执行
it is ok

第二种连贯写脚本 ;分割即可
[root@c7-1 ~]# vim 1.sh
#!/bin/bash
if ls /opt > /dev/null;then
echo "有opt目录,把opt里面内容注入给黑洞"
fi
有opt目录,把opt里面内容注入给黑洞
[root@c7-1 ~]# vim 2.sh

#!/bin/bash
MOUNT_DIR="/mnt/centos7"				//定义变量
if [ ! -e $MOUNT_DIR ]					//if判断 是否/mnt/centos7 不存在 
then									//条件成立
        mkdir "/mnt/centos7"			//创建 /mnt/centos7 
        echo "$MOUNT_DIR 并不存在,现已创建"	//输出返回值
fi										//fi 结束判断

[root@c7-1 ~]# chmod +x 2.sh    	//给与权限
[root@c7-1 ~]# ./2.sh 				//执行
/mnt/centos7 并不存在,现已创建
[root@c7-1 ~]# ls /mnt
centos7
[root@c7-1 ~]# vim 3.sh

#!/bin/bash
read -p "请输入文件名:" file

if [[ $file = *.sh ]]
then
        echo "这是一个shell脚本"
fi

[root@c7-1 ~]# ./3.sh 
请输入文件名:3.sh
这是一个shell脚本

2.双分支 if 语句结构

  • 双分支 if 语句只是在单分支的基础上针对 “条件不成立” 的情况执行另一种操作,而不是 坐视不管 的不执行任何操作
2.1语法格式

格式:

if 条件测试操作

​ then 命令序列 1

​ else 命令序列 2

fi

(if)判断条件,成立(then)命令输出 ,不成立(else)命令输出 ,(if)直接结束

image-20220625223516863

2.2例:简单使用双分支 if 判断
  • 例:判断目标主机时否存活,存活就打印 is up,如果不存活就打印 is down

ping的选项:

-c:ping的次数

-i:每次多久ping一次,单位是秒

-W:反馈结果的时间,如果不通可加快反馈时间,单位是秒

[root@localhost ~]# vim 1.sh
#!/bin/bash                                ##基本格式
ip=192.168.113.125                         ##定义变量
ping -c 2 -i 0.1 -W 3 $ip &> /dev/null     ##ping测试,混合注入到黑洞中,不看结果
if [ $? -eq 0 ]                            ##返回值比较,意思就是 echo $?
then                      
   echo "$ip is up"                        ##ping通,成立输出 is up
else
   echo "$ip is down"                      ##ping不通,不成立输出 is down
fi
[root@localhost ~]# sh  1.sh               ##执行
192.168.113.125 is up                      ##成立ping的通输出 is up
192.168.113.341 is down                    ##不成立ping不通输出 is down
[root@c7-1 ~]# vim 1.sh
#!/bin/bash
if [ $UID -eq 0 ];then
        echo "当前登陆用户是管理员root"
else
        echo "当前登陆用户不是管理员root"
fi
[root@c7-1 ~]# sh 1.sh 
当前登陆用户是管理员root

[root@c7-1 ~]# cp 1.sh /home/zhangsan/
[root@c7-1 ~]# cd /home/zhangsan/
[root@c7-1 zhangsan]# chmod +x 1.sh 
[root@c7-1 zhangsan]# su zhangsan
[zhangsan@c7-1 ~]$ ./1.sh 
当前登陆用户不是管理员roo

3.多分支 if 语句结构

  • 与单分支,双分支 if 语句相比,多分支 if 语句的结构能够根据多个互拆条件分别执行不同的操作
3.1语法格式

格式:
if 条件测试操作1
then 命令序列1
elif 条件测试操作2
then 命令序列2
else
命令序列3
fi

(if)判断条件,成立(then)命令输出 ,再判断(elif),成立(then)命令输出,不成立(else)命令输出 ,(if)直接结束,可一直嵌套

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A2OEfZ3T-1656657942732)(C:\Users\qi\AppData\Roaming\Typora\typora-user-images\image-20220625233903494.png)]

3.2例:简单使用多分支 if 判断

例:根据输入的考试分数不同来区分优秀,合格,不及格三个档次

[root@localhost ~]# vim 2.sh
#!/bin/bash
read -p "请输入您的分数(0-100):" score
if [ $score -ge 85 ] && [ $score -le 100 ];then      //判断$score 是否大于等于85,小于等于100
        echo "$score 分,优秀"                        //条件满足则输出,不满足则继续往下进行判断
elif [ $score -ge 70 ] && [ $score -le 84 ];then
        echo "$score 分,合格"
elif [ $score -ge 0 ] && [ $score -le 69 ];then
        echo "$score 分,不及格"
else                                                //以上条件都不成立
        echo "请输入100以内的分数"
fi
[root@localhost ~]# sh 2.sh
请输入您的分数(0-100) 73 
73 分,合格
[root@localhost ~]# sh 2.sh
请输入您的分数(0-100) 1001
请输入100以内的分数

4.嵌套 if 语句结构

4.1例:判断 httpd 服务有没有启动

image-20220626140717090

[root@c7-1 ~]# vim httpd.sh

#!/bin/bash
pgrep -l httpd			//查找httpd进程
if [ $? -ne 0 ]			//判断是否在运行
then					//条件成立则
        if [ "$(rpm -q httpd)"="未安装软件包 httpd" ]		//判断httpd是否安装
        then											//条件成立
                yum install -y httpd					//没安装则安装
                systemctl start httpd					//启动服务
                echo "httpd服务已安装启动"				//输出已启动
        else											//若以上条件不成立
                systemctl start httpd					//启动httpd
                echo "httpd服务已启动"					//输出服务已启动
        fi												//结束判断
else					//若以上条件都不成立	
        echo "httpd is running"		//则输出running
f
[root@c7-1 ~]# vim user.sh

#!/bin/bash
read -p "请输入用户名:" user					//定义交互式变量
if grep $user /etc/passwd &>/dev/dull		//条件测试,判断是否有这个用户并输入给黑洞
then										//条件成立 则
        if [ -d /home/$user ]				//判断用户是否有家目录
        then								//若条件成立
                echo "该用户状态正常"			//输出状态正常
        else								//若以上条件都不成立
                read -p "该用户没有家目录,是否删除该用户,请输入[yes/no]:" ask	//定义交互式变量
                if [ $ask == yes ]			//判断输入的是不是yes
                then						//若条件成立
                        echo "正在删除用户。。。"		//输出
                        userdel $user &>/dev/null;sleep 2	//删除该用户并延迟两秒
                        echo "该用户已删除"			//输出

                elif [ $ask == no ]			//条件测试2,判断输入的是不是no
                then						//若条件成立
                        exit				//退出
                fi							//结束判断
        fi									//结束判断

else				//若以上条件都不成立
        echo "该用户不存在"	//输出一个该用户不存在
fi

5.case单循环语句结构

作用:

  • case 语句可以使脚本程序更加清晰,层次分明,常用于服务的启动,重启,停止的脚本,有的服务不提供这种控制脚本,需要用 case语句编写
  • case 语句使用于:某个变量存在多种取值,需要对其中的每一个取值分别执行不同的命令序列,这种情况与多分支的 if 语句非常相似,只不过 if 语句需要判断多个不同的条件,而 case 语句只是判断一个变量的不同取值

格式:

case 变量值 in
模式1)
	命令序列1
	;;
模式2)
	命令序列2
	;;
 .....
*)
	默认命令序列
esac
##case 行尾必须为单词 “ in " 每一模式必须以 “ ) “ 结束
##双分号 ”;;“ 表示序列的结束
##模式字符串中,可以用方括号表示一个连续的范围,例 [0-9],还可以用竖杠符号 “|”表示
##最后的“ *) ”表示默认模式,其中的 * 相当于通配符
  • case语句的执行流程:首先使用"变量值"与模式 1进行比较,若取值相同则执行模式 1

  • 后的命令序列,直到遇见双分号";;“后跳转至esac,表示结束分支;若与模式1不相匹配,则继续与模式⒉2进行比较,若取值相同则执行模式⒉后的命令序列,直到遇见双分号”;;"后跳转至

  • esac,表示结束分支…依此类推,若找不到任何匹配的值,则执行默认模式"+)”后的命令序列,直到遇见 esac后结束分支

5.1例:使用case编写脚本
#!/bin.bash
read -p "请输入一个字符,按Enter确定: " dxz
case $dxz in
[a-z]|[A-Z])
  echo "你输入的$dxz是英文字母"
 ;;
[0-9])
  echo "你输入的$dxz是数字"
 ;;
*)
  echo "你输入的$dxz是符号或特殊字符"
esac
[root@localhost ~]# sh 6.sh 
请输入一个字符,按Enter确定: 1
你输入的 1 是数字
[root@localhost ~]# sh 6.sh 
请输入一个字符,按Enter确定: q
你输入的 q 是英文字母
[root@localhost ~]# sh 6.sh 
请输入一个字符,按Enter确定: !
你输入的 ! 是符号或特殊字符
##使用case语句编写httpd服务的启动,重启,停止等,定义了位置变量,根据在字符界面输入信息,脚本就会自上而下找到在case定义的菜单(选项)执行,来控制服务
#!/bin/bash
case $1 in
start)      #1
/usr/bin/systemctl $1 httpd
/usr/bin/ps aux | grep httpd
echo "httpd start"
;;

stop)       #2
/usr/bin/systemctl $1 httpd
/usr/bin/ps aux | grep httpd
echo "httpd stop"
;;

restart)    #3
echo "httpd stop......"
/usr/bin/ps aux | grep httpd
/usr/bin/systemctl $1 httpd
echo "httpd restart......"
/usr/bin/ps aux |grep httpd
;;

status)    #4
/usr/bin/systemctl $1 httpd
;;
*)         #匹配除了1-4命令序列的所有
echo "plases inpunt start|stop|restart|status"
esac

行,来控制服务
#!/bin/bash
case $1 in
start) #1
/usr/bin/systemctl $1 httpd
/usr/bin/ps aux | grep httpd
echo “httpd start”
;;

stop) #2
/usr/bin/systemctl $1 httpd
/usr/bin/ps aux | grep httpd
echo “httpd stop”
;;

restart) #3
echo “httpd stop…”
/usr/bin/ps aux | grep httpd
/usr/bin/systemctl $1 httpd
echo “httpd restart…”
/usr/bin/ps aux |grep httpd
;;

status) #4
/usr/bin/systemctl $1 httpd
;;
*) #匹配除了1-4命令序列的所有
echo “plases inpunt start|stop|restart|status”
esac


猜你喜欢

转载自blog.csdn.net/weixin_61269220/article/details/125558609
今日推荐