inotify 报告变化,但不是完整历史记录
inotify 通过一个带注册监视项和可读事件队列的实例,投递 Linux 文件系统通知。每条记录包含监视编号、事件掩码,也可能包含名字和移动 cookie。这能减少对未变化路径的反复检查,但事件流不是无限审计日志。正确消费者应把通知理解为相关状态可能需要重新检查的证据,而不能默认它保存了文件发生过的每一次操作。 通知是有边界的变化证据。覆盖范围、对象替换与队列丢失,都要求重新核对文件系统当前状态;重扫不能补回缺失的事件历史。 坏掉的样子 监视目录不会递归监视后代。它报告直接目录项上的相关活动,因此需要观察更深变化时,新子目录也需要独立监视。目录树监视器必须处理初次枚举和之后加入的目录。假定只注册根目录就覆盖整棵树,会悄悄漏掉更深层变化;能收到子目录被创建,并不代表能收到它内部之后的全部操作。 文件监视跟随具体对象,不会永久绑定路径。编辑器可以先写完并关闭临时文件,再用 rename 替换目标。父目录会报告替换,旧文件监视却不会转移到新 inode。如果消费者等待目标名字之后再出现 close-write,可能永远等不到,因为替代文件在发布前已经关闭。不能把一种编辑器保存顺序当成所有更新方式的固定流程。 连续产生且尚未读取的相同事件可以合并,队列满后会丢弃事件并报告 IN_Q_OVERFLOW。因此,事件数量不是可靠写入计数。溢出后,消费者无法仅靠剩余记录重建全部缺失操作,必须重新核对当前监视状态,不能继续假定根据事件维护的模型完整。历史丢失与当前状态仍可读取,是需要分别理解的两件事。 快速验证 把脚本保存为 inotify-events.py,在一次性 Linux 环境中运行 python3 inotify-events.py。此前记录使用 Linux 6.12.76 和 ext4;2026-10-15 的复核记录了两种语言样本在 Linux 6.18.44、Python 3.12.14 上通过。该记录属于历史执行,此次未重跑。样本创建 ASCII 名称的临时条目,并有意填满自己的队列。配置的队列上限必须不超过三万二千七百六十八;脚本只读取上限,不修改任何 sysctl: ...