判断

条件判断语法格式(只作判断)

  • 格式1: test 条件表达式
  • 格式2: [ 条件表达式 ]
  • 格式3: [[ 条件表达式 ]] 支持正则
    注意,中括号两边都需要空格隔开;更详细的使用man test看文档。

判断文件类型

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

例子1

1
2
3
4
5
6
7
8
判断当前目录下有没有  file  这个文件
[root@localhost ~]# test -e ./file
---没输出任何东西,这是正常的---

查看是否有这个文件
[root@localhost ~]#echo $?
0
---显示 0 表示true(存在),显示 1 表示 false (不存在)---

例子2

1
2
3
---判断是否有这个文件夹,并且输出提示
[root@localhost ~]# [ -d ./dir ] ;echo $?
0

判断文件权限

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

判断文件新旧

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

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

判断整数

判断参数 含义
-eq 相等
-ne 不等
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于

判断字符串

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

多重条件判断

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

特别说明:

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

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

; 只用于分割命令或表达式

举例说明

  • 数值比较
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[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风格的数值比较
1
2
3
4
5
6
7
8
9
10
注意:在(( ))中,=表示赋值;==表示判断
[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 $?
  • 字符串比较
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
注意:双引号引起来,看作一个整体;= 和 == 在 [ 字符串 ] 比较中都表示判断
[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 $?

逻辑运算符总结

  1. 符号;和&&和||都可以用来分割命令或者表达式
  2. 分号(;)完全不考虑前面的语句是否正确执行,都会执行;号后面的内容
  3. &&符号,需要考虑&&前面的语句的正确性,前面语句正确执行才会执行&&后的内容;反之亦然
  4. ||符号,需要考虑||前面的语句的非正确性,前面语句执行错误才会执行||后内容;反之亦然
  5. 如果&&和||一起出现,从左往右依次看,按照以上原则

流程控制语句

if结构

F:表示false,为假;T:表示true,为真

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if [ condition ];then
command
command
fi

---

if test 条件;then
命令
fi

---

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

[ 条件 ] && command

if…else结构

1
2
3
4
5
6
7
if [ condition ];then
command1
else
command2
fi

[ 条件 ] && command1 || command2

if…elif…else结构

1
2
3
4
5
6
7
8
9
if [ condition1 ];then
command1 结束
elif [ condition2 ];then
command2 结束
else
command3
fi
注释:
如果条件1满足,执行命令1后结束;如果条件1不满足,再看条件2,如果条件2满足执行命令2后结束;如果条件1和条件2都不满足执行命令3结束.

例子,案例1

判断两台主机是否ping通

思路
  1. 使用哪个命令实现 ping -c次数
  2. 根据命令的==执行结果状态==来判断是否通$?
  3. 根据逻辑和语法结构来编写脚本(条件判断或者流程控制)
    实现
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #!/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

    # 逻辑运算符
    # test $? -eq 0 && echo "当前主机和远程主机$ip是互通的" || echo "当前主机和远程主机$ip不通的"

    例子,案例2

    判断一个进程是否存在

    思路
  4. 查看进程的相关命令 ps pgrep
  5. 根据命令的返回状态值来判断进程是否存在
  6. 根据逻辑用脚本语言实现
落地实现
1
2
3
4
5
6
7
8
9
10
11
#!/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进程不存在"

补充命令

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

例子,案例3

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

思路
  1. 可以判断进程是否存在,用/etc/init.d/httpd status判断状态等方法
  2. 最好的方法是 直接去访问 一下,通过访问成功和失败的返回值来判断
    • Linux环境,wget curl elinks -dump
实现
1
2
3
4
5
6
7
8
9
#!/bin/env bash
# 判断门户网站是否能够正常提供服务

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