缺少 inotify 事件 (在。Git 目录

共5个回答,已解决, 标签: linux git docker libc inotify

我正在观察文件使用 inotify 事件的变化 (因为它发生,从 Python,调用 libc)。

对于一些文件在git clone, I see something odd: I see an IN_CREATE event, and I see via ls that the file has content, however, I never see IN_MODIFY or IN_CLOSE_WRITE. This is causing me issues since I would like to respond to IN_CLOSE_WRITE关于文件: 具体来说,要启动文件内容的上传。

行为古怪的文件在.git/objects/pack directory, and they end in .pack or .idx. Other files that git creates have a more regular IN_CREATE -> IN_MODIFY -> IN_CLOSE_WRITE chain (I'm not watching for IN_OPEN事件)。

这是在 MacOS 上的 docker 内部,但是我在远程系统的 Linux 上的 docker 上看到了同样的证据,所以我怀疑 MacOS 方面无关紧要。我看到这个,如果看着git clone都在_相同_Docker 容器。

我的问题:

  • 为什么这些文件上缺少这些事件?

  • 对此可以做些什么?具体来说,我如何应对这些文件的写入完成?注意: 理想情况下,我想在写作 “完成” 时做出回应,以避免不必要地/(错误地) 上传 “未完成” 的写作。


编辑: 阅读Https://developer.ibm.com/tutorials/ l-inotify/看起来我看到的是一致的

  • 一个单独的临时文件,名字像tmp_pack_hBV4Alz,正在创建、修改和关闭;
  • a硬的链接到此文件,最终.pack名称;
  • 原始的tmp_pack_hBV4Alz名称被删除。

我认为我的问题是试图使用 inotify 作为上传文件的触发器,然后减少到注意到.pack文件是到另一个文件的硬链接,在这种情况下上传?

第1个答案(采用)
    To answer your question separately for git 2.24.1 on Linux 4.19.95:
  • 为什么这些文件上缺少这些事件?

你看不到IN_MODIFY/IN_CLOSE_WRITE events because git clone will always try to use hard links for files under the .git/objects目录。当通过网络或跨文件系统边界进行克隆时,这些事件将再次出现。

  • 对此可以做些什么?具体来说,我如何应对这些文件的写入完成?注意: 理想情况下,我想在写作 “完成” 时做出回应,以避免不必要地/(错误地) 上传 “未完成” 的写作。

为了捕捉硬链接的修改,你必须为 inotify 设置一个处理程序。CREATE event which follows and keeps track of those links. Please note that a simple CREATE can also mean that a nonempty file was created. Then, on IN_MODIFY/IN_CLOSE_WRITE to any of the files you have to trigger the same action on all linked files as well. Obviously you also have to remove that relationship on the DELETE事件。

一个更简单、更健壮的方法可能是定期散列所有文件,并检查文件的内容是否发生了变化。


校正

检查后git source code closely and running git with strace, I found that git does use memory mapped files, but mostly for reading content. See the usage of xmmap which is always called with PROT_READ只有。。因此,我之前的答案如下:正确答案。然而,为了提供信息,我仍然想把它留在这里:

  • 你看不到IN_MODIFY events because packfile.c uses mmap for file access and inotify does not report modifications for mmapEd 文件。

    Inotify 手册页:

    Inotify API 不报告由于 mmap (2) 、 msync (2) 和 munmap (2) 而可能发生的文件访问和修改。

第2个答案
    I may speculate that Git most of the time uses atomic file updates which are done like this:
  1. 文件的内容被读入内存 (并被修改)。
  2. 修改后的内容被写入一个单独的文件 (通常位于与原始目录相同的目录中,并且具有随机化 (mktemp-风格) 名称。
  3. 然后是新文件rename(2)D-d 超过原来的; 这个操作保证了每个试图用它的名字打开文件的观察者会得到旧的或新的内容。

这样的更新被看到inotify(7) as moved_to事件-由于文件在目录中 “重新出现”。

第3个答案
    Based on this accepted answer I'd assume there might be some difference in the events based on the protocol being used (i.e. ssh or https).

Do you observe the same behavior when monitoring cloning from the local filesystem with the --no-hardlinks选项?

$ Git 克隆 git@github.com: user/repo.git
# 为新目录设置观察程序
$ Git 克隆-无硬链接回购新回购

您在 linux 和 Mac 主机上运行实验时观察到的行为可能消除了导致此开放性问题的原因Mac/issues/896 的 https://github.com/docker/但是只添加 incase。

第4个答案
    There is another possibility (from man inotify):

请注意,事件队列可能会溢出。在这种情况下,事件是 迷路了。强大的应用程序应该处理丢失的可能性 事件优雅。例如,可能需要重建零件 或所有应用程序缓存。(一个简单,但可能 昂贵,方法是关闭 inotify 文件描述符,空 缓存,创建一个新的 inotify 文件描述符,然后重新创建 监视对象的监视和缓存条目。)

git clone会产生沉重的事件流,这可能会发生。

如何避免这种情况:

  1. 增加读取缓冲区,尝试 fcntl (F_SETPIPE_SZ) (这种方法是猜测,我从来没有尝试过)。
  2. 在专用线程中将事件读入大缓冲区,在另一个线程中处理事件。
第5个答案
    Maybe you made the same mistake I made years ago.  I've only used inotify twice.  The first time, my code simply worked.  Later, I no longer had that source and started again, but this time, I was missing events and did not know why.

事实证明,当我阅读一个事件时,我真的是在阅读一小批事件。我解析了我所期望的那个,认为就是它,仅此而已。最终,我发现接收到的数据还有更多,当我添加一个小代码来解析从一次读取中接收到的所有事件时,没有更多的事件丢失。

相关问题

UTF-8 一路通过 错误: TCP 提供程序: 错误代码 0x2746。在 linux 下通过终端进行 Sql 设置时 为什么是统计:: st _ size 0 为设备, 但同时 lseek 正确地定义了设备大小? 如何避免在源代码中保留版本号? 为什么 “git 状态” 显示我在主分支上,而 “git 分支” 不显示? 缺少 inotify 事件 (在。Git 目录 MSBuild 未处理异常: 除非设置了 UseShellExecute,否则 FileName 属性不应是目录 如何解决 Alpine docker 容器内烧瓶应用 Gunicorn exec 上提出的 “oserror: libc 未找到” 为什么 _ _ libc_start_main 的地址在 GDB 内总是相同的,即使 ASLR 打开?