最轻量的批量文件修改监控是定时轮询 filemtime()。需先用 is_file() 和 is_readable() 过滤无效路径,缓存上一轮时间戳,避免重复读取元数据及警告。

用 filemtime() 检查文件是否被修改
最轻量的批量监控,就是定时轮询每个目标文件的最后修改时间。PHP 本身不提供文件系统事件监听(如 inotify),所以得靠主动比对 filemtime()。注意:该函数返回 Unix 时间戳,不是字符串;若文件不存在或无读取权限,会触发警告并返回 false,必须提前判断。
实操建议:
- 把待监控路径存进数组,避免硬编码路径字符串
- 每次检查前用
is_file()和is_readable()过滤无效项,防止警告打断流程 - 缓存上一轮的
filemtime()结果(例如存在$lastTimes关联数组里),不要每次都读一遍文件系统元数据 - 别用
time() - filemtime($f) 判断“1分钟内修改”——时区或系统时间跳变会导致误判,应比对前后两次 <code>filemtime()值是否变化
用 glob() 批量匹配路径,避开递归陷阱
监控日志目录或上传目录时,常要覆盖 logs/*.log 或 uploads/**/*.{jpg,png}。PHP 的 glob() 支持通配符,但默认不递归;PHP 7.1+ 才支持 GLOB_BRACE,旧版本需手动拼接多个 glob() 调用。
实操建议:
- 用
glob($pattern, GLOB_NOSORT | GLOB_NOESCAPE)避免隐式排序开销和反斜杠转义干扰 - Windows 下
glob()不支持**,需用RecursiveDirectoryIterator替代——但那会显著增加内存占用,小脚本慎用 - 如果模式中含变量(如
"$dir/*.tmp"),确保$dir已过滤掉../等路径穿越字符,否则可能意外扫到系统文件
避免 sleep() 阻塞导致监控延迟
写成死循环 + sleep(5) 最常见,但 PHP CLI 默认有 max_execution_time 限制(通常 30 秒),超时后进程直接退出,监控就断了。Web 环境更不可行——HTTP 请求不能挂起几十秒。
实操建议:
- CLI 模式下先执行
set_time_limit(0),并确认系统 ulimit 未限制进程时长 - 用
pcntl_signal()注册SIGINT(Ctrl+C)信号处理器,让脚本可优雅退出,而不是被 kill -9 强杀导致状态丢失 - 真正生产环境别自己写长周期轮询——改用
systemd定时启动、或配合inotifywait外部命令(Linux)更可靠
记录变更时小心 fopen('a') 的并发写入问题
监控到文件变动,习惯性用 fopen($logFile, 'a') 追加日志。但在高频率写入或多个 PHP 进程同时监控时,'a' 模式不保证原子性,可能造成日志内容错乱(比如两行日志挤在同一行)。
实操建议:
- 改用
fopen($logFile, 'c')+fseek($fp, 0, SEEK_END)+fwrite(),虽稍慢但可规避部分竞态 - 更稳妥的是用
file_put_contents($logFile, $line, FILE_APPEND | LOCK_EX),LOCK_EX会阻塞其他进程直到写完 - 日志量大时,别直接写磁盘文件——写入 Redis List 或本地 socket,再由单独进程落盘,解耦更稳
真正的难点不在“怎么发现变化”,而在“怎么不漏报、不误报、不拖垮服务器”。轮询间隔、路径合法性校验、错误静默处理、进程生命周期管理——这些细节堆起来,才决定脚本能跑几天还是几小时。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











