如何在 shell 脚本中添加循环执行步骤?

文章导读
在 Shell 脚本中实现循环执行,核心在于根据“是否已知执行次数”选择结构:次数固定或遍历集合用 for,条件驱动用 while。工程实践中,必须优先保证循环能正常退出,并做好变量引用保护。
📋 目录
  1. A 基础语法与安全规范
  2. B 场景实战:批量处理文件
  3. C 场景实战:带重试机制的服务等待
  4. D 调试与验证方法
  5. E 常见风险与规避
  6. F 参考来源
A A

在 Shell 脚本中实现循环执行,核心在于根据“是否已知执行次数”选择结构:次数固定或遍历集合用 for,条件驱动用 while。工程实践中,必须优先保证循环能正常退出,并做好变量引用保护。

核心建议:选对循环结构能避免死循环和逻辑遗漏,优先保证脚本能正常退出

  • 适合:批量处理文件或用固定次数重试场景
  • 先看:循环终止条件是否一定会被满足
  • 建议:变量引用加上双引号防止 word splitting
  • 规范:脚本开头建议加入 set -euo pipefail 增强健壮性

基础语法与安全规范

Shell 脚本是顺序执行的,循环结构允许你重复运行一段代码直到满足特定条件。for 适合遍历已知集合,while 适合等待某个状态变化。如果条件写反或变量不更新,脚本会卡住不动,这就是常见的死循环。

# for 循环:已知次数或列表
for i in 1 2 3; do
  echo "第 $i 次"
done

# while 循环:未知次数,靠条件退出
# 注意:变量 count 必须加引号,防止为空时报语法错误
count=0
while [ "$count" -lt 5 ]; do
  echo "计数 $count"
  count=$((count + 1))
done

场景实战:批量处理文件

遍历目录文件是常见需求。务必给变量加上双引号,防止文件名包含空格时脚本断裂。

如何在 shell 脚本中添加循环执行步骤?
#!/bin/bash
# 遍历当前目录下所有 .log 文件
for file in *.log; do
  # 检查文件是否存在,防止无匹配时字面量执行
  [ -e "$file" ] || continue
  
  echo "处理文件:$file"
  # 模拟处理逻辑
  mv "$file" "$file".bak
done

场景实战:带重试机制的服务等待

在等待服务启动或 API 响应时,while 循环需配合最大重试次数和 sleep 延迟,避免无限卡死或请求过快。

#!/bin/bash
max_retry=5
count=0

while [ "$count" -lt "$max_retry" ]; do
  # 模拟检查服务状态,替换为实际命令如 curl -s http://localhost:8080/health
  if command -v curl &> /dev/null && curl -s http://localhost:8080/health | grep -q "ok"; then
    echo "服务已就绪"
    exit 0
  fi
  
  count=$((count + 1))
  echo "重试第 $count 次..."
  sleep 2
done

echo "错误:服务启动超时" >&2
exit 1

调试与验证方法

运行脚本后不仅要看输出,还要检查退出码和关键状态。使用调试模式可以定位循环变量未更新等问题。

# 1. 语法检查
bash -n script.sh

# 2. 开启调试模式运行,查看每一步执行细节
bash -x script.sh

# 3. 验证退出状态
./script.sh
echo "退出码:$?"

验证循环是否生效,可在循环内写入日志文件,循环结束后检查日志行数是否符合预期。

常见风险与规避

1. 变量未 quoting:文件名为空格时循环会断裂,务必写 "$var"。

如何在 shell 脚本中添加循环执行步骤?

2. 条件判断空格:[ "$a" -eq "$b" ] 中括号内侧必须有空格,否则报错。

3. 静默失败:建议在脚本开头添加 set -e,遇到错误立即退出,避免循环继续执行错误逻辑。

4. 后台进程残留:循环里启动的背景任务可能在脚本退出后继续运行,需做好清理。

参考来源

  • GNU Bash Manual, Bash Features, Loop Constructs
  • POSIX Shell Command Language, Compound Commands