在 Bash 中,sleep 命令会让脚本的执行暂停一段指定的时间。它是 Shell 脚本中最常用的命令之一,尤其是在重试失败的操作、对一系列请求做限流,或在循环中加入短暂延迟时。

在本指南中,我们将通过实际示例演示如何使用 sleep 命令,包括如何让 sleep 暂停小数秒、如何组合多个时间单位,以及如何在后台运行 sleep。

语法

sleep 命令的语法如下:

sleep NUMBER[SUFFIX]...

NUMBER 可以是一个正整数或浮点数。

SUFFIX 可以是下列之一:

  • s — 秒(默认)
  • m — 分
  • h — 时
  • d — 天

如果不指定后缀,默认单位为秒。

当给定两个或更多参数时,总时长等于各参数值之和。

sleep 命令示例

下面这些示例展示了 sleep 命令的基本形式。

暂停指定秒数

要让脚本等待指定的秒数,直接传入不带后缀的数字即可。下面的命令会让执行延迟 5 秒:

sleep 5

暂停不足一秒(小数秒)

对于不足一秒的延迟,可以传入一个小数:

sleep 0.5

组合多个时长

可以组合多个值。下面这条命令会暂停 2 分 30 秒:

sleep 2m 30s

无限期暂停

要让进程无限期暂停,直到被手动中断,可以使用 infinity:

sleep infinity

这在 Docker 容器和 systemd 服务中很常见,用于在几乎不占用 CPU 的情况下让进程保持运行。

脚本示例

下面这些示例展示了 sleep 在 Bash 脚本中的常见用法。

计时延迟

这个脚本会在 5 秒延迟前后分别打印时间:

#!/bin/bash



# start time

date +"%H:%M:%S"



# sleep for 5 seconds

sleep 5



# end time

date +"%H:%M:%S"

运行该脚本时,它会先以 HH:MM:SS 格式打印当前时间。随后 sleep 命令让脚本暂停 5 秒。指定的时间过后,最后一行会打印当前时间。

13:34:40
13:34:45

等待主机上线

下面的脚本每 5 秒检查一次某台主机是否在线,并在其可达时通知你:

#!/bin/bash



while :

do

  if ping -c 1 192.168.1.10 &> /dev/null

  then

    echo "Host is online"

    break

  fi

  sleep 5

done

脚本的工作原理如下:

  • while 循环以 : 作为条件无限运行。
  • ping 命令向目标主机发送一个数据包。
  • 如果主机可达,脚本会打印“Host is online”,并用 break 退出循环。
  • 如果主机不可达,sleep 5 会让脚本暂停 5 秒后再重试。

指数退避重试

在重试失败的操作时,逐步增大每次尝试之间的延迟是一种良好的做法,可以避免压垮目标服务:

#!/bin/bash



max_retries=5

delay=1



for ((i = 1; i <= max_retries; i++)); do

  if curl -s --fail https://example.com > /dev/null; then

    echo "Request succeeded on attempt $i"

    exit 0

  fi



  echo "Attempt $i failed. Retrying in ${delay}s..."

  sleep "$delay"

  delay=$((delay * 2))

done



echo "All $max_retries attempts failed."

exit 1

延迟从 1 秒开始,每次失败后翻倍:1s、2s、4s、8s、16s。

倒计时器

一个简单的倒计时器,会打印剩余的秒数:

#!/bin/bash



seconds=${1:-10}



for ((i = seconds; i > 0; i--)); do

  printf "\rTime remaining: %d seconds " "$i"

  sleep 1

done



printf "\rTime's up!                    \n"

运行该脚本时可传入一个可选的秒数:

bash countdown.sh 30

在后台运行 sleep

可以在后台运行 sleep,从而实现非阻塞的延迟:

sleep 10 &

echo "Sleep is running in the background with PID $!"

& 运算符会把进程放到后台运行。特殊变量 $! 保存着最后一个后台进程的 PID。

要等待后台的 sleep 结束,可以使用 wait 命令:

sleep 10 &

pid=$!

echo "Doing other work..."

wait "$pid"

echo "Sleep finished"

暂停直到按键

在某些脚本中,你可能希望暂停直到用户按下某个键,而不是等待固定时长。sleep 命令本身做不到这一点,但你可以把它和 read 命令结合使用:

#!/bin/bash



read -n 1 -s -r -p "Press any key to continue..."

echo

-n 1 选项让 read 只接受一个字符,-s 不在终端回显按键,-r 则禁止对反斜杠进行转义解释。这是一种让脚本在继续之前等待用户确认的常见做法。

如果想要暂停直到按下按键,但没有人操作时也能自行继续,可以加上 -t 选项:

#!/bin/bash



read -t 10 -n 1 -s -r -p "Press any key to continue (continuing in 10s)..."

echo

脚本最多等待 10 秒让用户输入任意键,然后继续执行。同样的选项在读取值时也有效,例如 read -t 5 -p "Enter your name: " name 会给用户 5 秒时间输入姓名,超时后脚本将在没有该值的情况下继续。

中断 sleep

要中断正在运行的 sleep 命令,按下 Ctrl+C 即可。这会发送 SIGINT 信号来终止该进程。

要终止后台的 sleep 进程,可以使用 kill:

sleep 300 &

kill $!

快速参考

命令
sleep 5
sleep 0.5
sleep 2m
sleep 1h 30m
sleep infinity
sleep 10 &
Ctrl+C 或 kill PID

常见问题

sleep 是 bash 的内置命令吗?不是。sleep 命令由 GNU coreutils 软件包提供,位于 /usr/bin/sleep。因为它是一个外部程序而非 Shell 内置命令,所以 GNU 版本支持小数秒和 infinity 参数等不属于 POSIX 规范的特性。

sleep 能接受小数值吗?可以。Linux 上使用的 GNU 版 sleep 支持浮点数。例如,sleep 0.5 会暂停半秒。POSIX 规范只要求支持整数,因此在并非所有 Unix 系统上都能如此使用。

为什么 sleep 会报错 invalid time interval?这是因为参数不是一个数字后跟可选单位。常见原因包括数字与后缀之间多了空格(例如写成 sleep 2 m 而不是 sleep 2m)、使用了命令不支持的单位(如表示周的 w),或者变量被展开成了空字符串。在把变量传给 sleep 之前,应先给它加引号并打印其值确认。

sleep infinity 有什么用?sleep infinity 会无限期暂停进程,且不占用 CPU。它常用于 Docker 容器中以保持容器运行,或用于需要等待信号的脚本。

sleep 在等待时会占用 CPU 吗?不会。sleep 命令会挂起进程,在等待期间不消耗 CPU 周期。

如何在脚本中取消 sleep?按下 Ctrl+C 即可向前台进程发送 SIGINT。对于后台的 sleep 进程,则使用 kill PID,其中 PID 是 $! 返回的那个进程 ID。

总结

sleep 命令会让下一条命令的执行暂停一段指定的时间。它常用于 Shell 脚本中,以重试操作、限制请求频率以及调度延迟。

对于较长的脚本,请让延迟保持显式,并配合清晰的输出,这样你就能判断脚本当前是在等待、重试,还是已经结束。