until 循环

until 循环和 while 循环正好相反:条件为假时执行,条件为真时退出。理解了这个区别,就知道什么时候该用 until。

基本语法

until [ 条件 ]; do
    命令
done

条件为假时执行循环体,条件为真时退出。

与 while 的对比

# while:条件为真时执行
COUNT=1
while [ $COUNT -gt 5 ]; do
    echo $COUNT
    COUNT=$((COUNT + 1))
done
# 不输出任何内容,因为一开始条件就是假

# until:条件为假时执行
COUNT=1
until [ $COUNT -gt 5 ]; do
    echo $COUNT
    COUNT=$((COUNT + 1))
done
# 输出 1 2 3 4 5

简单记忆:

  • while:当条件成立时,一直做
  • until:直到条件成立,才停止

基本示例

#!/bin/bash

COUNT=1

until [ $COUNT -gt 5 ]; do
    echo "计数: $COUNT"
    COUNT=$((COUNT + 1))
done

等待条件成立

until 最常见的用途是等待某个条件成立:

# 等待文件出现
until [ -f /tmp/ready ]; do
    echo "等待文件..."
    sleep 1
done
echo "文件已出现"

# 等待服务启动
until curl -s http://localhost:8080/health > /dev/null; do
    echo "等待服务启动..."
    sleep 2
done
echo "服务已启动"

等待进程结束

#!/bin/bash

PID=$1

until ! kill -0 $PID 2>/dev/null; do
    echo "进程 $PID 仍在运行..."
    sleep 1
done

echo "进程 $PID 已结束"

kill -0 只是检查进程是否存在,不发送信号。

带超时的等待

#!/bin/bash

TIMEOUT=30
START=$(date +%s)

until curl -s http://localhost:8080/health > /dev/null; do
    NOW=$(date +%s)
    ELAPSED=$((NOW - START))
    
    if [ $ELAPSED -ge $TIMEOUT ]; then
        echo "等待超时"
        exit 1
    fi
    
    echo "等待服务启动... ($ELAPSED/$TIMEOUT 秒)"
    sleep 1
done

echo "服务已启动"

读取输入直到特定值

#!/bin/bash

until [ "$INPUT" = "quit" ]; do
    read -p "请输入 (quit 退出): " INPUT
    echo "你输入了: $INPUT"
done

echo "再见"

无限循环

# until 也可以实现无限循环
until false; do
    echo "无限循环"
    sleep 1
done

实际应用

等待数据库就绪

#!/bin/bash

until mysqladmin ping -h db -u root -p$MYSQL_ROOT_PASSWORD --silent; do
    echo "等待数据库启动..."
    sleep 2
done

echo "数据库已就绪"

等待网络连接

#!/bin/bash

until ping -c 1 google.com > /dev/null 2>&1; do
    echo "等待网络连接..."
    sleep 5
done

echo "网络已连接"

等待锁文件释放

#!/bin/bash

LOCK_FILE="/tmp/backup.lock"

until [ ! -f "$LOCK_FILE" ]; do
    echo "等待锁释放..."
    sleep 10
done

# 创建锁文件
touch "$LOCK_FILE"

# 执行备份
echo "开始备份..."

# 释放锁
rm "$LOCK_FILE"

until vs while

什么时候用 until,什么时候用 while?

用 until 的场景:

  • 等待某个条件成立
  • 条件更容易用"否定"表达
  • 语义更清晰时

用 while 的场景:

  • 条件为真时持续执行
  • 条件更容易用"肯定"表达
  • 大多数循环场景

示例对比:

# 等待文件出现:until 更直观
until [ -f /tmp/ready ]; do
    sleep 1
done

# 用 while 写
while [ ! -f /tmp/ready ]; do
    sleep 1
done

小结

until 循环要点:

  1. 条件为假时执行,为真时退出
  2. 适合"等待条件成立"的场景
  3. 与 while 逻辑相反
  4. 选择语义更清晰的方式