Shell 无限循环和指定次数循环

《Shell 无限循环和指定次数循环》深度学习版 🧠

🎉 欢迎来到 Shell 编程中非常实用的一章 —— 无限循环与指定次数循环。它们是自动化任务、监控系统状态、实现定时操作等场景的必备技能。掌握它,你就能写出真正“永不停歇”或“精准执行”的脚本!


🎯 学习目标

  • 理解无限循环与有限次循环的基本原理
  • 掌握 while truefor (( ))seqeval 等多种方式实现循环
  • 能在实际脚本中灵活使用监控、定时检查、批量处理等场景
  • 学会结合 sleepbreakcontinue 控制循环流程
  • 避免常见陷阱和语法错误,写出健壮可靠的 Shell 循环语句

⭐ 核心重点(知识点速览)

类型 内容 描述
无限循环 while true; do ... done 条件永远为真时持续运行
指定次数循环 for ((i=1; i<=N; i++)); do ... done 执行固定次数
命令生成序列 seq, eval, {1..n} 快速生成数字范围
实时监控 tail -f, ping, ps 结合 while 实现实时输出
定时任务 sleep N 控制循环间隔时间
控制结构 break, continue 控制循环流程
不同 shell 差异 bash vs dash 注意兼容性问题

📖 详细讲解


一、无限循环(Infinite Loop)🔥

适用于需要持续运行的任务,如守护进程、日志监控、定时检查等。

✅ 示例:每秒显示系统负载

while true
do
    load=$(uptime | awk '{print $10}')
    echo "[$(date +"%T")] 当前系统负载:$load"
    sleep 1
done

💡 这是最基本的“永动”模式,常用于后台服务监听。


二、退出无限循环的方式 🛑

虽然叫“无限”,但大多数情况下我们都需要一种方式来退出循环。

✅ 示例:按 Ctrl+C 终止 或 使用 break

while true
do
    read -p "请输入 quit 退出:" input
    if [ "$input" = "quit" ]; then
        echo "👋 正在退出..."
        break
    else
        echo "🔁 请再试一次"
    fi
done

三、使用 until 实现“直到满足条件才停止”的循环 🕒

untilwhile 的反向版本,当条件不成立时继续循环,成立时退出。

✅ 示例:等待文件出现后退出

target_file="/tmp/ready.txt"

echo "⏳ 正在等待文件 $target_file 出现..."

until [ -f "$target_file" ]
do
    sleep 1
done

echo "✅ 文件已找到!继续执行后续操作..."

四、指定次数循环 🔁

适用于只需要执行固定次数的任务,如模拟进度条、定时提醒、测试等。

✅ 方法 1:C 风格 for 循环(Bash 特有)

for ((i=1; i<=5; i++))
do
    echo "第 $i 次循环"
done

✅ 方法 2:使用 seq 命令(POSIX 兼容)

for i in $(seq 1 5)
do
    echo "第 $i 次循环"
done

✅ 方法 3:使用花括号展开(Bash 特有)

for i in {1..5}
do
    echo "第 $i 次循环"
done

✅ 方法 4:使用 eval 动态生成(高级技巧)

n=5
for i in $(eval echo "{1..$n}")
do
    echo "第 $i 次循环"
done

五、实战案例分析 🧪

🎯 场景一:带进度条的安装模拟器

for i in {1..10}
do
    percent=$((i * 10))
    bar=$(printf '=%.0s' $(seq 1 $i))
    printf "\r[%-10s] %d%% " "$bar" "$percent"
    sleep 0.5
done
printf "\n✅ 安装完成\n"

💡 输出效果:

[==========] 100% ✅ 安装完成

🎯 场景二:定时清理临时文件夹 🗑️

log_file="/var/log/cleaner.log"
timestamp=$(date "+%Y-%m-%d %T")

echo "[$timestamp] 开始定时清理 /tmp 下的 .tmp 文件..." >> "$log_file"

while true
do
    count=0
    for file in /tmp/*.tmp
    do
        rm -f "$file"
        count=$((count + 1))
    done

    echo "[$(date "+%T")] 共删除 $count 个临时文件" >> "$log_file"
    sleep 60   # 每分钟清理一次
done

🎯 场景三:自动重启宕机的服务 🔄

service_name="nginx"

while true
do
    if systemctl is-active --quiet "$service_name"; then
        echo "[$(date "+%T")] $service_name 正常运行"
    else
        echo "🔴 $service_name 已宕机,正在尝试重启..."
        systemctl restart "$service_name"
        if [ $? -eq 0 ]; then
            echo "✅ $service_name 重启成功"
        else
            echo "❌ $service_name 重启失败,请人工介入"
        fi
    fi
    sleep 10
done

🎯 场景四:用户登录验证限制重试次数 🔐

max_attempts=3
valid_user="admin"
valid_pass="password"

for attempt in $(seq 1 $max_attempts)
do
    read -p "请输入用户名:" username
    read -sp "请输入密码:" password

    if [ "$username" = "$valid_user" ] && [ "$password" = "$valid_pass" ]; then
        echo -e "\n✅ 登录成功!欢迎 $username"
        exit 0
    else
        remaining=$((max_attempts - attempt))
        echo -e "\n❌ 登录失败,剩余尝试次数:$remaining"
    fi
done

echo "🚫 登录失败次数过多,程序退出"
exit 1

六、不同系统的差异与注意事项 ⚠️

项目 Bash Dash (Ubuntu 默认) zsh
支持 (( ))
支持 seq
支持 {1..n}
推荐脚本开头 #!/bin/bash #!/bin/sh #!/bin/zsh
注意子 shell 变量作用域

📝 小贴士:

  • 在 Ubuntu 中默认 /bin/shdash,不支持某些高级特性,建议脚本开头写成 #!/bin/bash
  • 使用双引号包裹变量,防止路径含空格出错。
  • 多层循环建议用缩进保持可读性。

⚠️ 常见陷阱 & 解决方案

问题 原因 解决方法
循环未执行 条件一开始就不成立 加入调试输出或初始值设置
循环无法退出 条件永远为真 使用 break 或合理修改条件
数字范围错误 变量未定义或非整数 使用 [[ $var =~ ^[0-9]+$ ]] 判断
性能问题 高频率调用外部命令 合理调整间隔时间或合并处理逻辑
循环变量未更新 忘记递增计数器 添加 i=$((i+1))

🧠 总结与小贴士

技巧 说明
while true 是 Shell 的“永动机” 让脚本能持续响应变化
for (( )) 更适合数值范围控制 Bash 特有功能
seq{1..n} 是批量处理利器 提升灵活性
始终对变量加双引号 防止空格或未定义变量出错
使用 sleep 控制节奏 避免 CPU 占用过高
结合 break 实现优雅退出 提升脚本健壮性
注意子 shell 变量作用域 特别是在管道中使用时

📚 推荐练习题(可选)

  1. 编写一个脚本,每隔 5 秒检查一次磁盘空间,如果超过 90%,则发送邮件通知。
  2. 写一个脚本,实时监控 /var/log/auth.log,发现 SSH 登录失败超过 5 次就报警。
  3. 实现一个脚本,不断读取用户输入的数字,并累加求和,输入 q 时退出。
  4. 编写一个脚本,模拟进度条动画(使用 \rsleep)。
  5. 创建一个备份脚本,当检测到指定目录中有新文件时,自动打包上传至远程服务器。

🎯 下一章预告:《Shell 函数 Function》

你已经掌握了如何让脚本“循环执行”,下一步我们将学习如何将常用代码块封装成函数,提高复用性和可维护性 —— Shell 函数,让你的脚本更模块化、更专业!

需要我继续为你生成下一章内容吗?😊

posted @ 2025-06-18 22:44  红尘过客2022  阅读(102)  评论(0)    收藏  举报