Shell脚本-while循环应用案例
一、前言
在 Linux Shell 脚本编程中,while
循环是一种非常强大且常用的控制结构。它可以根据某个条件的真假,重复执行一段代码,直到条件不再满足为止。
相比于 for
循环,while
更适合处理不确定循环次数或依赖运行时状态判断的场景,例如:读取文件、监控进程、用户交互、定时任务等。
本文将通过 10 个典型的应用案例,带你深入理解 while
循环的实际用途,并掌握其在 Shell 脚本中的最佳实践。
二、while 循环语法回顾
while [ 条件判断 ]
do# 执行语句
done
或者使用双括号(适用于数值比较):
while (( 条件 ))
do# 执行语句
done
⚠️ 注意:条件为“真”时继续循环,为“假”时退出。
三、实战应用案例
✅ 案例1:简单计数器
打印从 1 到 5 的数字:
#!/bin/bash
i=1
while [ $i -le 5 ]
doecho "当前数字: $i"i=$((i + 1))
done
📌 说明:使用 $((...))
进行算术运算。
✅ 案例2:持续监控系统负载
每隔 3 秒检查一次系统负载,并输出:
#!/bin/bash
echo "开始监控系统负载,按 Ctrl+C 停止..."while true
doload=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}')echo "[$(date +%H:%M:%S)] 当前负载: $load"sleep 3
done
📌 说明:
true
表示无限循环。- 使用
sleep
控制轮询间隔。 awk
提取负载信息。
✅ 案例3:读取文件每一行(推荐方式)
逐行读取文件内容并处理:
#!/bin/bash
filename="data.txt"while IFS= read -r line
doecho "处理行: $line"
done < "$filename"
📌 说明:
IFS=
防止首尾空格被删除。-r
防止反斜杠转义。< "$filename"
将文件重定向给while
。
✅ 这是读取文件最安全、最推荐的方式!
✅ 案例4:用户交互式菜单
创建一个简单的交互菜单:
#!/bin/bash
choice=""while [ "$choice" != "3" ]
doecho "=== 主菜单 ==="echo "1. 查看当前目录"echo "2. 查看系统时间"echo "3. 退出"read -p "请选择: " choicecase $choice in1) ls -l ;;2) date ;;3) echo "再见!" ;;*) echo "无效选择,请重试" ;;esac
done
📌 说明:常用于自动化脚本中的菜单系统。
✅ 案例5:等待某个服务启动
监控某个端口是否开放(如 Web 服务):
#!/bin/bash
host="localhost"
port=80
timeout=30
elapsed=0while ! nc -z $host $port 2>/dev/null
doecho "等待服务启动... ($elapsed 秒)"sleep 1elapsed=$((elapsed + 1))if [ $elapsed -ge $timeout ]; thenecho "超时:服务未在 $timeout 秒内启动"exit 1fi
doneecho "服务已在 $host:$port 启动"
📌 说明:
- 使用
nc -z
检测端口。 - 设置超时机制避免无限等待。
✅ 案例6:处理管道数据(while + pipe)
结合管道处理命令输出:
ps aux | grep -v grep | awk '{print $2}' | while read pid
doecho "正在处理进程 PID: $pid"# 可以在这里做更多操作,比如 kill、日志记录等
done
⚠️ 注意:这种写法中 while
在子 shell 中运行,内部变量修改不会影响外部环境。若需保留变量,应避免使用管道,改用重定向。
✅ 案例7:模拟 do-while 循环
Shell 没有原生 do-while
,但可以用 while true
模拟:
#!/bin/bash
while true
doread -p "输入一个正数: " numif [ $num -gt 0 ]; thenecho "你输入的是: $num"breakelseecho "请输入大于0的数!"fi
done
📌 说明:使用 break
跳出循环,实现“先执行,后判断”的效果。
✅ 案例8:批量重命名文件
遍历目录下所有 .log
文件并重命名:
#!/bin/bash
ls *.log 2>/dev/null | while read file
doif [ -f "$file" ]; thennew_name="${file%.log}_backup.log"mv "$file" "$new_name"echo "已重命名: $file -> $new_name"fi
done
📌 说明:${file%.log}
表示去除文件名后缀。
✅ 案例9:定时备份并压缩日志
每隔1分钟检查日志目录,自动打包旧日志:
#!/bin/bash
log_dir="/var/log/myapp"
backup_dir="/backup/logs"while true
dofind "$log_dir" -name "*.log" -mtime +1 | while read logdotar -czf "${backup_dir}/$(basename $log).tar.gz" "$log"rm "$log"echo "已备份并删除: $log"donesleep 60 # 每分钟检查一次
done
📌 说明:适用于日志轮转、自动化运维等场景。
✅ 案例10:防止脚本重复运行(锁机制)
使用 while
实现简单的进程锁:
#!/bin/bash
lockfile="/tmp/script.lock"while [ -f "$lockfile" ]
doecho "检测到锁文件,脚本可能已在运行,等待中..."sleep 5
done# 创建锁文件
touch "$lockfile"
echo "脚本开始执行..."# --- 正式业务逻辑 ---
sleep 10
echo "任务完成"# 删除锁文件
rm -f "$lockfile"
📌 说明:防止多个实例同时运行,避免资源冲突。
四、常见问题与最佳实践
问题 | 解决方案 |
---|---|
变量在循环中无法保留 | 避免使用管道,改用 < file 重定向 |
无限循环卡死 | 设置超时机制或使用 break 条件 |
中文乱码 | 设置 LANG=en_US.UTF-8 或使用 iconv |
安全性问题 | 对变量使用引号,如 "$var" |
脚本可读性差 | 添加注释、使用函数封装逻辑 |
五、总结
应用场景 | 推荐写法 |
---|---|
计数循环 | [ $i -le 10 ] |
文件读取 | while read; do ... done < file |
服务监控 | while true; do ... sleep 3; done |
用户交互 | while [ "$input" != "exit" ] |
数据处理 | 结合 awk/sed/grep 流式处理 |
while
循环是 Shell 脚本中实现自动化、监控、交互、批处理的核心工具。掌握它的各种用法,能极大提升你的运维效率和脚本能力。
六、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!