楼主: liushuang14
37 0

[作业] RHCSE--SHELL04--流程判断 [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

学前班

40%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
20 点
帖子
1
精华
0
在线时间
0 小时
注册时间
2018-12-2
最后登录
2018-12-2

楼主
liushuang14 发表于 2025-12-1 14:56:20 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

Shell 流程控制详解

在 Shell 脚本编程中,流程控制是实现逻辑判断与重复操作的关键部分。主要涵盖条件判断、多分支选择、循环结构以及循环控制语句等核心内容。以下将系统性地介绍这些控制结构的用法和实际应用场景。

一、条件判断(if 语句)

1. 基本 if 语法

# 单分支
if [ condition ]; then
    commands
fi

# 双分支
if [ condition ]; then
    commands1
else
    commands2
fi

# 多分支
if [ condition1 ]; then
    commands1
elif [ condition2 ]; then
    commands2
elif [ condition3 ]; then
    commands3
else
    commands4
fi

2. 示例:使用 if 进行条件判断

#!/bin/bash

# 检查文件是否存在
file="/etc/passwd"

if [ -f "$file" ]; then
    echo "文件 $file 存在"
    echo "文件大小: $(wc -c < "$file") 字节"
else
    echo "文件 $file 不存在"
fi

# 检查数字范围
read -p "请输入分数 (0-100): " score

if [ "$score" -ge 90 ] && [ "$score" -le 100 ]; then
    echo "优秀"
elif [ "$score" -ge 80 ] && [ "$score" -lt 90 ]; then
    echo "良好"
elif [ "$score" -ge 70 ] && [ "$score" -lt 80 ]; then
    echo "中等"
elif [ "$score" -ge 60 ] && [ "$score" -lt 70 ]; then
    echo "及格"
elif [ "$score" -ge 0 ] && [ "$score" -lt 60 ]; then
    echo "不及格"
else
    echo "无效分数"
fi

# 检查字符串
read -p "请输入yes或no: " answer

if [ "$answer" = "yes" ] || [ "$answer" = "y" ]; then
    echo "你选择了是"
elif [ "$answer" = "no" ] || [ "$answer" = "n" ]; then
    echo "你选择了否"
else
    echo "无效输入"
fi

3. 利用命令返回值进行判断
Shell 中很多命令执行后会返回退出状态码(exit status),通常0表示成功,非0表示失败。该特性常用于 if 条件中进行流程控制。

#!/bin/bash

# 检查命令是否执行成功
if grep -q "root" /etc/passwd; then
    echo "系统中存在root用户"
fi

# 检查进程是否运行
if ps aux | grep -q "[s]shd"; then
    echo "SSH服务正在运行"
else
    echo "SSH服务未运行"
fi

# 复杂的条件组合
if [ -d "/var/log" ] && [ -w "/var/log" ] && 
   ! [ -f "/var/log/system.log" ]; then
    echo "日志目录可写且系统日志文件不存在"
fi

练习1:编写一个名为 choice2.sh 的脚本,定时检测系统剩余内存是否低于 2000M。若满足条件,则触发告警,并通过邮件通知管理员。要求每分钟执行一次检查。

#扩展:邮箱
[root@localhost s1]# cat e.sh
#!/bin/bash
num=`free -m | awk '/Mem/ {print $4}'`
if [ $num -gt 2000 ] ;then
echo " warnging:mem is too less `date`" | mail -s "Men_warnning"
xxxxxxxxxxx@qq.com
fi
[root@localhost s1]# vim /etc/s-nail.rc
文件末尾添加:
set v15-compat
set smtp-auth=login
set from="昵称<qq号@qq.com>"
set mta=smtps://qq号:qq邮箱授权码@smtp.qq.com:465

set v15-compat
set smtp-auth=login
set from="<xxxxxxxxxxxxxxxxx@qq.com>"
set mta=smtps://xxxxxxxxxxxxx:rnwfflmbakcbgjhh@smtp.qq.com:465

rnwfflmbakcbgjhh

练习2:创建脚本 temp5.sh,列出当前系统所有用户,提示用户选择其中一个。根据所选用户名判断其账户类型:属于 root 用户、系统账户或普通用户。

[root@server ~]# vim temp5.sh
#!/bin/bash
cat /etc/passwd | cut -d ":" -f1 | sort -u
read -p "请输入一个账户名:" us
us_num=$(id -u $us)
if (($us_num==0))
then
	echo "此用户为管理员账户"
else
if (($us_num>=1 && $us_num<=999))
then
	echo "此账户为系统账户"
else
	echo "普通账户"
fi
fi

二、case 多分支选择结构

1. case 语句基本语法

当需要对单一变量进行多种模式匹配时,case 比多个 elif 更清晰高效。

case 变量 in
模式1)
    commands1
    ;;
模式2)
    commands2
    ;;
模式3|模式4)  # 多个模式用 | 分隔
    commands3
    ;;
*)
    default_commands  # 默认情况
    ;;
esac

2. 实际应用示例

#!/bin/bash

# 简单的选项处理
echo "请选择操作:"
echo "1) 显示日期"
echo "2) 显示用户"
echo "3) 显示磁盘使用"
echo "4) 退出"

read -p "请输入选择 (1-4): " choice

case $choice in
    1)
        echo "当前日期: $(date)"
        ;;
    2)
        echo "当前用户: $(whoami)"
        echo "所有用户: $(who)"
        ;;
    3)
        echo "磁盘使用情况:"
        df -h
        ;;
    4)
        echo "再见!"
        exit 0
        ;;
    *)
        echo "无效选择!"
        exit 1
        ;;
esac
# 模式匹配示例
read -p "请输入文件名: " filename

case $filename in
    *.txt)
        echo "这是文本文件"
        ;;
    *.jpg|*.png|*.gif)
        echo "这是图片文件"
        ;;
    *.tar.gz|*.tgz)
        echo "这是压缩文件"
        ;;
    /etc/*)  # 绝对路径匹配
        echo "这是系统配置文件"
        ;;
    [a-z]*)  # 以小写字母开头
        echo "文件名以小写字母开头"
        ;;
    *)
        echo "未知文件类型"
        ;;
esac

# 系统服务管理脚本
case "$1" in
    start)
        echo "启动服务..."
        # 启动命令
        ;;
    stop)
        echo "停止服务..."
        # 停止命令
        ;;
    restart)
        echo "重启服务..."
        # 重启命令
        ;;
    status)
        echo "服务状态..."
        # 状态检查
        ;;
    *)
        echo "用法: $0 {start|stop|restart|status}"
        exit 1
        ;;
esac

三、循环控制机制

1. for 循环

适用于已知迭代次数或明确遍历对象的情况。

基本 for 循环格式

#!/bin/bash

# 遍历列表
for fruit in apple banana orange grape; do
    echo "水果: $fruit"
done

# 遍历文件
for file in *.txt; do
    if [ -f "$file" ]; then
        echo "处理文件: $file"
        wc -l "$file"
    fi
done

# 数字范围循环
for i in {1..5}; do
    echo "数字: $i"
done

# 带步长的数字范围
for i in {1..10..2}; do
    echo "奇数: $i"
done

# 遍历命令输出
for user in $(cut -d: -f1 /etc/passwd | head -5); do
    echo "系统用户: $user"
done
#注意:for的列表会识别空格和换行符作为参数的分隔符

C 风格 for 循环
类似 C 语言的三段式写法,适合数值计数场景。

#!/bin/bash

# 类似C语言的for循环
for ((i=1; i<=5; i++)); do
    echo "循环次数: $i"
done

# 复杂的循环控制
for ((i=0, j=10; i<j; i++, j--)); do
    echo "i=$i, j=$j"
done

# 无限循环(需要break退出)
for ((;;)); do
    read -p "输入quit退出: " input
    if [ "$input" = "quit" ]; then
        break
    fi
    echo "你输入了: $input"
done

练习:编写一个 Shell 脚本完成以下任务:
- 批量检测五个指定服务器的网络连通性,IP 地址分别为:192.168.1.10、192.168.1.11、192.168.1.12、10.0.0.100、10.0.0.101;
- 使用 ping 命令测试连接,仅发送 1 个数据包,超时设为 1 秒,且不显示原始输出信息。

#!/bin/bash
# 批量检查服务器是否在线

# 服务器IP列表
SERVERS=("192.168.1.10" "192.168.1.11" "192.168.1.12" "10.0.0.100" "10.0.0.101")

echo "开始服务器连通性检查..."
echo "=========================="

for server in "${SERVERS[@]}"; do
    # 使用ping检查连通性,发送1个包,超时1秒
    if ping -c 1 -W 1 "$server" &> /dev/null; then
        echo " $server - 在线"
    else
        echo " $server - 离线"
    fi
done

echo "检查完成!"

2. while 循环
当某个条件为真时持续执行循环体,常用于未知循环次数但依赖条件判断的场景。

#!/bin/bash

# 计数器循环
count=1
while [ $count -le 5 ]; do
    echo "计数: $count"
    ((count++))
done

# 读取文件行
echo "=== 读取文件内容 ==="
while read -r line; do
    echo "行内容: $line"
done < /etc/passwd

# 监控循环(无限循环)
while true; do
    clear
    echo "=== 系统监控 ==="
    echo "时间: $(date)"
    echo "负载: $(uptime)"
    echo "内存: $(free -h | grep Mem | awk '{print $3 "/" $2}')"
    echo "按 Ctrl+C 退出"
    sleep 5
done

# 条件判断循环
number=0
while [ $number -lt 100 ]; do
    if [ $((number % 2)) -eq 0 ]; then
        echo "偶数: $number"
    fi
    ((number++))
done

练习:读取文件 iplist.txt 中的每一行 IP 地址,逐一测试其可达性。只输出能够连通的地址,不可达的则丢弃输出(重定向至 /dev/null)。

#!/bin/bash
# 测试IP连通性脚本

# 检查iplist.txt文件是否存在
if [ ! -f "iplist.txt" ]; then
    echo "错误:iplist.txt文件不存在"
    exit 1
fi

# 遍历文件中的每个IP地址
while read -r ip; do
    # 跳过空行和注释行
    [[ -z "$ip" || "$ip" =~ ^# ]] && continue
    
    # 测试IP连通性,成功则输出,失败重定向到/dev/null
    if ping -c 1 -W 1 "$ip" &> /dev/null; then
        echo "可达: $ip"
    fi
done < "iplist.txt"

3. until 循环
与 while 相反,until 在条件为“假”时继续执行循环,直到条件变为“真”为止。

#!/bin/bash

# until循环(条件为假时执行)
count=1
until [ $count -gt 5 ]; do
    echo "计数: $count"
    ((count++))
done

# 等待服务启动
echo "等待MySQL服务启动..."
until systemctl is-active mysql > /dev/null 2>&1; do
    echo "服务未就绪,等待5秒..."
    sleep 5
done
echo "MySQL服务已启动!"

# 等待文件创建
timeout=60
counter=0
until [ -f "/var/run/service.pid" ]; do
    ((counter++))
    if [ $counter -ge $timeout ]; then
        echo "超时:PID文件未创建"
        exit 1
    fi
    sleep 1
done
echo "PID文件已创建"

四、循环控制语句

在复杂循环逻辑中,可通过特定关键字调整流程走向。

1. break 与 continue 的作用

  • break:立即终止当前循环,跳出整个循环结构。
  • continue:跳过本次循环剩余代码,进入下一次循环迭代。
#!/bin/bash

# break 示例
echo "=== break 示例 ==="
for i in {1..10}; do
    if [ $i -eq 6 ]; then
        echo "遇到6,退出循环"
        break
    fi
    echo "当前数字: $i"
done

# continue 示例
echo "=== continue 示例 ==="
for i in {1..10}; do
    if [ $((i % 2)) -eq 0 ]; then
        continue  # 跳过偶数
    fi
    echo "奇数: $i"
done

# 多层循环中的break
for i in {1..3}; do
    echo "外层循环: $i"
    for j in {1..3}; do
        if [ $j -eq 2 ]; then
            echo "内层遇到2,跳出内层循环"
            break
        fi
        echo "内层循环: $j"
    done
done

# 跳出多层循环
for i in {1..3}; do
    echo "外层循环: $i"
    for j in {1..3}; do
        if [ $i -eq 2 ] && [ $j -eq 2 ]; then
            echo "遇到(2,2),跳出所有循环"
            break 2
        fi
        echo "内层循环: ($i, $j)"
    done
done

2. 多层循环中的层级控制
使用 break ncontinue n 可以从嵌套循环中跳出第 n 层循环,提升控制精度。

#!/bin/bash

# break n:跳出n层循环
for i in {1..3}; do
    for j in {1..3}; do
        for k in {1..3}; do
            if [ $k -eq 2 ]; then
                echo "跳出1层循环"
                break 1  # 只跳出最内层循环
            fi
            echo "循环: i=$i, j=$j, k=$k"
        done
    done
done

echo "---"

for i in {1..3}; do
    for j in {1..3}; do
        for k in {1..3}; do
            if [ $k -eq 2 ]; then
                echo "跳出2层循环"
                break 2  # 跳出两层循环
            fi
            echo "循环: i=$i, j=$j, k=$k"
        done
    done
done

五、select 菜单式循环

select 提供一种便捷的交互式菜单机制,常用于脚本中让用户从列表中选择选项。

#!/bin/bash

# 简单的选择菜单
PS3="请选择操作 (1-5): "
options=("显示日期" "显示用户" "显示磁盘" "显示内存" "退出")

select opt in "${options[@]}"; do
    case $REPLY in
        1)
            echo "当前日期: $(date)"
            ;;
        2)
            echo "当前用户: $(whoami)"
            ;;
        3)
            df -h
            ;;
        4)
            free -h
            ;;
        5)
            echo "再见!"
            break
            ;;
        *)
            echo "无效选择!"
            ;;
    esac
done

用户输入的选择结果默认存储在内置变量 REPLY 中。同时,可以通过设置环境变量 PS3 来自定义提示信息的显示内容。

while true; do
   select choice in option1 option2 option3 option4 quit
   do
       case $choice in
           option1)
               # 执行相关命令
               break
               ;;
           # 其他选项
           quit)
               break 2 # 跳出两层循环
               ;;
           *)
               echo "Invalid selection"
               exit
               ;;
       esac
   done
done

总结:Shell 流程控制核心要点

1. 条件判断结构

  • if-elif-else:处理多个互斥条件分支。
  • case:基于模式匹配实现高效的多路分支选择。
  • test 命令或 [ ]:用于比较数值、字符串及文件状态等条件测试。

2. 循环控制类型

  • for:适用于已知循环次数或遍历集合的场景。
  • while:当条件为真时持续执行,适合动态判断。
  • until:与 while 相反,条件为假时执行循环。
  • select:构建简单交互式菜单,提升用户体验。

3. 循环控制语句

  • break:退出当前循环。
  • continue:跳过当前轮次,继续下一轮循环。
  • break n:支持从多层嵌套循环中跳出指定层数。

4. 编码建议与最佳实践

  • 始终对变量使用双引号包裹,防止因空格导致解析错误。
  • 推荐使用 [[ ]] 替代传统的 [ ],以获得更强大且安全的条件判断能力。
  • 在函数内部声明变量时,使用 local 关键字定义局部变量,避免污染全局命名空间。
[[ ]]
[ ]
local
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:Shell Shel SHE condition localhost

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
jg-xs1
拉您进交流群
GMT+8, 2025-12-5 20:24