本质是用recursivedirectoryiterator或glob()高效扫描文件,结合filemtime()比对时间戳识别超期文件,再通过日志、邮件(单次汇总)等方式通知;必须用cron定时执行cli脚本,并注意时区、权限和跨平台兼容性。

PHP用filemtime()判断文件是否过期再提醒
批量提醒的本质是:扫描目录下一批文件,检查它们的最后修改时间是否超过某个阈值(比如7天),超时就触发通知。PHP本身不带“提醒”功能,得靠你定义通知方式(邮件、日志、控制台输出等),核心是准确识别哪些文件该被提醒。
关键不是“怎么发”,而是“怎么找”。别直接遍历所有文件再逐个stat()——效率低还容易漏掉嵌套子目录。推荐用RecursiveDirectoryIterator配合filemtime():
-
filemtime()返回的是 Unix 时间戳,和time()单位一致,可直接做减法比较 - 注意它对符号链接默认返回链接本身的修改时间,不是目标文件;如需跟随链接,得用
filemtime(realpath($path)) - 如果文件被删除或权限不足,
filemtime()会警告并返回false,必须提前用is_file()和is_readable()兜底
用glob()快速筛选特定后缀的待提醒文件
如果你只关心.log或.csv这类文件,glob()比迭代器更轻量,且天然支持通配符。但要注意它的路径行为:
-
glob('logs/*.log')只查一级子目录;要递归匹配,得用glob('logs/**/*.log', GLOB_BRACE | GLOB_ONLYDIR)(PHP 7.1+)或手动拼接**模式 - Windows 下
glob()对大小写不敏感,Linux 下敏感——若脚本跨平台部署,别依赖.LOG和.log自动匹配 - 返回数组为空时不报错,但容易被忽略;建议加
if (empty($files)) { error_log("No files matched"); }防静默失败
避免mail()在批量场景下被拒或限流
用mail()发提醒看似简单,但批量调用极易触发本地MTA(如sendmail)的速率限制,或被收件方标记为垃圾邮件。真实项目中不建议直接循环调用mail()。
- 改用单次发送汇总内容:把所有超期文件路径、修改时间、超期天数拼成一个
$message字符串,一次发完 - 设置
headers参数,至少包含From:和Content-Type: text/plain; charset=UTF-8,否则中文可能乱码 - 更稳妥的做法是写入日志文件(
error_log($message, 3, '/var/log/file-alerts.log')),再由外部工具(如logrotate + cron)统一处理推送
定时执行必须用cron而非sleep()
有人试图在PHP脚本里写while(true) { check_and_alert(); sleep(3600); }来模拟定时,这在Web服务器上极其危险:进程会长期驻留、占用内存、无法优雅终止,且Apache/Nginx可能主动kill掉超时请求。
- 正确做法是把检测逻辑写成独立CLI脚本(如
/usr/local/bin/check-files.php),然后用系统cron调度 - crontab示例:
0 2 * * * /usr/bin/php /usr/local/bin/check-files.php >> /var/log/file-check.log 2>&1(每天凌晨2点执行) - 务必在脚本开头加
#!/usr/bin/env php并chmod +x,否则cron可能找不到PHP解释器
最易被忽略的是时区——PHP CLI环境的date.timezone常和Web环境不同,filemtime()本身不涉及时区,但人读日志时看到“2024-05-01”和“超期3天”却对不上本地时间,八成是CLI的php.ini里date.timezone没设对。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











