You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

pywatchdog与pyinotify无法检测FTP创建目录内的文件变更问题

解决ProFTPD 1.3.5a下pywatchdog/pyinotify监控新创建FTP目录文件事件丢失的问题

我之前踩过类似的监控FTP服务器文件事件的坑,结合你提到的ProFTPD 1.3.5a版本和pywatchdog/pyinotify的表现,大概率是ProFTPD的目录创建机制和Linux inotify的默认行为不兼容导致的,下面给你拆解问题根源和可行的解决办法:

问题根源分析

首先得明确:pywatchdog在Linux平台底层就是基于pyinotify实现的,所以两者出现相同异常,说明问题出在系统或FTP服务层面,而非库本身:

  • inotify的默认限制:inotify默认只监控你初始指定的路径,对后续动态创建的子目录不会自动触发递归监控——哪怕你一开始设置了递归,部分旧内核或特殊场景下也可能失效;
  • ProFTPD的目录创建逻辑:ProFTPD 1.3.5a在通过FTP创建目录时,可能会使用特殊的权限设置或系统调用,导致新目录的inotify监控继承失败;另外,如果监控进程对新创建的目录没有r-x权限,也无法捕获其下的文件事件。

可行解决方案

1. 调整pywatchdog配置,确保递归监控生效

如果你坚持用pywatchdog,一定要在初始化监控时明确开启recursive=True,并且在捕获到目录创建事件时手动补加监控(防止内核递归监控失效):

import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

class FTPMonitorHandler(FileSystemEventHandler):
    def __init__(self, observer):
        self.observer = observer

    def on_created(self, event):
        # 处理文件创建事件
        if not event.is_directory:
            print(f"捕获到新文件: {event.src_path}")
        # 新目录创建时,手动添加监控
        else:
            print(f"捕获到新目录,添加监控: {event.src_path}")
            self.observer.schedule(FTPMonitorHandler(self.observer), event.src_path, recursive=True)

    def on_modified(self, event):
        if not event.is_directory:
            print(f"捕获到文件修改: {event.src_path}")

if __name__ == "__main__":
    ftp_root = "/path/to/ftp/root"
    observer = Observer()
    # 关键:开启recursive=True
    observer.schedule(FTPMonitorHandler(observer), ftp_root, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

2. 修改ProFTPD配置,优化目录权限与行为

打开ProFTPD的主配置文件(通常是/etc/proftpd/proftpd.conf),调整以下配置:

  • 确保目录权限允许监控进程读取:
    Umask 022 022
    DirUmask 022 022
    
  • 禁用UseSendfile(部分场景下会影响文件系统事件触发):
    UseSendfile off
    
  • 限制用户操作目录范围,避免权限交叉:
    DefaultRoot /path/to/ftp/root
    

修改后重启ProFTPD服务:

sudo systemctl restart proftpd

3. 用pyinotify手动实现可靠的递归监控

如果pywatchdog的递归监控还是不稳定,可以直接用pyinotify手动处理目录创建事件,补加监控:

import pyinotify

class FTPMonitorHandler(pyinotify.ProcessEvent):
    def __init__(self, watch_manager):
        self.wm = watch_manager
        # 监控事件类型:创建+修改
        self.mask = pyinotify.IN_CREATE | pyinotify.IN_MODIFY

    def process_IN_CREATE(self, event):
        if event.dir:
            # 新目录创建,添加递归监控
            self.wm.add_watch(event.pathname, self.mask, rec=True)
            print(f"添加新目录监控: {event.pathname}")
        else:
            print(f"捕获到文件创建: {event.pathname}")

    def process_IN_MODIFY(self, event):
        if not event.dir:
            print(f"捕获到文件修改: {event.pathname}")

if __name__ == "__main__":
    ftp_root = "/path/to/ftp/root"
    wm = pyinotify.WatchManager()
    handler = FTPMonitorHandler(wm)
    notifier = pyinotify.Notifier(wm, handler)
    # 初始监控根目录
    wm.add_watch(ftp_root, handler.mask, rec=True)
    notifier.loop()

额外验证步骤

  • 检查监控进程的用户权限,确保它对FTP根目录及其所有子目录拥有r-x权限;
  • 如果出现监控数量超限的错误,调整系统inotify上限:
    echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
    sudo sysctl -p
    
  • 手动在FTP根目录下创建目录并上传文件,验证事件是否被捕获。

内容的提问来源于stack exchange,提问作者Luiz Fernando Schrickte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:14:22