sleep()单位为秒且仅接受非负整数,传浮点数会警告并返回false;毫秒级延时需用usleep()(参数为微秒);两者均可被信号中断,应检查返回值并循环重试以确保精确延时。

PHP CLI 脚本里用 sleep() 最直接,但要注意单位是秒
sleep() 是 CLI 环境下最常用的延时函数,它会让当前进程暂停指定的**整数秒数**。比如 sleep(3) 就停 3 秒,期间 CPU 几乎不消耗,脚本也不往下走。
常见错误是误以为能传小数:sleep(0.5) 会直接报 Warning 并返回 false —— 它只接受 int 类型参数。真要毫秒级控制,得换 usleep()。
- 单位严格是「秒」,且必须为非负整数
- 返回值为
0表示成功,false表示失败(如传入浮点数或负数) - 信号(如 Ctrl+C)可中断
sleep(),但默认行为是继续执行后续代码,除非你显式捕获SIGINT
需要毫秒级延时?改用 usleep(),注意参数是微秒
usleep() 接收的是微秒(1 秒 = 1,000,000 微秒),所以 usleep(500000) ≈ 半秒。它比 sleep() 精确,也支持更短的停顿,适合轮询、限频等场景。
但别写成 usleep(1000) 想停 1 秒——那只是 1 毫秒,容易导致逻辑错乱。调试时建议先 echo 当前时间戳对比差值,确认是否真停够了。
立即学习“PHP免费学习笔记(深入)”;
- 参数类型仍是 int,超大数值(如 >2147483647)在 32 位系统可能溢出,导致意外行为
- 和
sleep()一样,可被信号中断;PHP 7.1+ 中,若被信号中断,usleep()返回false,之前版本返回null - 不要在高并发 CLI 长任务里无节制用
usleep(1)做“忙等”,既耗 CPU 又没意义
延时被信号打断后怎么继续?得手动检查返回值
CLI 脚本常跑在后台或被运维 kill -TERM,而 sleep() 和 usleep() 在收到信号时会提前退出,并返回 false。如果你依赖固定延时来控制节奏(比如每 5 秒拉一次 API),不检查返回值就可能跳过延时,瞬间发起一堆请求。
正确做法是用循环重试,直到累计延时达标:
function sleep_exact($seconds) {
$start = microtime(true);
while (microtime(true) - $start < $seconds) {
if (sleep(1) === false) {
// 被中断,继续等待剩余时间
continue;
}
}
}- 上面例子用
sleep(1)分段等待,避免单次阻塞太久失联 - 用
microtime(true)计算真实流逝时间,比单纯循环调用usleep()更可靠 - 生产环境建议加最大重试次数或超时保护,防止因信号风暴卡死
CLI 和 Web 环境下 sleep() 行为一致,但后果不同
函数本身行为没区别,但 CLI 中 sleep 不影响其他进程,而 Web 中 sleep 会占住一个 PHP-FPM worker 或 Apache 线程,容易拖垮并发能力。这点很多人混淆,以为 CLI 脚本里的 sleep() 也要“优化”成异步——其实完全没必要。
真正要注意的是资源释放:如果脚本在 sleep 前打开了文件、数据库连接或 curl 句柄,记得确认它们不会因延时过长被服务端断开(比如 MySQL 的 wait_timeout 默认 8 小时,一般够用;但 Redis 连接可能更敏感)。
- CLI 下放心用
sleep()控制节奏,它是轻量、可靠、语义清晰的工具 - 别为了“看起来高级”引入 ReactPHP 或 amphp,除非你真有并行 I/O 需求
- 延时逻辑一旦嵌套在循环或条件分支里,务必用日志打点,否则半夜出问题很难定位是卡在计算、IO 还是睡过头了











