Java WatchService在监视映射驱动器时不生成事件



我实现了一个文件监视器,但我注意到java nio文件监视器不会为映射驱动器上复制的文件生成事件。例如,我在Unix上运行文件监视器来监视映射到windows (H:)上的本地目录(/sharedfolder),然后我在该目录(H:)中放置了一个文件,但是文件监视器没有生成任何事件。现在,如果我在windows上运行文件监视程序来监视指向unix路径(/sharedfolder)的映射驱动器(H:),并在unix中将一个文件放入该文件夹,则文件监视程序将识别更改并生成事件。它看起来像一个bug,或者我可能遗漏了什么,你有什么想法吗?

我有同样的问题,试图通过CIFS观看挂载的windows共享。获取CIFS挂载的文件系统事件似乎是不可能的。

Java 7 NIO FileWatcher的linux实现使用通知。Inotify是一个linux内核子系统,用于注意文件系统的更改,它适用于本地目录,但显然不适用于CIFS挂载。

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

JNotify在linux系统上也使用inotify,所以这也不是一个选项。

所以映射驱动器的监控似乎仅限于轮询器:

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

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

JDK中的文件监视功能依赖于平台,因为它使用本机库,因此它在不同的平台上可能表现不同。我很惊讶它能在所有网络驱动器上工作——Windows必须轮询网络映射驱动器的变化,而Linux却不能(我应该说,这是正确的)。

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

我也遇到了同样的问题。我通过在main类中创建一个新线程并定期触摸文件来解决这个问题,以便触发一个新的更改事件。

示例每10秒轮询一次目录。

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<Path> listFiles(Path path) throws IOException {
        final List<Path> files = new ArrayList<>();
        try (DirectoryStream<Path> 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)解决方案,基本上只是使用轮询来监视更改,然后在挂载的一侧再次接触相同的文件,这似乎会触发通知事件。这不是我最骄傲的时刻。

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

相关内容

  • 没有找到相关文章

最新更新