shell-3.条件判断流程控制

一、条件判断语法结构

1. 条件判断语法格式

  • 格式1: test 条件表达式
  • 格式2: [ 条件表达式 ]
  • 格式3: [[ 条件表达式 ]] 支持正则 =~

特别说明:

1)[ 亲亲,我两边都有空格,不空打死你呦 ] 👿

2)[[ 亲亲,我两边都有空格,不空打死你呦 ]]👿

  1. 更多判断,man test去查看,很多的参数都用来进行条件判断

2. 条件判断相关参数

问:你要判断什么?

答:我要判断文件类型,判断文件新旧,判断字符串是否相等,判断权限等等…

判断文件类型

判断参数含义
-e判断文件是否存在(任何类型文件)
-f判断文件是否存在并且是一个普通文件
-d判断文件是否存在并且是一个目录
-L判断文件是否存在并且是一个软连接文件
-b判断文件是否存在并且是一个块设备文件
-S判断文件是否存在并且是一个套接字文件
-c判断文件是否存在并且是一个字符设备文件
-p判断文件是否存在并且是一个命名管道文件
-s判断文件是否存在并且是一个非空文件(有内容)

举例说明:

判断文件是否存在

[root@node2 shell102]# touch file1
[root@node2 shell102]# echo hello > file1
[root@node2 shell102]# test -e ./file1 
[root@node2 shell102]# echo $?
0
[root@node2 shell102]# test -e ./file2
[root@node2 shell102]# echo $?    --查看上一个命令的结果
1

判断目录是否存在

[root@node2 shell102]# mkdir dir1
[root@node2 shell102]# [ -d ./dir1 ]
[root@node2 shell102]# echo $?
0
[root@node2 shell102]# [ -d ./dir2 ]
[root@node2 shell102]# echo $?
1

判断是否是软连接

[root@node2 shell102]# ll
总用量 4
drwxr-xr-x. 2 root root 6 1020 10:17 dir1
-rw-r--r--. 1 root root 6 1020 10:13 file1
[root@node2 shell102]# ln -s file1 test1    --创建软连接
[root@node2 shell102]# ll
总用量 4
drwxr-xr-x. 2 root root 6 1020 10:17 dir1
-rw-r--r--. 1 root root 6 1020 10:13 file1
lrwxrwxrwx. 1 root root 5 1020 10:20 test1 -> file1
[root@node2 shell102]# [ -L ./test1 ]
[root@node2 shell102]# echo $?
0

删除file1
[root@node2 shell102]# rm -rf file1 ;[ -L ./test1 ];result=$?;echo $result   
0

[[]] 语法判断是否是普通文件
[root@node2 shell102]# [[ -f ./test1 ]];echo $?
1

判断目录不存在
[root@node2 shell102]# [ ! -d ./dir2 ];echo $?
0

㈡ 判断文件权限

判断参数含义
-r当前用户对其是否可读
-w当前用户对其是否可写
-x当前用户对其是否可执行
-u是否有suid,高级权限冒险位
-g是否sgid,高级权限强制位
-k是否有t位,高级权限粘滞位

粘滞位就是只有文件的创建者和root用户可以删除

练习
在这里插入图片描述

㈢ 判断文件新旧

说明:这里的新旧指的是文件的修改时间

判断参数含义
file1 -nt file2比较file1是否比file2新
file1 -ot file2比较file1是否比file2旧
file1 -ef file2比较是否为同一个文件,或者用于判断硬连接,是否指向同一个inode

判断软连接的两个文件是否为同一个文件

[root@node2 shell102]# ll
总用量 4
drwxr-xr-x. 2 root root 6 1020 10:17 dir1
-rw-r--r--. 1 root root 7 1020 11:05 file1
lrwxrwxrwx. 1 root root 5 1020 10:20 test1 -> file1

[root@node2 shell102]# [ file1 -ef test1 ];echo $?
0
[root@node2 shell102]# touch file2
[root@node2 shell102]# echo hello > file2
[root@node2 shell102]# [ file1 -ef file2 ];echo $?
1

即使file1和file2的内容一样,都是hello,也不是同一个文件

判断file2是继file1以后创建的

[root@node2 shell102]# [ file1 -ot file2 ];echo $?
0
[root@node2 shell102]# [ file2 -nt file1 ];echo $?
0

判断两个文件中的内容是否相同

一开始file1 和 file2中的内容都是hello
[root@node2 shell102]# diff file1 file2   --发现相同
[root@node2 shell102]# echo aa > file2
[root@node2 shell102]# diff file1 file2
1c1
< hello
---
> aa

㈣ 判断整数

判断参数含义
-eq相等
-ne不等
-gt大于
-lt小于
-ge大于等于
-le小于等于
[root@node2 shell102]# [ 1 -eq 2 ];echo $?
1
[root@node2 shell102]# [ 1 -ne 2 ];echo $?
0
[root@node2 shell102]# [ 3 -gt 2 ];echo $?
0
[root@node2 shell102]# [ 3 -lt 2 ];echo $?
1

判断字符串

判断参数含义
-z判断是否为字符串,字符串长度为0则成立
-n判断是否为非空字符串,字符串长度不为0则成立
string1 = string2判断字符串是否相等
string1 != string2判断字符串是否相不等

判断字符串是否为空

[root@node2 shell102]# test -z "hello world";echo $?
1
[root@node2 shell102]# n=" ";test -z $n;echo $?
0
[root@node2 shell102]# test -n "";echo $?  --判断非空
1
[root@node2 shell102]# test -n " ";echo $?  --判断非空
0
[root@node2 shell102]# test -z "";echo $?  --判断空
0
[root@node2 shell102]# test -z "  ";echo $?  --判断空
1 

判断字符串是否相等或者不等

[root@node2 shell102]# test "hello" = "world";echo $?
1
[root@node2 shell102]# test "hello" != "world";echo $?
0

多重条件判断

判断符号含义举例
-a 和 &&逻辑与[ 1 -eq 1 -a 1 -ne 0 ] [ 1 -eq 1 ] && [ 1 -ne 0 ]
-o 和 ||逻辑或[ 1 -eq 1 -o 1 -ne 1 ]

特别说明:

&& 前面的表达式为真,才会执行后面的代码

|| 前面的表达式为假,才会执行后面的代码

; 用于分割命令或表达式

判断当前用户是普通用户,还是管理员,要根据用户的uid来判断

[root@node2 shell102]# id
uid=0(root) gid=0(root)=0(root) 环境=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[root@node2 shell102]# id -u
0

[root@server ~]# [ $(id -u) -eq 0 ] && echo "the user is admin"
[root@server ~]$ [ $(id -u) -ne 0 ] && echo "the user is not admin"
[root@server ~]$ [ $(id -u) -eq 0 ] && echo "the user is admin" || echo "the user is not admin"

[root@server ~]# uid=`id -u`
[root@server ~]# test $uid -eq 0 && echo this is admin
this is admin
[root@server ~]# [ $(id -u) -ne 0 ]  || echo this is admin
this is admin
[root@server ~]# [ $(id -u) -eq 0 ]  && echo this is admin || echo this is not admin
this is admin
[root@server ~]# su - stu1
[stu1@server ~]$ [ $(id -u) -eq 0 ]  && echo this is admin || echo this is not admin
this is not admin

类C风格

注意:在(( ))中,=表示赋值;==表示判断
[root@server ~]# ((1==2));echo $?
[root@server ~]# ((1<2));echo $?
[root@server ~]# ((2>=1));echo $?
[root@server ~]# ((2!=1));echo $?
[root@server ~]# ((`id -u`==0));echo $?
 
[root@server ~]# ((a=123));echo $a
[root@server ~]# unset a
[root@server ~]# ((a==123));echo $?

字符串比较

注意:双引号引起来,看作一个整体;===[ 字符串 ] 比较中都表示判断
[root@server ~]# a='hello world';b=world
[root@server ~]# [ $a = $b ];echo $?
[root@server ~]# [ "$a" = "$b" ];echo $?
[root@server ~]# [ "$a" != "$b" ];echo $?
[root@server ~]# [ "$a" !== "$b" ];echo $?        错误
[root@server ~]# [ "$a" == "$b" ];echo $?
[root@server ~]# test "$a" != "$b";echo $?


test  表达式
[ 表达式 ]
[[ 表达式 ]]

思考:[ ][[ ]] 有什么区别?

[root@server ~]# a=
[root@server ~]# test -z $a;echo $?
[root@server ~]# a=hello
[root@server ~]# test -z $a;echo $?
[root@server ~]# test -n $a;echo $?
[root@server ~]# test -n "$a";echo $?

# [ '' = $a ];echo $?
-bash: [: : unary operator expected
2
# [[ '' = $a ]];echo $?
0


[root@server ~]# [ 1 -eq 0 -a 1 -ne 0 ];echo $?
[root@server ~]# [ 1 -eq 0 && 1 -ne 0 ];echo $?
[root@server ~]# [[ 1 -eq 0 && 1 -ne 0 ]];echo $?

man test 查询test的用法

[root@node2 shell102]# A="hello";B="world";[ $A=$B ];echo $?
0
[root@node2 shell102]# echo $A
hello
[root@node2 shell102]# A="hello";B="world";[ "$A"="$B" ];echo $?
0

------以上 = 左右没有空格,有问题

[root@node2 shell102]# A="hello";B="world";[ "$A" = "$B" ];echo $?
1
[root@node2 shell102]# A="hello";B="world";[ $A = $B ];echo $?
1
[root@node2 shell102]# A="hello";B="world";[ $A == $B ];echo $?
1

[]中一个=== 都表示“判断相等”

二、流程控制语句

  1. 基本语法结构

if结构

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

F:表示false,为假

T:表示true,为真

if [ condition ];then
		command
		command
fi

if test 条件;then
	命令
fi

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

[ 条件 ] && command

if…else结构

if [ condition ];then
		command1
	else
		command2
fi

[ 条件 ] && command1 || command2
[root@node2 shell102]# if test 1 -eq 1 ;then echo hello; fi
hello

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

vi if1.sh

[root@node2 shell102]# vi if1.sh
[root@node2 shell102]# chmod +x if1.sh

-------------------------------------
#!/bin/env bash
#....

read -p "Input content:" str

if test "$str" = "hello";then
  echo "world"
 else
   echo "请输入hello"
fi
-------------------------------------

[root@node2 shell102]# ./if1.sh 
Input content:jj
请输入hello
[root@node2 shell102]# ./if1.sh 
Input content:hello
world

vi if2.sh

#!/bin/env bash
#.....


if test "$#" -eq 0;then
echo "请输入参数 "
else
  echo "输入参数是:$1"
  if [ "$1" = "hello" ];then
     echo "world"
   else
      echo "请输入hello"
  fi
fi

chmod +x if2.sh

执行

[root@node2 shell102]# ./if2.sh  helloe
输入参数是:helloe
请输入hello
[root@node2 shell102]# ./if2.sh  hello
输入参数是:hello
world
[root@node2 shell102]# ./if2.sh
请输入参数 

vi if3.sh

#!/bin/env bash
A=hello
B=world
C="请输入hello"

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

if4.sh

#!/bin/env bash
A=hello
B=world
C="请输入hello"

read -p "请输入参数:" str
#方式1
#if [[ $str = hello ]];then
#    echo "$B"
# else
#    echo "$C"

#fi


#方式2
[[ $str = $A ]] && echo "$B" || echo "$C"

if…elif…else结构

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

t.sh

#!/bin/env bash

if [ 1 -eq 1 ];then
     echo 1
  elif [ 0 -ne 2 ];then
     echo 2
  elif [ 1 -ne 3 ];then
    echo 99
  else
     echo 3
fi


调用

[root@node2 shell102]# sh t.sh     ---这里采用了非标准方式执行
1
[root@node2 shell102]# bash -x t.sh    --查看执行过程
+ '[' 1 -eq 1 ']'
+ echo 1
1

三、应用案例

㈠ 判断两台主机是否ping通

① 思路

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

② 落地实现

在脚本当中尽量避免交互,ping -c 数字 ip地址,可以限制ping的次数

如果将ping的结果不显示,则可以

ping ip地址 &>/dev/null

[root@node2 dev]# ping -c1 124.0.0.100 &>/dev/null;echo $?
1  ---这里会阻塞,知道ping命令执行完以后,才会echo输出

vi ping.sh

#!/bin/env bash
#判断与指定的网络ip是否可以ping通

read -p "输入ip地址:" ipstr

# ping -c1 $ipstr &>/dev/null
ping -c1 $ipstr
if [ $? -eq 0 ];then
   echo "本机可以ping通$ipstr"
else
   echo "本机无法ping通$ipstr"
fi

chmod +x ping.sh

㈡ 判断一个进程是否存在

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

① 思路

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

② 落地实现

#!/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。
[root@node2 dev]# ps -ef |grep httpd
root     28321  1789  0 17:42 pts/0    00:00:00 grep --color=auto httpd
[root@node2 dev]# echo $?   --因为上面有输出,所以是0
0
[root@node2 dev]# ps -ef |grep httpd |grep -v 'grep'   --过滤掉grep进程
[root@node2 dev]# echo $?   --此时输出就是非0了
1

在这里插入图片描述

㈢ 判断一个服务是否正常

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

① 思路

  1. 可以判断进程是否存在,用/etc/init.d/httpd status判断状态等方法
  2. 最好的方法是直接去访问一下,通过访问成功和失败的返回值来判断
    • Linux环境,wget curl elinks -dump

进程存在,也有可能进程假死了,程序是无法正常访问的

wget www.baidu.com ,linux会将百度的首页index.html给下载下来

  --将百度首页下载到当前目录的baidu文件夹下
[root@node2 shell102]# wget -P ./baidu/ www.baidu.com &>/dev/null  
[root@node2 shell102]# ll
总用量 36
drwxr-xr-x. 2 root root   24 1020 18:08 baidu

[root@node2 shell102]# cd baidu/
[root@node2 baidu]# ll
总用量 4
-rw-r--r--. 1 root root 2381 1020 18:08 index.html
[root@node2 baidu]# 

② 落地实现

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

read -p "请输入门户首页网址:" web_url
wget -P ./index/ $web_url &>/dev/null
test $? -eq 0 && echo "当前网站:$web_url可以正常提供服务" && rm -rf ./index || echo "当前网站:$web_url无法
提供服务"

 [root@node2 shell102]# vi checkserver.sh 
[root@node2 shell102]# ./checkserver.sh 
请输入门户首页网址:www.baidu.com
当前网站:www.baidu.com可以正常提供服务
[root@node2 shell102]# ./checkserver.sh 
请输入门户首页网址:wwww.error.com
当前网站:wwww.error.com无法提供服务
[root@node2 shell102]# 

(四) 判断用户是否存在

**需求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 '不存在'



注意,用grep 用户名 /etc/passwd 来判断用户是否存在是不准确的,例如

[root@node2 shell102]# id yanweiling
uid=1000(yanweiling) gid=1000(yanweiling)=1000(yanweiling)
[root@node2 shell102]# grep weiling /etc/passwd
yanweiling:x:1000:1000::/home/yanweiling:/bin/bash
[root@node2 shell102]# echo $?
0
结果发现,weiling用户根本就不存在,但是也过滤grep出来了

所以需要精确匹配 grep -w 用户名 /etc/passwd

(五) 判断当前主机的内核版本

**需求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 '不符合要求'

shell中,默认变量是没有类型的,我们可以给变量赋予任何值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值