08-循环控制

for if 作业

循环打印1到10,完成任务

- 不打印5
- 不打印4和5
- 不打印偶数
- 不打印奇数

在 Bash 脚本中,循环控制是自动化运维任务的核心。以下是对关键循环控制结构的解释及实用案例:


一、核心循环控制结构

  1. break
    立即终止当前循环,执行循环后的代码
    典型场景:满足条件时提前退出循环

  2. continue
    跳过当前迭代剩余代码,进入下一次循环
    典型场景:过滤不需要处理的情况

  3. while
    条件为真时持续循环
    典型场景:监控类任务

  4. for
    遍历列表/数组执行操作
    典型场景:批量处理文件/服务

  5. exit
    立即终止脚本执行
    典型场景:遇到致命错误时退出


二、运维脚本案例集

案例 1:服务状态监控(break + while)

根据进程pid判断进程是否挂掉

# nginx_pid=$(ps -ef |grep 'nginx: master' | grep -v 'grep' | awk '{print $2}')

#!/bin/bash
# 监控Nginx服务,若连续3次检测失败则告警并停止检测
max_retries=3
retries=0

while true; do
    if  systemctl is-active redis &>/dev/null; then
        echo "[$(date)] redis is running"
        break  # 服务正常则退出监控循环
    else
        ((retries++)) # 重试次数+1  1/3
        echo "[$(date)] redis maybe down! Retry $retries/$max_retries"
        # 重试次数大于等3,程序直接异常退出
        if [ $retries -ge $max_retries ]; then
            echo "ALERT: redis failed to start!" >&2
            exit 1  # 严重故障退出脚本
        fi
        # 5秒重试一次
        sleep 5
    fi
done

案例 2:日志文件清理(continue + for)

# 注意引号区别
双引号包裹变量,禁止二次解析通配符
双引号包裹路径,通配符 * 被抑制扩展,Bash 将其视为字面字符串
命令1流程:
for循环输入 → "/var/log/*.log"(字面字符串)
           ↓
echo "$log" → 直接输出字符串

命令2流程:
for循环输入 → "/var/log/*.log"(字面字符串)
           ↓
echo $log → 替换为 /var/log/*.log → 通配符展开 → 输出真实文件列表

案例

#!/bin/bash
# 删除 /var/log 下7天前的.log文件,跳过正在使用的文件
log_dir="/var/log"
days=7

for logfile in "$log_dir"/*.log; do
    if lsof "$logfile" &>/dev/null; then
        echo "Skipping active file: $logfile"
        continue  # 跳过被占用的文件
    fi

    if find "$logfile" -mtime +$days -exec rm -vf {} \; &>/dev/null; then
        echo "Deleted: $logfile"
    fi
done

案例 3:批量用户创建(break on error)

#!/bin/bash
# 从userlist.txt批量创建用户,遇到格式错误立即终止
userfile="userlist.txt"

for line in $(cat $userfile); do
    if [[ ! $line =~ ^[a-z0-9_]+$ ]]; then
        echo "ERROR: Invalid username '$line'"
        break  # 发现非法用户名立即停止处理
    fi

    if id "$line" &>/dev/null; then
        echo "User $line already exists"
        continue  # 跳过已存在用户
    fi

    useradd -m "$line" && echo "Created user: $line"
done

案例 4:磁盘空间监控(while + exit)

#!/bin/bash
# 检查根分区使用率,超过90%立即告警退出
threshold=90

while :; do
    usage=$(df -h / | awk 'NR==2 {print $5}' | tr -d '%')

    if [ $usage -ge $threshold ]; then
        echo "CRITICAL: Disk usage $usage%! Sending alert..."
        send_alert "Disk full"  # 假设存在的告警函数
        exit 2  # 立即退出并返回状态码2
    else
        echo "Current usage: $usage% - OK"
    fi

    sleep 300  # 每5分钟检测一次
done

案例 5:智能重试机制(continue + 嵌套循环)

#!/bin/bash
# 批量下载URL列表,失败后最多重试3次
urls=(
    "https://example.com/file1.tar.gz"
    "https://example.com/file2.iso"
    "https://broken-url.com/errorfile"
)

for url in "${urls[@]}"; do
    filename=$(basename "$url")
    retry=0

    while [ $retry -lt 3 ]; do
        if wget -q --timeout=20 "$url"; then
            echo "Downloaded: $filename"
            break  # 成功则跳出重试循环
        else
            ((retry++))
            echo "Failed $retry/3: $filename"

            if [ $retry -eq 3 ]; then
                echo "Permanent failure: $url" >> failed_downloads.log
                continue 2  # 跳过当前文件,继续下一个URL
            fi

            sleep $((retry*5))  # 指数退避:5,10,15秒
        fi
    done
done

三、关键技巧总结

  1. break N:跳出N层嵌套循环
  2. continue N:跳过N层循环的当前迭代
  3. 循环陷阱处理:结合trap实现中断处理
  4. 性能优化:避免在循环内启动不必要的子进程
  5. 超时控制:结合timeout命令防止死循环

这些模式可灵活组合,应对服务监控、批量操作、故障处理等典型运维场景。实际使用时注意添加日志记录和错误处理机制。

1.应用场景

1. 循环我们已经从for while两大循环中感受到其方便,但很多时候我们希望中断这个循环,或者跳过某次循环
2. 例如网站的登录验证,输入允许错误三次,再就终止循环,不让登录了。

2.break

语法

break用于终止当前循环,如某一个for循环、某一个while循环

3.终止for循环

#!/bin/bash

# 到11的时候结束循环,注意,是包括11,还是不包括11?

for i in {1..20}
do
    echo "$i"
    if [ $i == 11  ];then
             break
    fi
  echo "这里代码什么时候会执行呢?"
done

echo "程序结束~"

4.continue

1. 跳过本次循环,忽略本次循环的代码执行,直接进入下一次循环,直到结束。
2. 循环结束后,循环外部的代码依然继续。

打印1~20、跳过6和16

#!/bin/bash

# 到11的时候结束循环
for i in {1..20}
do
    if [ $i == 6 -o $i == 16 ];then
             continue
    fi
    echo "$i"
  echo "这里代码什么时候会执行呢?"
done

echo "程序结束~"

5.exit命令

exit用于直接退出当前进程,脚本直接结束了。

打印1~20,到13的时候,程序直接结束。

#!/bin/bash

# 到11的时候结束循环
for i in {1..20}
do
    if [ $i == 13 ];then
             exit
    fi
    echo "$i"
  echo "这里代码什么时候会执行呢?"
done

echo "程序结束~这一次能看到我吗?"
Copyright © www.yuchaoit.cn 2025 all right reserved,powered by Gitbook作者:于超 2025-01-30 18:30:34

results matching ""

    No results matching ""