当前位置: 首页 > backend >正文

14.Shell脚本修炼手册--玩转循环结构(While 与 Until 的应用技巧与案例)

while 循环和 until 循环的应用实践

文章目录

    • while 循环和 until 循环的应用实践
      • 当型和直到型循环:两种 "重复" 的逻辑
        • while 循环:满足条件就继续
        • until 循环:不满足条件就继续
      • 基础示例:从简单场景学用法
        • 示例 1:竖向打印数字 54321
        • 示例 2:模拟 "赚钱直到目标金额"
        • 示例 3:计算 1 到 100 的总和
        • 示例 4:计算 5 的阶乘(5! = 5×4×3×2×1)
        • 示例 5:猴子吃桃问题(逆向推导)
        • 示例 6:猜数字游戏(带次数统计)
        • 示例 7:CPU 满负荷消耗(带进程守护)
        • wait 指令:等待所有后台任务完成
      • 企业实战:循环的实际应用场景
        • 示例 1:定时监控系统负载
        • 示例 2:守护进程监控 sshd 服务
        • 示例 3:网站可用性监控
        • 示例 4:手机短信平台模拟
      • while 循环按行读取文件的 4 种方式
        • 方式 1:用 exec 重定向输入
        • 方式 2:用 cat 管道传递内容
        • 方式 3:在 done 后指定输入文件
        • 方式 4:用 for 循环(指定分隔符为换行)
      • 企业级高级实战:防御类 DDoS 攻击
        • 示例 1:根据 Web 日志封停高频访问 IP
        • 示例 2:根据并发连接数封停恶意 IP
      • 小结

循环语句是编程中用来重复执行指令的工具,就像生活中 “每天早上喝一杯水” 这样的重复行为。在 Shell 脚本里,常见的循环有 while、until、for 和 select,其中 while 和 until 主要用于 “根据条件重复执行” 的场景。本章我们就来详细聊聊这两种循环的用法,从基础语法到实际场景,让你一看就懂、一用就会。

当型和直到型循环:两种 “重复” 的逻辑

while 循环:满足条件就继续

while循环:当满足A条件,就执行B操作。

语法结构

while <条件表达式>  # 判断条件是否成立
do指令...  # 条件成立时执行的内容
done  # 执行完指令后,回到开头重新判断条件

通俗理解:while 循环就像 “只要下雨,就带伞”—— 只要条件(下雨)成立,就重复执行动作(带伞),直到条件不成立(不下雨)为止。

举个生活例子:

# 只要冰箱里有牛奶,就每天喝一杯
while 冰箱里有牛奶
do喝一杯牛奶
done

执行流程

  1. 先判断条件表达式是否成立;
  2. 成立则执行dodone之间的指令;
  3. 执行完后回到开头,再次判断条件;
  4. 直到条件不成立,跳出循环。
until 循环:不满足条件就继续

until循环:直到A条件满足时,B操作就执行。

语法结构

until <条件表达式>  # 判断条件是否成立
do指令...  # 条件不成立时执行的内容
done  # 执行完指令后,回到开头重新判断条件

通俗理解:until 循环就像 “直到雨停,才不带伞”—— 只要条件(雨停)不成立,就重复执行动作(带伞),直到条件成立(雨停)才停止。

举个生活例子:

# 直到冰箱里没有牛奶,才停止喝牛奶
until 冰箱里没有牛奶
do喝一杯牛奶
done

执行流程

  1. 先判断条件表达式是否成立;
  2. 不成立则执行dodone之间的指令;
  3. 执行完后回到开头,再次判断条件;
  4. 直到条件成立,跳出循环。

基础示例:从简单场景学用法

示例 1:竖向打印数字 54321

实验流程

  1. 定义变量i初始值为 5;
  2. 使用循环判断i是否满足条件(while 用i>0,until 用i==0);
  3. 满足条件时打印i,并让i减 1;
  4. 重复步骤 2-3,直到条件不满足,结束循环。

while 实现

#!/bin/bash
i=5  # 初始值设为5
# 当i>0时,进入循环
while ((i>0))
doecho $i  # 打印当前i的值((i--))  # i减1(相当于i = i - 1)
done

运行结果

5
4
3
2
1

until 实现

#!/bin/bash
i=5  # 初始值设为5
# 直到i==0时,停止循环(即i≠0时一直执行)
until ((i==0))
doecho $i  # 打印当前i的值((i--))  # i减1
done

运行结果

5
4
3
2
1
示例 2:模拟 “赚钱直到目标金额”

实验流程

  1. 设定目标金额target=10000000,初始金额money=0
  2. 使用 until 循环判断money是否达到目标;
  3. 未达到时,打印 “正在赚钱”,每次增加 1000000,休眠 1 秒;
  4. 达到目标后,打印 “hahaha” 并结束。
#!/bin/bash
target=10000000  # 目标金额:1000万
money=0  # 初始金额:0# 直到money >= target时停止循环(未达标时一直执行)
until (($money>=$target))
doecho "I'm working hard to get money..."  # 提示正在赚钱sleep 1  # 休眠1秒(模拟耗时过程)money=$[ money + 1000000 ]  # 每次赚100万echo "I have $money."  # 打印当前金额
done
echo hahaha  # 达标后打印

运行结果

I'm working hard to get money...
I have 1000000.
I'm working hard to get money...
I have 2000000.
...(中间省略)...
I'm working hard to get money...
I have 10000000.
hahaha
示例 3:计算 1 到 100 的总和

实验流程

  1. 定义变量i=1(起始数字)、sum=0(总和);
  2. 使用 while 循环判断i是否小于等于 100;
  3. 满足条件时,将i加到sum中,i加 1;
  4. 循环结束后,打印总和。
#!/bin/bash
i=1  # 从1开始
sum=0  # 初始总和为0# 当i<=100时,持续累加
while ((i<=100))
do((sum+=i))  # 等价于 sum = sum + i((i++))  # i加1(等价于i = i + 1)
done
echo "1+2+3+...+99+100=$sum"  # 打印结果

运行结果

1+2+3+...+99+100=5050
示例 4:计算 5 的阶乘(5! = 5×4×3×2×1)

实验流程

  1. 定义变量i=1(起始乘数)、sum=1(阶乘结果,初始为 1);
  2. 使用 while 循环判断i是否小于等于 5;
  3. 满足条件时,将sum乘以ii加 1;
  4. 循环结束后,打印结果。
#!/bin/bash
i=1  # 从1开始乘
sum=1  # 初始值为1(乘法的"单位元")# 当i<=5时,持续相乘
while ((i<=5))
do((sum*=i))  # 等价于 sum = sum * i((i++))  # i加1
done
echo "5的阶乘为:$sum"  # 打印结果

运行结果

5的阶乘为:120
示例 5:猴子吃桃问题(逆向推导)

问题描述:猴子每天吃剩下桃子的一半加 1 个,第 10 天早上只剩 1 个桃。求第一天摘了多少桃?

实验流程

  1. 已知第 10 天早上有 1 个桃,逆向推导前一天的数量(前一天 = (当天 + 1) × 2);
  2. 从第 10 天推到第 1 天,需要循环 9 次;
  3. 定义变量today=1(第 10 天的桃),循环计算前一天的数量并更新today
  4. 循环结束后,today即为第一天的数量。

while 循环实现

#!/bin/bash
today=1  # 第10天早上的桃子数量
lastday=0  # 用于存储前一天的数量
i=1  # 循环计数器# 循环9次(从第10天推到第1天)
while ((i<=9))
dolastday=$[(today+1)*2]  # 计算前一天的数量:前一天 = (当天 + 1) × 2today=${lastday}  # 更新today为前一天的数量(向前推一天)((i++))  # 计数器加1
done
echo "猴子第一天摘的桃子数量是:$today。"

运行结果

猴子第一天摘的桃子数量是:1534。

函数递归实现

#!/bin/bash
# 定义递归函数:计算第n天早上的桃子数量
function sum (){if [[ $1 = 10 ]];then  # 第10天早上固定是1个echo 1else# 前一天 = (当天 + 1) × 2(递归调用下一天的结果)echo $[ ($(sum $[$1 +1]) + 1)*2 ]fi
}
echo "猴子第一天摘的桃子数量是:$(sum 1)。"  # 计算第1天的数量

运行结果

猴子第一天摘的桃子数量是:1534。
示例 6:猜数字游戏(带次数统计)

实验流程

  1. 系统生成 1-50 的随机数,保存到临时文件;
  2. 提示用户猜数字,记录猜测次数;
  3. 若猜测正确,提示次数并清理临时文件;
  4. 若猜错,提示 “太大” 或 “太小”,继续猜测;
  5. 若输入超出 1-50,提示重新输入。
#!/bin/bash
# 生成1-50的随机数(RANDOM是系统随机数,%50取0-49,+1后为1-50)
random_num=$[ RANDOM%50+1 ]
echo "${random_num}" >> /tmp/number  # 保存到临时文件(可用于验证)i=0  # 猜测次数计数器# 无限循环(直到猜对才退出)
while true
doread -p "猜一猜系统产生的50以内随机数是:" num  # 读取用户输入# 判断输入是否在1-50之间if ((num>=1 && num<=50));then((i++))  # 次数加1# 判断是否猜对if [ $num -eq ${random_num} ];thenecho "恭喜你,第$i次猜对了!"rm -f /tmp/number  # 清理临时文件exit  # 退出脚本elseecho -n "第$i次猜测,加油。"# 提示猜大或猜小[ $num -gt ${random_num} ] && echo "太大了,往小猜。" || echo "太小了,往大猜。"fielseecho "请输入一个介于1-50之间的数字。"  # 输入无效时提示fi 
done

运行示例

猜一猜系统产生的50以内随机数是:25
第1次猜测,加油。太大了,往小猜。
猜一猜系统产生的50以内随机数是:10
第2次猜测,加油。太小了,往大猜。
猜一猜系统产生的50以内随机数是:15
恭喜你,第3次猜对了!
示例 7:CPU 满负荷消耗(带进程守护)

实验流程

  1. 获取 CPU 核心数,启动对应数量的 “CPU 负载进程”(无限循环计算 1+1);
  2. 持续监控进程数量,若少于 CPU 核心数,自动补充新进程;
  3. 即使管理员杀死进程,也会重新启动,直到手动终止脚本。

cpu_load 脚本(负载进程)

#!/bin/bash
# 无限循环执行1+1(消耗CPU资源)
while true;do let 1+1;done

multi_cpu_load 脚本(进程守护)

#!/bin/bash
# 获取CPU核心数(通过lscpu命令过滤)
cpu_count=$(lscpu|egrep '^CPU\(s' | awk '{print $2}')\# 启动与CPU核心数相同的负载进程
for ((i=1;i<=cpu_count;i++))
dobash /root/bin/cpu_load &  \# 后台运行负载进程
done\# 持续监控进程数量,不足则补充
while true
do\# 统计当前负载进程数量(排除grep自身)current_count=$(ps axu |grep cpu_load |grep -v grep| wc -l)\# 若数量少于CPU核心数,补充新进程if [ $current_count -lt ${cpu_count} ];thenbash /root/bin/cpu_load &sleep 3  \# 间隔3秒再检查fi 
done
```**验证方法**:
1. 运行脚本:`bash multi_cpu_load &`2. 查看CPU使用率:`top`(按`1`显示每个核心,可见所有核心使用率接近100%);
3. 手动杀死一个负载进程:`pkill -f cpu_load`4. 再次查看进程:`ps aux | grep cpu_load`(会发现进程数量自动恢复)。\##\# 10.3 脚本后台运行:防止执行中断在实际工作中,脚本可能需要长时间运行(如监控脚本),若不小心关闭终端或按`Ctrl+C`,脚本就会中断。以下是几种防止中断的方法:| 方法 | 命令示例 | 说明 |
|------|----------|------|
| 后台运行 | `sh script.sh &` | 脚本在后台运行,终端关闭后会停止 |
| 忽略挂断信号 | `nohup sh script.sh &` | 终端关闭后仍继续运行,输出保存到`nohup.out` |
| 保持会话 | `screen -S session1` <br> 然后执行脚本 | 关闭终端后,可通过`screen -r session1`恢复会话 |**常用操作命令**:
- `Ctrl+C`:停止当前前台运行的脚本;
- `Ctrl+Z`:暂停当前前台脚本,放入后台(状态为`Stopped`);
- `bg %任务编号`:将暂停的后台任务转为运行状态(如`bg %1`);
- `fg %任务编号`:将后台任务调回前台(如`fg %1`);
- `jobs`:查看当前后台任务列表(含编号);
- `kill %任务编号`:终止后台任务(如`kill %1`)。\##\## 示例:让所有CPU满负荷工作(简化版)
```bash
\#!/bin/bash
\# 获取CPU核心数
cpu_count=$(lscpu|grep '^CPU(s)'|awk '{print $2}')
i=1\# 为每个CPU核心启动一个负载进程
while ((i<=${cpu_count}))
do{  \# 将命令组放入后台运行while :  \# 等价于while true(无限循环)do((1+1))  \# 简单计算消耗CPUdone} &  \# 后台运行该命令组((i++))  \# 计数器加1
done
```
**验证**:运行后用`top`命令查看,所有CPU核心使用率接近100%。\##\# 10.4 并发控制:限制同时运行的进程数当需要批量执行任务时,若进程过多会占用大量资源,因此需要控制并发数量(如不超过CPU核心数)。\##\## 示例:控制并发数不超过CPU核心数
**cpu_load 脚本(限时负载)**:
```bash
\#!/bin/bash
\# 后台运行负载进程
while true
do((1+1))
done &pid=$!  \# 获取后台进程的PID
sleep 10 && kill -9 $pid  \# 10秒后自动杀死该进程
```**multi_cpu_load 脚本(并发控制)**:
```bash
\#!/bin/bash
\# 获取CPU核心数
cpu_count=$(lscpu | awk '/^CPU\(s\):/ { print $2}')# 无限循环启动负载进程
while true
dobash /home/bq/cpu_load &  # 启动一个负载进程# 检查当前并发数,若超过CPU核心数则等待while truedojobs=$(jobs -l |wc -l)  # 统计当前后台任务数if [ $jobs -ge $cpu_count ];thensleep 3  # 并发数已满,休眠3秒再检查elsebreak  # 并发数未满,退出内层循环,继续启动新进程fidone
done

验证:运行后用jobs命令查看,后台任务数始终等于 CPU 核心数。

wait 指令:等待所有后台任务完成
#!/bin/bash
> /tmp/sleep  # 清空临时文件(用于记录结果)
i=1# 启动10个后台任务(分别休眠1-10秒)
while [ $i -le 10 ]
do# 休眠i秒后,将结果写入文件(&表示后台运行)( sleep $i && echo sleep $i >> /tmp/sleep )&((i++))
donewait  # 等待所有后台任务完成
cat /tmp/sleep  # 打印所有结果(按休眠时间排序)

运行结果

sleep 1
sleep 2
sleep 3
sleep 4
sleep 5
sleep 6
sleep 7
sleep 8
sleep 9
sleep 10

企业实战:循环的实际应用场景

示例 1:定时监控系统负载

实验流程

  1. 无限循环执行uptime命令(查看系统负载);
  2. 每次执行后休眠 2 秒;
  3. 可选:将结果写入日志文件(后台运行时用)。
#!/bin/bash
# 无限循环监控系统负载
while true
douptime  # 输出系统负载信息(当前时间、运行时间、用户数、平均负载)sleep 2  # 每2秒监控一次
done

运行结果

 10:23:45 up 2 days,  3:15,  2 users,  load average: 0.05, 0.03, 0.0010:23:47 up 2 days,  3:15,  2 users,  load average: 0.05, 0.03, 0.00
...(每2秒输出一次)

后台日志版

#!/bin/bash
while true
douptime >> /tmp/loadaverage.log  # 结果写入日志sleep 2
done

使用方法bash while2.sh &(后台运行),用tail -f /tmp/loadaverage.log查看实时日志。

示例 2:守护进程监控 sshd 服务

实验流程

  1. 无限循环检查 sshd 服务状态;
  2. 若服务未运行,自动重启;
  3. 每 5 秒检查一次。

while 实现

#!/bin/bash
while true
do # 检查sshd服务是否活跃(&>/dev/null表示不输出结果)systemctl is-active sshd.service &>/dev/nullif [ $? -ne 0 ];then  # $?为0表示服务正常,非0表示异常systemctl restart sshd.service  &>/dev/null  # 重启服务echo "sshd restarted at $(date)" >> /tmp/sshd_monitor.log  # 记录重启时间fisleep 5  # 每5秒检查一次
done

until 实现

#!/bin/bash
# until false 等价于while true(因为false永远不成立,所以循环无限执行)
until false
do systemctl is-active sshd.service &>/dev/nullif [ $? -ne 0 ];then systemctl restart sshd.service  &>/dev/nullecho "sshd restarted at $(date)" >> /tmp/sshd_monitor.logfisleep 5
done

验证:手动停止 sshd 服务(systemctl stop sshd),5 秒后查看状态(systemctl status sshd),会发现服务已自动重启。

示例 3:网站可用性监控

实验流程

  1. 接收用户输入的 URL 作为参数;
  2. 无限循环用curl检查 URL 是否可访问;
  3. 每 3 秒检查一次,输出 “正常” 或 “异常”。
#!/bin/bash
# 检查参数:必须提供一个URL
if [ $# -ne 1 ];thenecho "Usage: $0 url"  # 提示用法(如:bash check_url.sh www.baidu.com)exit 1
fiurl="$1"  # 保存URL参数while true
do# curl选项:-o /dev/null(不保存输出)、-s(静默模式)、--connect-timeout 5(超时5秒)if curl -o /dev/null -s --connect-timeout 5 $url;thenecho "$url is ok."  # 访问成功elseecho "$url is error."  # 访问失败fisleep 3  # 每3秒检查一次
done

运行示例

bash check_url.sh www.baidu.com
www.baidu.com is ok.
www.baidu.com is ok.
...
示例 4:手机短信平台模拟

实验流程

  1. 初始余额 0.5 元,每条短信花费 0.15 元;
  2. 提供菜单:查询余额、发送短信、充值、退出;
  3. 发送短信前检查余额,不足则提示充值;
  4. 充值时验证输入为正数,否则提示重新输入。
#!/bin/bashmoney=0.5  # 初始余额(单位:元)
msg_file=/tmp/message  # 保存短信的文件
> $msg_file  # 清空文件# 打印菜单函数
function print_menu () {cat << EOF
1. 查询余额
2. 发送消息
3. 充值
4. 退出
EOF
}# 检查输入是否为数字
function check_digit () {# expr计算失败时返回非0,用于判断是否为数字expr $1 + 1 &> /dev/null && return 0 || return 1
}# 显示当前余额
function check_money_all () {echo "余额为:$money 元。"
}# 检查余额是否足够发送一条短信(0.15元)
function check_money () {# 将余额转换为分(避免小数计算误差)new_money=$(echo "$money*100"|bc|cut -d . -f1)if [ ${new_money} -lt 15 ];then  # 小于15分(0.15元)echo "余额不足,请充值。"return 1  # 余额不足返回1elsereturn 0  # 余额充足返回0fi
}# 充值函数
function chongzhi () {read -p "充值金额(单位:元):" chongzhi_moneywhile truedocheck_digit $chongzhi_money  # 检查是否为数字# 若为数字且>=1元,则执行充值if [ $? -eq 0 ] && [ ${chongzhi_money} -ge 1 ];then# 用bc工具处理小数加法money=$( echo "($money+${chongzhi_money})"|bc)echo "充值成功,当前余额为:$money 元"return 0elseread -p "输入无效,请重新输入充值金额(至少1元):" chongzhi_money fidone
}# 发送短信函数
function send_msg () {check_money  # 检查余额if [ $? -eq 0 ];then  # 余额充足read -p "请输入短信内容:" messageecho "$message" >> ${msg_file}  # 保存短信# 计算扣除0.15元后的余额(转换为分计算)new_money=$(echo "scale=2;($money*100-15)" | bc |cut -d. -f1 )# 转换回元(处理小于1元的情况,如0.35元)if [ ${new_money} -ge 100 ];thenmoney=$(echo "scale=2;${new_money}/100" | bc )elsemoney=0$(echo "scale=2;${new_money}/100" | bc )fiecho "发送成功,当前余额为:$money 元"fi
}# 主程序(无限循环显示菜单)
while true
doprint_menuechoread -p "请输入你的选择(1-4):" choiceclear  # 清屏,使界面整洁case  $choice in1)check_money_all  # 调用查询余额函数;;2)send_msg  # 调用发送短信函数;;3)chongzhi  # 调用充值函数;;4)exit  # 退出脚本;;*)echo "输入错误,请从1、2、3、4中选择。" ;;esacecho
done

运行示例

1. 查询余额
2. 发送消息
3. 充值
4. 退出请输入你的选择(1-4):1
余额为:0.5 元。1. 查询余额
2. 发送消息
3. 充值
4. 退出请输入你的选择(1-4):2
请输入短信内容:hello
发送成功,当前余额为:0.35 元

while 循环按行读取文件的 4 种方式

读取文件内容是脚本中常见的操作,以下是用 while 循环按行读取/etc/hosts文件的 4 种方法:

方式 1:用 exec 重定向输入
#!/bin/bash
exec < /etc/hosts  # 将文件内容重定向为标准输入
# 循环读取每一行(read line会自动读取下一行,直到文件结束)
while read line
doecho $line  # 打印当前行
done
方式 2:用 cat 管道传递内容
#!/bin/bash
# cat读取文件内容,通过管道传给while循环
cat /etc/hosts | while read line
doecho $line
done
方式 3:在 done 后指定输入文件
#!/bin/bash
# 循环读取行,done后指定输入文件
while read line
doecho $line
done < /etc/hosts  # 输入重定向到文件
方式 4:用 for 循环(指定分隔符为换行)
#!/bin/bash
IFS=$'\n'  # 将分隔符设为换行(默认包含空格、制表符等,会拆分一行)
# 遍历文件内容的每一行
for line in $(cat /etc/hosts)
doecho $line
done

说明:方式 1-3 功能相同,方式 4 适合用 for 循环的场景,但需注意文件中是否有特殊字符(如空格)。

企业级高级实战:防御类 DDoS 攻击

示例 1:根据 Web 日志封停高频访问 IP

场景:若某个 IP1 小时内访问次数(PV)超过 500,判定为恶意攻击,用 iptables 封停。

实验流程

  1. 每小时分析一次 Web 日志,提取所有访问 IP;
  2. 统计每个 IP 的访问次数;
  3. 对次数超过 500 且未被封停的 IP,执行封停命令并记录。
#!/bin/bash
logfile=$1  # 接收Web日志文件路径作为参数# 无限循环,每小时执行一次
while true
do# 提取日志中第1列(IP),去重并统计次数,保存到临时文件awk '{print $1}' $logfile | grep -v "^$" | sort |uniq -c > /tmp/tmp.logexec < /tmp/tmp.log  # 读取临时文件内容while read linedoip=$(echo $line |awk '{print $2}')  # 提取IPcount=$(echo $line |awk '{print $1}')  # 提取访问次数# 若次数>500且未被封停,则执行封停if [ $count -gt 500 ] && [ $(iptables -L -n|grep "$ip" |wc -l) -lt 1 ];theniptables -I INPUT -s $ip -j DROP  # 封停IPecho "$(date +'%F %T') $ip is dropped (count=$count)" >> /tmp/droplist_$(date +%F).log  # 记录日志fidonesleep 3600  # 每3600秒(1小时)执行一次
done

使用方法bash block_ip_by_log.sh /var/log/nginx/access.log(需替换为实际日志路径)。

示例 2:根据并发连接数封停恶意 IP

场景:若某个 IP 的并发连接数超过 100,判定为恶意攻击,用 iptables 封停。

实验流程

  1. 每 10 秒统计一次 ESTABLISHED 状态的连接;
  2. 提取客户端 IP 并统计连接数;
  3. 对连接数超过 100 且未被封停的 IP,执行封停命令并记录。
#!/bin/bash
# 无限循环,每10秒执行一次
while true
do# 提取ESTABLISHED状态连接的客户端IP(第4列是客户端地址,:前为IP)ss -t | grep ESTAB|awk '{print $4}' | cut -d: -f1 | sort |uniq -c > /tmp/tmp.logexec < /tmp/tmp.log  # 读取临时文件内容while read linedoip=$(echo $line |awk '{print $2}')  # 提取IPcount=$(echo $line |awk '{print $1}')  # 提取连接数# 若连接数>100且未被封停,则执行封停if [ $count -gt 100 ] && [ $(iptables -L -n|grep "$ip" |wc -l) -lt 1 ];theniptables -I INPUT -s $ip -j DROP  # 封停IPecho "$(date +'%F %T') $ip is dropped (count=$count)" >> /tmp/droplist_$(date +%F).log  # 记录日志fidonesleep 10  # 每10秒执行一次
done

验证:运行脚本后,用ss -t | grep ESTAB | awk '{print $4}' | cut -d: -f1 | sort | uniq -c查看 IP 连接数,模拟高并发后会被自动封停。

小结

  1. while vs until
    • while 是 “条件成立就执行”(当型循环),适合 “满足条件持续做” 的场景(如守护进程);
    • until 是 “条件不成立就执行”(直到型循环),适合 “不满足条件持续做,满足后停止” 的场景。
  2. 常见用法场景
    • 无限循环(while true):用于监控、守护进程(需配合sleep控制频率);
    • 按条件重复:如计数、累加、逆向推导(如猴子吃桃);
    • 读取文件:按行处理文本内容(4 种读取方式);
    • 并发控制:限制后台进程数量,避免资源耗尽。
  3. 实战技巧
    • 后台运行脚本用nohupscreen,防止中断;
    • wait等待所有后台任务完成;
    • 防御攻击时,结合日志 / 连接数统计 + 防火墙命令,实现自动封停。

通过本章学习,你已经掌握了循环的核心逻辑和实际应用,接下来可以尝试用循环解决更多复杂场景(如批量处理文件、定时任务等)。

如涉及版权问题,请联系作者处理!!!

http://www.xdnf.cn/news/18564.html

相关文章:

  • 题解:P13754 【MX-X17-T3】Distraction_逆序对_前缀和_Ad-hoc_算法竞赛C++
  • java猜数字游戏(赌城主题版)
  • priority_queue和仿函数
  • 【CSP初赛】程序阅读3
  • (一)算法(big O/)
  • 一种解决使用 PotPlayer 播放 Alist 的 Webdav 时提示 无法在 FTP/WebDAV/HTTP 上修改该文件夹 的方法
  • QT-Mysql-查询语句-查询是否有表-表列名-查询记录
  • 【AI基础:神经网络】16、神经网络的生理学根基:从人脑结构到AI架构,揭秘道法自然的智能密码
  • TensorFlow 深度学习 开发环境搭建
  • Java和数据库的关系
  • Ubuntu 的 apt-get 强制使用 IPv4 网络
  • How to Use Managed Identity with ACS?
  • XCVU13P-2FHGB2104E Xilinx(AMD)Virtex UltraScale+ FPGA
  • MySQL索引原理与优化全解析
  • 55.Redis搭建主从架构
  • ANSI终端色彩控制知识散播(II):封装的层次(Python)——不同的逻辑“一样”的预期
  • 【C初阶】自定义类型--结构体
  • Java:对象的浅拷贝与深拷贝
  • 探索 List 的奥秘:自己动手写一个 STL List✨
  • 基于JSqlParser的SQL语句分析与处理
  • 网址账号正确,密码错误返回的状态码是多少
  • Go语言数据结构与算法-基础数据结构
  • Compose笔记(四十七)--SnackbarHost
  • Axure:有个特别实用的功能
  • 什么是AI宠物
  • [2025CVPR-目标检测方向]PointSR:用于无人机视图物体检测的自正则化点监控
  • C++的struct里面可以放函数,讨论一下C++和C关于struct的使用区别
  • leetcode算法刷题的第十六天
  • 力扣热题之技巧
  • 雷卯针对香橙派Orange Pi 3G-IoT-B开发板防雷防静电方案