11.Shell脚本修炼手册---IF 条件语句的知识与实践
if 条件语句的知识与实践
文章目录
- if 条件语句的知识与实践
- if 条件语句
- if 条件语句的语法
- 1. 单分支结构(满足条件才执行)
- 2. 双分支结构(二选一执行)
- 3. 多分支结构(多选一执行)
- if 条件表达式的 5 种写法
- 逻辑运算符替换规则(巩固扩展)
- **一、整数比较运算符(常用)**
- 二、字符串比较运算符(常用)
- 三、文件测试运算符(常用)
- if 条件语句实践
- **实验 1:检测并启动 sshd 服务**
- **实验 2:通过参数控制 sshd 服务(start/stop/restart)**
- **实验 3:三个整数从大到小排序**
- **实验 4:监控系统内存(低于 100M 时发邮件)**
- if 条件语句企业案例精讲
- 监控 Web 服务(Apache)和数据库(MySQL)
- 比较两个整数的大小(带参数校验)
- 判断字符串是否为数字(多种方法)
- 开发 rsync 服务启动脚本(模拟系统服务)
if 条件语句
if 条件语句是 Linux 运维中最常用的语句之一,无论是简单的服务检查还是复杂的业务判断,都离不开它。掌握 if 条件语句,能让你轻松应对各种场景下的逻辑判断需求。
if 条件语句的语法
if 条件语句的核心逻辑和我们日常说的 “如果… 那么…” 完全一致。根据判断场景的复杂程度,它分为三种结构:单分支、双分支和多分支。
1. 单分支结构(满足条件才执行)
单分支就像日常决策中的 “如果满足 A,就做 B”。比如 “如果下雨,就带伞”。
语法格式 1(换行写法):
if <条件表达式> # 判断条件是否成立then # 如果成立,就执行下面的指令指令 # 具体要执行的操作
fi # 结束判断(if的反向拼写,标记语句结束)
语法格式 2(紧凑写法):
if <条件表达式>;then # 分号替代换行,功能和上面完全一样指令
fi
举个例子:
如果/tmp/bq
目录不存在,就创建它。
# 判断/tmp/bq是否不是目录(!表示否定,-d检查是否为目录)
if [ ! -d /tmp/bq ];thenmkdir /tmp/bq # 不存在则创建目录
fi
嵌套用法:
if 语句内部还可以再放 if 语句(类似 “如果 A 成立,且 B 也成立,就做 C”)。注意每个 if 都要对应一个 fi,缩进对齐更易读。
if [ 条件1 ];then# 条件1成立后,再判断条件2if [ 条件2 ];then指令 # 只有条件1和条件2都成立才执行fi # 关闭条件2的判断
fi # 关闭条件1的判断
2. 双分支结构(二选一执行)
双分支对应 “如果满足 A,就做 B;否则,就做 C”。比如 “如果考试及格,就出去玩;否则,在家复习”。
语法格式:
if <条件表达式>;then指令集1 # 条件成立时执行
else指令集2 # 条件不成立时执行
fi
举个例子:
检查/tmp/bq
目录是否存在,存在就提示,不存在就创建。
if [ -d /tmp/bq ];thenecho "/tmp/bq 已存在" # 存在时提示
elsemkdir /tmp/bq # 不存在时创建
fi
3. 多分支结构(多选一执行)
多分支对应 “如果满足 A,做 B;如果满足 C,做 D;否则,做 E”。比如 “如果成绩≥90,评优;≥60,及格;否则,挂科”。
语法格式:
if <条件表达式1>;then指令1 # 满足条件1时执行
elif <条件表达式2>;then # else if的缩写,可多个指令2 # 满足条件2时执行
else指令3 # 所有条件都不满足时执行
fi
注意:
- 每个
elif
后面必须跟then
- 最后一个
else
后面没有then
if 条件表达式的 5 种写法
if 后面的 “条件表达式” 可以有多种形式,本质都是判断 “成立(真)” 或 “不成立(假)”,选一种你习惯的即可。
表达式类型 | 语法示例 | 说明 |
---|---|---|
test 命令 | if test 1 -eq 1;then echo "相等";fi | 最基础的条件判断命令 |
[] 符号 | if [ 1 -eq 1 ];then echo "相等";fi | 简化的 test 写法(注意括号内外有空格) |
[[]] 符号 | if [[ 1 -eq 1 ]];then echo "相等";fi | 增强版 [],支持更多语法(如字符串模式匹配) |
(()) 符号 | if ((1 == 1));then echo "相等";fi | 专门用于整数计算和比较 |
直接用命令 | if ls /tmp;then echo "成功";fi | 命令执行成功(返回值 0)则条件成立 |
举个例子:用命令作为条件
检查 sshd 服务是否未运行,如果是则输出 “fail”:
# systemctl status sshd | grep -q inactive:查找"inactive"(静默模式,不输出内容)
# 命令执行成功(找到关键词)则条件成立,执行echo
if systemctl status sshd | grep -q inactive; then echo fail; fi
逻辑运算符替换规则(巩固扩展)
在shell脚本中,逻辑运算符有特定的写法,不能直接用&&
(与)、||
(或)等符号进行表达,需要有专门的关键字替代,为了增强记忆,如下在进行一个逻辑运算符的详细替换规则和示例操作:
一、整数比较运算符(常用)
用于比较两个整数的大小关系,只能用于数字,不能用于字符串或小数。
运算符 | 含义 | 示例 |
---|---|---|
-eq | 等于(equal) | [ 5 -eq 5 ] → 成立(返回真) |
-ne | 不等于(not equal) | [ 5 -ne 3 ] → 成立 |
-gt | 大于(greater than) | [ 10 -gt 5 ] → 成立 |
-lt | 小于(less than) | [ 3 -lt 8 ] → 成立 |
-ge | 大于等于(greater or equal) | [ 7 -ge 7 ] → 成立 |
-le | 小于等于(less or equal) | [ 4 -le 6 ] → 成立 |
示例1:基本整数的比较
a=10
b=20# 判断a是否等于b
if [ $a -eq $b ];thenecho "$a 等于 $b"
elseecho "$a 不等于 $b" # 执行此句(10≠20)
fi# 判断a是否大于b
if [ $a -gt $b ];thenecho "$a 大于 $b"
elseecho "$a 不大于 $b" # 执行此句(10<20)
fi
示例2:结合逻辑运算符的多条件判断
score=85# 判断分数是否在60~100之间(包含边界)
if [ $score -ge 60 -a $score -le 100 ];thenecho "成绩有效:$score 分" # 85在范围内,执行此句
elseecho "成绩无效"
fi# 判断分数是否小于60或大于100(无效成绩)
if [ $score -lt 60 -o $score -gt 100 ];thenecho "成绩无效"
elseecho "成绩有效:$score 分" # 执行此句
fi
二、字符串比较运算符(常用)
用于比较字符串的内容或长度,注意字符串变量最好用双引号包裹,避免空格导致的错误。
运算符 | 含义 | 示例 |
---|---|---|
= 或 == | 字符串相等(== 在[] 中兼容,推荐用= ) | [ "abc" = "abc" ] → 成立 |
!= | 字符串不相等 | [ "abc" != "def" ] → 成立 |
-z | 字符串长度为 0(空字符串) | [ -z "" ] → 成立 |
-n | 字符串长度不为 0(非空字符串) | [ -n "hello" ] → 成立 |
< | 字符串按字典序小于(需用\ 转义,或在[[]] 中使用) | [ "apple" \< "banana" ] → 成立 |
> | 字符串按字典序大于(需用\ 转义) | [ "cat" \> "bat" ] → 成立 |
示例 3:字符串相等性判断
name="Alice"
input="alice"# 判断两个字符串是否完全相等(区分大小写)
if [ "$name" = "$input" ];thenecho "名字匹配"
elseecho "名字不匹配" # 执行此句(Alice≠alice)
fi# 判断字符串是否为空
empty_str=""
if [ -z "$empty_str" ];thenecho "字符串为空" # 执行此句
elseecho "字符串非空"
fi
示例 4:字符串字典序比较
str1="apple"
str2="apricot"# 判断str1是否按字典序小于str2(注意<需要转义)
if [ "$str1" \< "$str2" ];thenecho "$str1 在字典中位于 $str2 之前" # 执行此句(apple < apricot)
elseecho "$str1 在字典中位于 $str2 之后"
fi
三、文件测试运算符(常用)
用于判断文件的类型、权限等属性,是运维脚本中非常常用的判断条件。
运算符 | 含义 | 示例 |
---|---|---|
-f | 是否为普通文件(非目录、非设备) | [ -f "test.txt" ] → 文件存在且是普通文件则成立 |
-d | 是否为目录 | [ -d "docs" ] → 目录存在则成立 |
-e | 文件或目录是否存在 | [ -e "file.txt" ] → 存在则成立 |
-r | 是否有读权限 | [ -r "data.txt" ] → 有读权限则成立 |
-w | 是否有写权限 | [ -w "log.txt" ] → 有写权限则成立 |
-x | 是否有执行权限 | [ -x "script.sh" ] → 有执行权限则成立 |
-s | 文件是否存在且不为空(大小 > 0) | [ -s "info.txt" ] → 文件非空则成立 |
示例 5:文件属性判断
file="example.sh"# 判断文件是否存在且是可执行脚本
if [ -f "$file" -a -x "$file" ];thenecho "$file 是可执行脚本,正在运行..."./"$file" # 执行脚本
elseecho "$file 不存在或不可执行"
fi# 判断目录是否存在,不存在则创建
dir="backup"
if [ ! -d "$dir" ];then # !否定-d,目录不存在则成立echo "目录 $dir 不存在,创建中..."mkdir "$dir"
elseecho "目录 $dir 已存在"
fi
if 条件语句实践
实验 1:检测并启动 sshd 服务
实验流程:
- 检查 sshd 服务状态(用命令返回值判断)
- 如果服务未运行,启动服务并提示
- 如果服务已运行,直接提示
实现代码:
#!/bin/bash
# 检查sshd服务状态(&>/dev/null:屏蔽输出,只保留返回值)
systemctl is-active sshd &>/dev/null# $?是上一条命令的返回值:0表示成功(服务运行),非0表示失败(服务未运行)
if [ $? -ne 0 ];then # -ne:不等于(如果返回值非0,说明服务未运行)echo "sshd未运行,正在启动..."systemctl start sshd # 启动服务
elseecho "sshd已运行"
fi
实验 2:通过参数控制 sshd 服务(start/stop/restart)
实验流程:
- 接收用户输入的参数(如 start)
- 根据参数执行对应的操作(启动 / 停止 / 重启)
- 若参数无效,提示正确用法
实现代码:
#!/bin/bash
# 判断参数是否为start/stop/restart
if [ "$1" = "start" ];thensystemctl start sshd # 启动服务
elif [ "$1" = "stop" ];thensystemctl stop sshd # 停止服务
elif [ "$1" = "restart" ];thensystemctl restart sshd # 重启服务
else# 提示正确用法($0表示脚本自身的文件名)echo "用法:$0 start|stop|restart"exit 1 # 非0退出码表示执行出错
fi
实验 3:三个整数从大到小排序
实验流程:
- 定义三个整数变量
- 两两比较,通过交换值让变量从大到小排列
- 输出排序结果
实现代码:
#!/bin/bash
a=10
b=20
c=30# 第一步:确保a >= b(如果a < b,交换a和b的值)
if [ $a -lt $b ];then # -lt:小于num=$b # 临时变量num存b的值b=$a # b换成a的值a=$num # a换成原来的b的值(现在a > b)
fi# 第二步:确保b >= c(如果b < c,交换b和c的值)
if [ $b -lt $c ];thennum=$cc=$bb=$num # 现在b > c
fi# 第三步:再次确保a >= b(经过前两步,可能a < b,需再检查)
if [ $a -lt $b ];thennum=$bb=$aa=$num # 最终a >= b >= c
fiecho "$a>$b>$c" # 输出结果:30>20>10
实验 4:监控系统内存(低于 100M 时发邮件)
实验流程:
- 获取系统当前空闲内存(单位:MB)
- 判断空闲内存是否小于 100M
- 若小于,给 root 用户发报警邮件
- 设置定时任务,每 3 分钟执行一次
实现代码:
#!/bin/bash
# 获取第2行(NR==2)第4列($4)的空闲内存值(free -m以MB显示内存)
FreeMem=$(free -m | awk 'NR==2 { print $4}')# 如果空闲内存小于100M,发邮件报警
if [ $FreeMem -lt 100 ];then# echo内容作为邮件正文,-s指定主题,发送给root@localhostecho "内存不足!当前空闲内存:${FreeMem}M" | mail -s "内存报警" root@localhost
fi
设置定时任务:
# 给脚本添加执行权限
chmod +x monitor_mem.sh# 编辑定时任务(*/3表示每3分钟)
crontab -e
# 添加以下内容(脚本路径替换为实际路径)
*/3 * * * * /home/bq/monitor_mem.sh
if 条件语句企业案例精讲
监控 Web 服务(Apache)和数据库(MySQL)
实验目标: 检测服务是否正常,若异常则提示(或自动启动)。
实验流程:
- 准备 Web(Apache)和数据库(MySQL)环境
- 用命令行测试服务是否正常(端口检测 / 进程检测)
- 编写监控脚本,用 if 判断服务状态并输出结果
1. 环境准备
# 安装Apache(Web服务,默认端口80)
sudo yum install -y httpd
sudo systemctl enable httpd --now # 开机启动并立即启动# 安装MySQL(数据库,默认端口3306,CentOS中常用mariadb替代)
sudo yum install -y mariadb-server
sudo systemctl enable mariadb --now# 关闭防火墙(避免端口被拦截)
sudo systemctl disable firewalld --now
2. 命令行测试服务状态
# 检测MySQL端口(3306)是否监听(ss -lnt:列出监听的TCP端口)
ss -lnt | grep ':3306' | wc -l # 结果为1表示端口正常监听# 检测Apache端口(80)是否监听
ss -lnt | grep ':80' | wc -l # 结果为1表示正常
3. 编写监控脚本
监控 MySQL 的脚本:
#!/bin/bash
# 用ss命令检测3306端口是否被监听(-q:静默模式,只返回成功/失败)
if ss -lnt | grep -q ':3306';thenecho "MySQL运行正常"
elseecho "MySQL未运行!"# 可选:自动启动服务(取消下面一行注释)# sudo systemctl start mariadb
fi
监控 Apache 的脚本:
#!/bin/bash
# 用curl访问本地80端口(--head:只取响应头,-s:静默模式)
if curl -s --head 127.0.0.1:80 | grep -q "HTTP/1.1 200 OK";thenecho "Apache运行正常"
elseecho "Apache未运行!"# 可选:自动启动服务# sudo systemctl start httpd
fi
比较两个整数的大小(带参数校验)
实验目标: 接收用户输入的两个整数,比较大小并输出结果(需先校验参数是否合法)。
实验流程:
- 检查用户输入的参数个数是否为 2
- 检查参数是否为整数(非整数则报错)
- 比较两个整数的大小并输出结果
实现代码:
#!/bin/bash
# 步骤1:检查参数个数($#表示参数总数,-ne 2:不等于2)
if [ $# -ne 2 ];thenecho "用法:$0 数字1 数字2" # 提示正确输入方式exit 1 # 退出并返回错误码
fi# 步骤2:赋值($1是第一个参数,$2是第二个参数)
a=$1
b=$2# 步骤3:检查参数是否为整数(expr计算非整数会报错,返回值非0)
expr $a + 1 &>/dev/null # 用expr检测a是否为整数(+1不影响结果,只测合法性)
RETVAL1=$? # 保存检测结果(0为整数,非0为非整数)
expr $b + 1 &>/dev/null
RETVAL2=$?# 如果a或b不是整数,提示错误
if [ $RETVAL1 -ne 0 -o $RETVAL2 -ne 0 ];then # -o:或者echo "请输入两个整数!"exit 2
fi# 步骤4:比较大小并输出
if [ $a -lt $b ];then # -lt:小于echo "$a < $b"
elif [ $a -eq $b ];then # -eq:等于echo "$a = $b"
elseecho "$a > $b"
fi
判断字符串是否为数字(多种方法)
方法 1:删除所有数字后检查是否为空
原理:如果字符串全是数字,删除数字后会变成空字符串。
# 示例:判断变量string是否为数字
string=1234
# ${string//[0-9]/}:删除string中所有0-9的数字
if [ -z "${string//[0-9]/}" ];then # -z:检查字符串是否为空echo "是数字"
elseecho "不是数字"
fi
方法 2:用正则表达式匹配
原理:^[0-9]+$
表示 “从开头到结尾全是数字”。
string=1234
# [[ ]]支持=~正则匹配
if [[ $string =~ ^[0-9]+$ ]];thenecho "是数字"
elseecho "不是数字"
fi
开发 rsync 服务启动脚本(模拟系统服务)
实验目标: 实现类似系统服务的启动脚本(支持 start/stop/restart/status)。
实验流程:
- 安装 rsync 服务并测试启动 / 停止命令
- 编写脚本,通过参数判断执行对应操作
- 验证脚本功能(启动 / 停止 / 重启 / 查看状态)
1. 环境准备
# 安装rsync(数据同步工具,默认端口873)
sudo yum install -y rsync# 启动rsync服务(--daemon:以守护进程模式运行)
sudo rsync --daemon# 检查端口是否启动(873为rsync默认端口)
ss -lnt | grep ':873' # 有输出表示启动成功# 停止rsync服务(pkill:杀死进程)
sudo pkill rsync
2. 编写启动脚本
#!/bin/bash
# rsync服务控制脚本(支持start/stop/restart/status)# 步骤1:检查参数个数(必须传入1个参数)
if [ $# -ne 1 ];thenecho "用法:$0 [ start | stop | restart | status ]"exit 1
fi# 步骤2:根据参数执行操作
if [ "$1" = "start" ];then# 启动服务sudo rsync --daemonsleep 2 # 等待2秒,确保服务启动完成# 检查是否启动成功(检测873端口)if ss -lnt | grep -q ':873';thenecho "rsync已启动"elseecho "rsync启动失败"fielif [ "$1" = "stop" ];then# 停止服务sudo pkill rsync &>/dev/nullsleep 2# 检查是否停止成功if ! ss -lnt | grep -q ':873';then # !表示否定echo "rsync已停止"elseecho "rsync停止失败"fielif [ "$1" = "status" ];then# 查看状态if ss -lnt | grep -q ':873';thenecho "rsync正在运行"elseecho "rsync未运行"fielif [ "$1" = "restart" ];then# 重启服务(先停止,再启动)sudo pkill rsync &>/dev/nullsleep 1sudo rsync --daemonsleep 1# 检查重启结果if ss -lnt | grep -q ':873';thenecho "rsync已重启"elseecho "rsync重启失败"fielse# 无效参数echo "用法:$0 [ start | stop | restart | status ]"exit 1
fi
3. 验证脚本
# 给脚本添加执行权限
sudo chmod +x /etc/init.d/rsyncd# 测试启动
sudo /etc/init.d/rsyncd start # 输出:rsync已启动# 测试查看状态
sudo /etc/init.d/rsyncd status # 输出:rsync正在运行# 测试停止
sudo /etc/init.d/rsyncd stop # 输出:rsync已停止# 测试重启
sudo /etc/init.d/rsyncd restart # 输出:rsync已重启
如涉及版权问题请联系作者处理!!!