Java WatchService在查看映射驱动器时不生成事件

我实现了一个文件监视器,但我注意到java nio文件观察器不会为映射驱动器上复制的文件生成事件。 例如,我在Unix上运行文件观察器来观察映射到Windows( H:\ )的本地目录( /sharedfolder ),然后我将一个文件放在这个目录中( H:\ )但是文件观察者没有生成任何事件。 现在,如果我在Windows上运行文件观察器来监视映射驱动器( H:\ ),它引用了unix路径( /sharedfolder ),并且从unix我将文件放在此文件夹中,文件监视器识别更改并生成事件。 它看起来像一个bug,或者可能是我错过了一些东西,任何想法?

我有同样的问题试图通过CIFS观看挂载的Windows共享。 似乎无法获取CIFS挂载的文件系统事件 。

Java 7 NIO FileWatcher的linux实现使用inotify 。 Inotify是一个Linux内核子系统,用于注意文件系统更改,这些更改适用于本地目录,但显然不适用于CIFS安装 。

在Oracle,修复此错误似乎不是高优先级。 (这是他们的责任吗?更多的操作系统问题……)

JNotify也在linux系统上使用inotify ,所以这也没有选择。

因此,不幸的是,映射驱动器监控似乎仅限于轮询器:

  • 用于轮询目录的Apache VFS DefaultFileMonitor (已安装的共享)
  • File Poller基于标准Java API。
  • 使用jCIFS的自定义文件轮询器(因此不需要在主机上安装共享)

我可能会尝试Apache VFS Monitor,因为它可以检测文件创建,更新和删除。 它需要挂载共享,但这使操作系统负责CIFS连接而不是我的应用程序。

JDK中的文件监视function取决于平台,因为它使用本机库,因此它在不同平台上的行为可能不同。 我很惊讶它适用于网络驱动器–Windows必须轮询网络映射驱动器以进行更改,而Linux则不然(理所当然,我应该说)。

通常这种监控在OS内核中实现,显然知道哪些文件在本地被修改/创建/等等,但是没有简单的方法让操作系统知道网络驱动器上发生了什么,因为它没有对它的独占控制。

我有同样的问题。 我已经通过在de main类中创建一个新线程并定期触摸文件来解决它,因此会触发一个新的更改事件。

样本每隔10秒轮询dir一次。

 package com.ardevco.files; import java.io.IOException; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.FileTime; import java.util.ArrayList; import java.util.List; public class Touch implements Runnable { private Path touchPath; public Touch(Path touchPath) { this.touchPath = touchPath; this.checkPath = checkPath; } public static void touch(Path file) throws IOException { long timestamp = System.currentTimeMillis(); touch(file, timestamp); } public static void touch(Path file, long timestamp) throws IOException { if (Files.exists(file)) { FileTime ft = FileTime.fromMillis(timestamp); Files.setLastModifiedTime(file, ft); } } List listFiles(Path path) throws IOException { final List files = new ArrayList<>(); try (DirectoryStream stream = Files.newDirectoryStream(path)) { for (Path entry : stream) { if (Files.isDirectory(entry)) { files.addAll(listFiles(entry)); } files.add(entry); } } return files; } @Override public void run() { while (true) { try { for (Path path : listFiles(touchPath)) { touch(path); } } catch (IOException e) { System.out.println("Exception: " + e); } try { Thread.sleep(10000L); } catch (InterruptedException e) { System.out.println("Exception: " + e); } } } } 

我在Python脚本中看到了远程Windows目录上日志文件内容的类似问题。

这是我的答案。

从Unix映射远程驱动器时,在/etc/fstab使用//xxx.xxx.xxx.xxx/shareddrive /media/shareddrive cifs username=xxxx,password=xxxx,**directio** 0 0

您可以使用凭证文件来避免使用纯文本密码。

该命令可能会根据unix版本而改变,这是在debian下测试的。 它应该按预期工作。 你能告诉我它是否有效吗? 我计划在Java中实现相同的东西,所以答案也可能对我有用。

我也碰到了这个并得到了和其他人一样的结论(CIFS + inotify = no go)。

但是,由于我的工作流程依赖于依赖于inotify的远程挂载和自动编译工具,我最终构建了一个(相当绝望和hacky)解决方案,基本上只使用轮询来监视更改,然后再次触摸相同的文件在安装的一面,似乎确实触发了inotify事件。 这不是我最骄傲的时刻。

话虽如此,它确实有用,所以,享受: http : //github.com/rubyruy/watchntouch