PHP不适合做长期运行的监控画面刷新服务,因其Web环境受限于超时机制、进程销毁及I/O压力;应改用前端轮询+后端轻量接口方案,或CLI常驻进程配合中间文件。

PHP 本身不适合做长期运行的监控画面刷新服务,用 sleep() + 循环读取目录的方式在 Web 环境下基本不可靠,容易超时、阻塞、被回收,真要实现得换思路。
为什么 sleep() 在 PHP Web 脚本里根本撑不住监控画面
Web 服务器(如 Apache/Nginx + PHP-FPM)默认会限制脚本执行时间(max_execution_time 通常为 30 秒),即使你设成 0,FPM 的 request_terminate_timeout、SAPI 层超时、浏览器自动断连(如 Chrome 对长连接有 idle 限制)仍会中断。循环中调用 sleep(1) 看似简单,实际一两分钟后大概率返回 502/504 或空白页。
- PHP 进程不是守护进程,每次 HTTP 请求结束就销毁,无法“持续刷新”
-
sleep()期间不响应任何请求,整个连接挂起,无法支持多客户端 - 频繁
scandir()或glob()目录读取在高并发下易引发 I/O 压力,且无变更感知机制
真正可行的替代方案:前端轮询 + 后端轻量接口
把“刷新逻辑”从 PHP 后端移到浏览器端,后端只负责快速返回最新图片路径或 base64 数据,这才是稳定做法。
- 前端用
setInterval(() => { fetch('/api/latest-img.php') }, 1000)拉取最新图片 URL - 后端
latest-img.php不含sleep(),仅做:扫描目录 → 找最新修改的图片文件 → 返回json_encode(['src' => 'img/20240520-142345.jpg']) - 前端拿到后更新
的src,触发浏览器重新加载(可加时间戳防缓存:src + '?t=' + Date.now()) - 目录扫描建议用
array_filter(glob('img/*.jpg'), 'is_file'),再按filemtime()排序取第一个
如果硬要 PHP 后台常驻(仅限 CLI 环境)
仅当运行在终端(php monitor.php)且有进程管理(如 systemd / supervisor)时,sleep() 循环才可能成立,但此时已脱离 Web 场景,不能直接输出给浏览器。
立即学习“PHP免费学习笔记(深入)”;
- CLI 模式下可设
set_time_limit(0),用while (true) { ... sleep(1); } - 但不能 echo HTML 或图片二进制流——浏览器收不到;只能写日志、发消息、或生成供前端轮询的中间文件(如
latest.json) - 务必加异常捕获:
if (!is_dir('img')) { error_log('img dir missing'); break; } - 避免
filemtime()频繁调用,可缓存上次扫描结果,仅当目录 mtime 变化时才重扫
最易被忽略的一点:图片文件名若不含时间戳(比如固定叫 current.jpg),那么即使内容更新,浏览器很可能因强缓存不重载——必须用服务端响应头(Cache-Control: no-cache)或 URL 参数破缓存,否则前端看到的永远是旧图。











