什么是 inotify?

inotify 是 Linux 内核的一个子系统,专门用来监控文件系统事件(比如文件的创建、删除、读取、写入和关闭)。

在 PHP 中,inotify 扩展是对这个内核功能的封装。

1. 为什么它比“定时扫描”好?

维度 定时任务 (Cron) Inotify 扩展
实时性 取决于间隔(如 1 秒或 5 秒) 零延迟,文件一关闭立即触发
性能消耗 即使没图片,PHP 也会频繁启动并扫描磁盘 静默监听,无事件时不消耗 CPU
可靠性 容易漏掉处理中的文件,或重复处理 精确捕捉“文件写入完成”那一刻

2. 如何安装?

由于它依赖 Linux 内核,Windows 环境下无法使用。在 Linux 上通常通过 pecl 安装:

sudo pecl install inotify
# 安装完成后,在 php.ini 中添加:
# extension=inotify.so

3. PHP 代码怎么写?

效果:死循环运行,监听文件夹,一旦 FTP 完整上传了一张图,它就捕获到路径并输出

<?php
// 1. 初始化 inotify 实例
$fd = inotify_init();

// 2. 添加监听目录(你的 FTP 根目录)
// IN_CLOSE_WRITE 非常重要:表示文件写入完成并关闭,此时读取才完整
$watch_descriptor = inotify_add_watch($fd, ‘/path/to/ftp/images’, IN_CLOSE_WRITE);

echo “正在监听 FTP 目录…\n”;

// 3. 进入无限循环监听
while (true) {
// 读取事件(这一步是阻塞的,没有事件时程序会“休息”,不占 CPU)
$events = inotify_read($fd);

if ($events) {
foreach ($events as $event) {
// $event[‘name’] 就是新上传的文件名
$fileName = $event[‘name’];
$fullPath = “/path/to/ftp/images/” . $fileName;

if (preg_match(‘/\.(jpg|jpeg|png)$/i’, $fileName)) {
echo “检测到新图片: $fullPath \n”;
// — 这里就是以后对接 RabbitMQ 的地方 —
// pushToRabbitMQ($fullPath);
}
}
}
}

// 4. 停止监听(实际运行中基本不会走到这)
inotify_rm_watch($fd, $watch_descriptor);
fclose($fd);

4. 关键点:为什么选 IN_CLOSE_WRITE?

这是很多新手容易踩的坑。

如果监听 IN_CREATE(创建):文件刚创建,内容还是 0KB,PHP 读图会报错。

如果监听 IN_MODIFY(修改):文件传输过程中会触发几十次这个事件,导致重复处理。

IN_CLOSE_WRITE:只有当 FTP 进程把图片写完并关闭了文件句柄时才会触发。这保证了你拿到的图片是 100% 完整的。

避坑指南

子目录问题:标准的 inotify 不支持递归监控子目录。如果你的 FTP 是按照 /camera1/、/camera2/ 这种结构存的,你需要为每个子目录分别调用 inotify_add_watch。

进程守护:这个脚本需要常驻后台运行。建议使用 nohup php script.php & 或者最专业的 Supervisor。

作者 admin

百度广告效果展示