Linux 缺少inotify事件(在.git目录中)
我正在使用inotify事件观察文件的更改(实际上,从Python调用libc) 对于git克隆过程中的一些文件,我看到了一些奇怪的事情:我在CREATE事件中看到了一个Linux 缺少inotify事件(在.git目录中),linux,git,docker,libc,inotify,Linux,Git,Docker,Libc,Inotify,我正在使用inotify事件观察文件的更改(实际上,从Python调用libc) 对于git克隆过程中的一些文件,我看到了一些奇怪的事情:我在CREATE事件中看到了一个,我通过ls看到文件有内容,但是,我从来没有在MODIFY中看到,或者在WRITE中看到。这给我带来了一些问题,因为我想对文件中的进行响应:具体来说,就是开始上传文件内容 行为异常的文件位于.git/objects/pack目录中,它们以.pack或.idx结尾。git创建的其他文件在_CREATE->IN _MODIFY->I
,我通过ls
看到文件有内容,但是,我从来没有在MODIFY
中看到,或者在WRITE
中看到。这给我带来了一些问题,因为我想对文件中的进行响应:具体来说,就是开始上传文件内容
行为异常的文件位于.git/objects/pack
目录中,它们以.pack
或.idx
结尾。git创建的其他文件在_CREATE
->IN _MODIFY
->IN _CLOSE _WRITE
链中有一个更规则的(我不关注_OPEN
事件中的)
这是MacOS上的docker内部,但我在远程系统的Linux上的docker上看到了相同的证据,因此我怀疑MacOS方面与此无关。如果监视和git clone在同一个docker容器中,我就会看到这一点
我的问题是:
- 为什么这些文件中缺少这些事件
- 对此我们能做些什么?具体来说,我如何响应对这些文件的写入完成?注:理想情况下,我希望在写作“完成”时做出回应,以避免不必要地(错误地)上传“未完成”的写作
编辑:读起来,我看到的似乎与
- 正在创建、修改和关闭一个名为
tmp\u pack\u hBV4Alz
的单独临时文件李>
- 将创建指向此文件的硬链接,其中包含最终的
.pack
名称李>
- 原始的
tmp\u pack\u hBV4Alz
名称被删除
我想我的问题是,试图使用inotify作为上传文件的触发器,然后我发现.pack
文件是指向另一个文件的硬链接,在这种情况下上传?我可能推测Git在大多数情况下使用原子文件更新,如下所示:
文件的内容被读入内存(并被修改)
修改后的内容将写入一个单独的文件(通常与原始文件位于同一目录中,并具有随机(mktemp
-style)名称)
然后,新文件将被重命名(2)
d-d,而不是原来的文件;此操作保证每个试图使用其名称打开文件的观察者将获得旧内容或新内容
inotify(7)
将此类更新视为移动到事件,因为文件在目录中“重新出现”。基于,我假设基于所使用的协议(即ssh或https),事件中可能存在一些差异
在使用--无硬链接
选项从本地文件系统监视克隆时,您是否观察到了相同的行为
$git克隆git@github.com:user/repo.git
#为新目录设置监视程序
$git克隆--无硬链接回购新回购
您观察到的在linux和Mac主机上运行实验的行为可能消除了这个未解决的问题,但只是增加了一个以防万一的问题。要单独回答您在linux 4.19.95上的git
2.24.1的问题:
- 为什么这些文件中缺少这些事件
您不会在“修改”
/中的“关闭”\u“写入”
事件中看到,因为git clone
将始终尝试对.git/objects
目录下的文件使用硬链接。通过网络或跨文件系统边界进行克隆时,这些事件将再次出现
- 对此可以做些什么?具体来说,我如何对这些文件的写入完成做出响应?注意:理想情况下,我希望在写入“完成”时做出响应,以避免不必要地(错误地)上载“未完成”的写入
为了捕获硬链接的修改,您必须为inotifyCREATE
事件设置一个处理程序,该事件随后发生并跟踪这些链接。请注意,简单的CREATE
也可能意味着创建了一个非空文件。然后,在In\u MODIFY
/In\u CLOSE\u WRITE
中写入您尚未创建的任何文件o在所有链接文件上触发相同的操作。显然,您还必须在DELETE
事件中删除该关系
一种更简单、更健壮的方法可能是定期散列所有文件,并检查文件内容是否已更改
校正
在仔细检查git
源代码并使用strace
运行git
后,我发现git
确实使用内存映射文件,但主要用于阅读内容。因此,我之前的回答是不是正确的答案。不过出于参考目的,我仍然希望在这里保存它:
- 由于使用
mmap
进行文件访问,并且inotify
不报告mmap
已编辑文件的修改,因此在\u MODIFY
事件中看不到
从:
inotifyapi不报告由于mmap(2)、msync(2)和munmap(2)而可能发生的文件访问和修改
还有另一种可能性(来自man inotify):
请注意,事件队列可能会溢出。在这种情况下,事件是
丢失。健壮的应用程序应处理丢失的可能性
事件。例如,可能需要重新生成零件
或者所有的应用程序缓存。(一个简单,但可能)
代价高昂的方法是关闭inotify文件描述符,使其为空
在缓存中,创建一个新的inotify文件描述符,然后重新创建
监视和缓存要监视的对象的条目。)
而
git克隆