守望者可以发送文件更改的原因吗?

bno*_*afk 3 watchman

watchman 是否能够发布到配置的命令,为什么它向该命令发送文件?

例如:

  1. 文件夹中的新文件可能是 FILE_CREATE 标志;
  2. 被删除的文件将向命令发送 FILE_DELETE 标志;
  3. 修改后的文件将发送 FILE_MOD 标志等。
  4. 也许即使当一个文件夹被删除(及其下的文件)时,也会发送一个命名该文件夹的 FOLDER_DELETE 参数,以及一个 FILE_DELETE 到其下的文件/ FOLDER_DELETE 到其下的文件夹

有这样的事吗?

Wez*_*ong 5

不,它不能那样做。其原因对于其设计来说非常重要。总而言之,客户端正确处理这些单独的事件比您想象的要复杂得多,而且几乎在所有情况下您并不真正想要它们。

大多数文件监视系统都是抽象的,只是将系统特定的通知信息转换为某种通用形式。他们不能很好地处理通知队列溢出的情况,也不能为客户提供可靠地响应这种情况的方法。

除此之外,文件系统可能会在很短的时间内受到来自多个并发线程或进程的许多不同的更改。这使得该区域极易出现难以管理的TOCTOU问题。例如,创建和写入文件通常会产生一系列有关该文件及其包含目录的通知。如果该文件在此序列之后立即被删除(可能它是构建步骤中的中间文件),那么当您看到有关文件创建的通知时,它很可能已经被删除。

Watchman 获取通知的输入流并将其输入文件系统的内部模型:观察到的文件的有序列表。每次收到通知时,监视程序都会将其视为一个信号,表明它应该查看报告为已更改的文件,然后将该文件的条目移至有序列表的最新末尾。

当您向 Watchman 询问有关文件系统的信息时,可能甚至可能仍然存在来自内核的待处理通知。为了最小化 TOCTOU 并确保其状态是最新的,watchman 会生成一个同步 cookie并等待该通知可见,然后再响应您的查询。

上述两件事的结合意味着守望者结果数据有两个重要的属性:

  1. 您保证已观察到查询之前发生的所有通知
  2. 您在查询结果中仅收到一次任何给定文件的最新信息(更改结果合并在一起)

我们来谈谈溢出的情况。如果您的系统无法跟上文件更改的速度(例如:您有一个大项目并且非常快速地创建和删除文件并且系统负载很重),则操作系统无法容纳所有待处理的文件分配给手表的缓冲区资源中的通知。当这种情况发生时,它会耗尽这些缓冲区并发送溢出信号。这意味着监视 API 的客户端错过了一些事件,并且不再与文件系统的状态同步。如果该客户端维护有关文件系统的状态,则它不再有效。

Watchman 通过重新检查受监视的树并将所有文件综合标记为已更改来解决这种情况。这会导致客户端的下一个查询看到树中的所有内容。我们将其称为新实例结果集,因为它与您第一次查询时获得的视图相同。我们在结果中设置一个标志,以便客户端知道这种情况已经发生,并可以采取适当的步骤来修复自己的状态。您可以通过查询参数配置此行为。

在这些新的实例结果集中,我们不知道任何给定的文件是否真的发生了变化(它的变化方式可能是我们无法通过 检测到的lstat),即使我们可以看到它的元数据发生了变化,我们不知道这种变化的原因。

可能有多个事件导致给定文件出现在 watchman 提供的结果中。我们不会单独记录它们,因为我们无法用无限的历史来追踪它们;想象一个文件全天每秒增量写入一次。我们是否每天保留 86400 个变更条目并将其交付给我们的客户?如果有几十万个这样的文件怎么办?我们必须截断该数据,此时数据的丢失会降低您对其进行推理的能力。

最后,客户端很少会做比尝试读取文件或查看其元数据更多的事情,一般来说,他们只想在文件停止更改时才这样做。对于此用例,watchman-wait、watchman-make和trigger都具有稳定周期的概念,这会导致更改通知延迟传递,直到文件系统停止更改之后。