跳转至主要内容

故障排除

我们尝试在 Watchman 错误诊断中给出针对性的建议,这意味着当我们有足够的信息时,我们会显示一个指向此页面上某个章节的链接,其中包含一些上下文和建议。有些操作系统提供的诊断信息比其他操作系统更丰富,因此在某些情况下,我们不得不求助于更通用的建议。

最常见的问题原因是达到系统资源限制。文件系统监视可用的资源是有限的,当超出这些资源时,在最好的情况下会影响性能,在最坏的情况下会阻止正确操作。

确保您使用的是最佳可用版本

通常,确保您使用的是最新版本的软件是个好主意,这样可以避免任何已知问题。

如果您运行的是操作系统分发系统提供的预构建二进制文件,则您可能需要从源代码构建最新版本。您可以在安装部分中找到相关说明。

重新爬取

重新爬取是 Watchman 执行的操作,以便从它认为已经与文件系统状态失去同步的情况中恢复。

重新爬取的最常见原因是 Linux 系统上的默认 inotify 限制设置得非常小。这意味着您的监视根目录生成更改的速率高于内核可以缓冲并中继到 watchman 服务的速率。发生这种情况时,内核会检测到溢出并发出 IN_Q_OVERFLOW 信号。恢复方法是递归扫描根目录以确保我们知道实际存在的内容,并与通知流重新同步。

频繁的重新爬取是不希望出现的,因为它们会导致潜在的昂贵的完整树爬取,这会将所有文件标记为已更改,并将此状态传播给客户端,客户端将依次对大多数文件的(可能是错误的)更改状态执行某些操作。

避免重新爬取

没有简单的公式来设置您的系统限制;越大越好,但代价是内核内存来维护缓冲区。您和/或您的系统管理员应查看您系统的工作负载以及特定于系统的准备文档,并相应地提高您的限制。

kFSEventStreamEventFlagUserDropped

macOS 也有类似的内部限制和行为,当超过该限制时。如果您遇到类似的消息

Recrawled this watch 1 times, most recently because:
/some/path: kFSEventStreamEventFlagUserDropped

那么您就达到了系统的限制。无法直接控制该限制,但从 Watchman 3.2 开始,您可以增加 .watchmanconfig 文件中的 fsevents_latency 参数。

我已经更改了限制,如何清除警告?

该警告将一直存在,直到您取消监视并重新启用它,或重新启动 watchman 进程。最简单的解决方法是运行 watchman shutdown-server 并在您的下一个 watchman 查询中重新建立您的监视。

日志在哪里?

Watchman 将日志放在名为 <STATEDIR>/<USER>.log 的文件中,其中 STATEDIR 是在您构建 watchman 时设置的。

如果您使用了 --enable-statedir=<STATEDIR> 配置选项,那么该位置将保存您的日志。如果不是,STATEDIR 的默认值为 <PREFIX>/var/run/watchman,或者对于较旧版本的 watchman,日志可能会放在 <TMPDIR>/.watchman.<USER>.log 中。

自从 3.8.

Watchman 将日志放在名为 <STATEDIR>/log 的文件中,该位置通常类似于 <PREFIX>/var/run/watchman/<USER>-state/log。如果您运行的是 homebrew 构建的 watchman,则 <PREFIX> 通常是 /usr/local

默认日志位置可以通过 --logfile 服务器选项 覆盖。

关于默认位置的快速说明解释了 <STATEDIR><TMPDIR><USER> 等的含义。

中毒:inotify_add_watch

A non-recoverable condition has triggered.  Watchman needs your help!
The triggering condition was at timestamp=1407695600: inotify-add-watch(/my/path) -> Cannot allocate memory
All requests will continue to fail with this message until you resolve
the underlying problem. You will find more information on fixing this at
https://fbdocs.cn/watchman/docs/troubleshooting.html#poison-inotify-add-watch

如果您遇到此状态,则意味着您的*内核*无法监视您要求它监视的一个或多个根目录中的目录。Watchman 认为此特定条件是不可恢复的,原因是 Watchman 服务可以执行的任何操作都无法保证根本原因已解决,并且当系统处于此状态时,Watchman 无法保证它可以响应其客户端所依赖的正确结果。我们认为自己中毒了,并将拒绝所有监视的所有请求(不仅仅是触发它的监视),直到重新启动该过程。

有两个主要原因可以触发此情况

  • 达到了 inotify 监视总数的用户限制,或者内核无法分配所需的资源
  • 可用的内核内存不足

前者的解决方案是重新访问特定于系统的准备文档,并相应地提高您的限制。

后一种情况意味着您的工作负载超出了机器上可用的 RAM。很难在此处给出解决此条件的具体建议;您或许可以降低其他系统限制以释放一些资源,或者您可能只需要在系统中安装更多 RAM。

我已经更改了限制,如何清除错误?

该错误将一直存在,直到您重新启动 watchman 进程。最简单的解决方法是

自从 4.6

$ watchman watch-del-all
$ watchman shutdown-server

在 4.6 之前

$ rm <STATEDIR>/state       # see above for what STATEDIR means
$ watchman --no-spawn --no-local shutdown-server

如果您实际上尚未解决根本原因,则每次系统超出这些限制时,您可能会继续触发并遇到此状态。

中毒:opendir

A non-recoverable condition has triggered.  Watchman needs your help!
The triggering condition was at timestamp=1407695600: opendir(/my/path) -> Too many open files in system
All requests will continue to fail with this message until you resolve
the underlying problem. You will find more information on fixing this at
https://fbdocs.cn/watchman/docs/troubleshooting.html#opendir

如果您遇到此状态,则意味着您的整个系统打开的文件太多,这阻止了 watchman 跟踪系统上的更改。在这种情况下,该错误与文件系统监视无关,而是与系统上其他(可能)行为不端的进程有关;它通常表明失控的程序或一组程序正在消耗资源,但在某些情况下,可能只是您的系统工作负载要求您增加系统文件数量的限制。

我该如何解决此问题?

请按照以下指示进行操作

如果问题仍然存在,请咨询您的系统管理员,以确定是什么在消耗这些资源并对其进行修复,或者增加您的系统限制。

FSEvents

FSEvents 是 macOS 上的文件监视工具。几乎没有诊断可以帮助诊断 FSEvents 的问题;该 API 本身在许多错误情况下几乎不提供反馈,而是向日志文件发出相当神秘的错误消息。

如果您因为错误消息告诉您阅读本节而来到这里,它还会要求您查看您的日志文件。如果您使用的是旧版本的 watchman 并且遇到错误消息 FSEventStreamStart failed,那么您应该找到您的日志文件(请参阅上面的日志在哪里?)并查找提及 FSEvents 的行,然后参考下面的信息。

FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21)

除了 Apple 之外,没有人确定这到底是什么意思,但它表明 fsevents 服务已进入不良状态。可能的原因包括

  • 事件流客户端太多
  • 一个或多个事件流客户端已进入不良状态,并且以某种方式影响了 fsevents 服务

要解决此问题,您可能希望尝试以下操作,这些操作的侵入性越来越强

  • 避免在同一文件系统树中建立多个重叠的监视,尤其是在大型树中。我们建议仅监视项目或存储库的根目录,而不监视该树中的子树。具有大型树的组织可能希望部署 root_restrict_files 配置选项,以便 watchman 仅允许监视项目根目录。
  • 关闭或重新启动其他正在使用 fsevents 的应用程序。一些例子是
  • 编辑器,例如 Sublime Text 和 TextMate。
  • 许多 nodejs 包和 Grunt 样式的工作流程都使用 fsevents。确保您将 nodejs 升级到至少 v0.11.14 版本。如果可能,请将您的 nodejs 包配置为使用 sanefb-watchman 进行文件监视,因为这会将 fsevents 监视的数量整合到仅由 watchman 维护的集合中。
  • 重新启动 fsevents 服务:sudo pkill -9 -x fseventsd
  • 重新启动您的计算机

触发器/订阅在 macOS 上不起作用

存在一个罕见的 fsevents 错误,该错误可以阻止内核中目录名称的大小写不一致的目录中的任何通知工作。

您可以通过按照 find-fsevents-bugs 工具的说明来测试是否发生了这种情况。

如果发生了这种情况,解决方案是重命名该工具突出显示的目录。

您可以在以下资源中阅读有关此问题的更多信息

ReactNative:监视器加载时间过长

存在一个问题,该问题是 umask 影响 launchd plist 文件的权限的结果,Watchman 使用该文件在 OS X 上设置您的 watchman 服务。此问题已在 Watchman 3.1 版本中得到解决。

更新

$ watchman shutdown-server
$ brew update
$ brew reinstall watchman