【问题标题】:Detect mtime resolution of filesystem检测文件系统的 mtime 分辨率
【发布时间】:2012-01-05 00:36:06
【问题描述】:

如何从 Node.js 中找出系统的 mtime 分辨率?

我为什么要问

在 Node.js 中,fs.watch 有时会发出重复的 change 事件。为了避免采取多余的操作,通常使用这样的代码(来自 CoffeeScript 的 coffee 实用程序):

  if event is 'change'
    fs.stat source, (err, stats) ->
      throw err if err
      return if stats.size is prevStats.size and
        stats.mtime.getTime() is prevStats.mtime.getTime()
      prevStats = stats
      ...

问题是:在 OS X 下,由于底层 HFS+ 文件系统,mtime 的分辨率只有 1 秒。也就是说,mtime.getTime() 值的格式为

1322068921000

因此,只要在 1 秒内发生两次更改,第二次更改就有可能不会影响文件的 mtime。感谢stats.size 检查,如果第二次更改对文件大小没有影响,这只是一个问题。不过,这还是个问题。

一个可靠的解决方案是按 mtime 间隔“去抖动”change 事件;即在 OS X 下,当 change 发生时,我将等待 1 秒对其采取行动(从而将可能具有相同 mtime 的所有更改事件组合在一起)。但我想在每个文件系统下将事件延迟尽可能短的时间,而不是采用最大公分母。

【问题讨论】:

    标签: node.js filesystems filemtime


    【解决方案1】:

    迭代某个目录(如/tmp)中的所有文件并执行类似的操作

    files.forEach(function(filename) {
        sum += fs.statSync(filename).mtime % 1000;
    });
    
    if (sum == 0) {
       // supports only 1 second resolution
    } 
    

    有点老套,我知道。

    【讨论】:

    • 我真的希望有一个不涉及 I/O 的解决方案。这是一个图书馆。
    • 也许你可以在库初始化时扫描模块目录,节点无论如何都会扫描、请求和加载它,所以很少的额外 I/O 调用不会产生太大的影响。
    • 我如何确定模块目录包含一组文件,其中包含多个不同的mtimes?
    • 你不能确定,但​​如果文件系统支持毫秒粒度,那么所有文件都不太可能有精确秒的 mtime。
    • 对,只要有几个文件是在不同时间创建的。但是我怎样才能找到这样的目录呢?
    【解决方案2】:

    我在编写一些 Java 代码时遇到了同样的问题。这个问题超越了 Node.js,因为大多数语言在处理文件时都有类似的 API(并且都受到文件系统特定约束的限制)。 Linux 中的其他文件系统也有同样的问题(1s 时间戳粒度),以及适用于 Windows 的旧 FAT32。

    一个 hacky 解决方案是在您读取文件(或发送文件事件)之前将文件的 mtime 设置回一秒。这样,如果在同一个粒度窗口(本例中为 1s)内发生了另一次修改,新的 mtime 将不同,您将能够检测到修改。

    如果没有其他应用程序正在使用该文件的 mtime,这应该可以正常工作,否则很可能会干扰它们的操作。实际上,这是一种解决方法,不是正确的解决方案。不过,我发现它在某些场景中很有用,例如,对于我的 Java 代码的自动化测试(测试会快速连续地修改文件,比实际使用中自然发生的要多)。

    【讨论】:

      猜你喜欢
      • 2014-09-08
      • 1970-01-01
      • 2017-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多