31

ファイル ウォッチャーを実装しましたが、Java nio ファイル ウォッチャーが、マップされたドライブにコピーされているファイルのイベントを生成しないことに気付きました。たとえば、Unix でファイル ウォッチャーを実行して、/sharedfolderWindows ( ) にマップされているローカル ディレクトリ ( ) を監視しH:\、このディレクトリ ( H:\) にファイルを配置しましたが、ファイル ウォッチャーはイベントを生成しませんでした。 . ここで、Windows でファイル ウォッチャーを実行しH:\て、UNIX パス ( /sharedfolder) を参照するマップされたドライブ ( ) を監視し、Unix からこのフォルダーにファイルを配置すると、ファイル ウォッチャーは変更を識別し、イベントを生成します。バグのように見えますか、何かが足りないのではないでしょうか?

4

5 に答える 5

30

マウントされた Windows 共有を CIFS 経由で監視しようとすると、同じ問題が発生します。CIFS マウントのファイルシステム イベントを取得できないようです。

Java 7 NIO FileWatcher の Linux 実装はinotifyを使用します。inotify は、ファイルシステムの変更を通知するための Linux カーネル サブシステムであり、ローカル ディレクトリでは完璧に機能しますが、明らかにCIFS マウントでは機能しません。

オラクルでは、このバグを修正する優先度は高くないようです。(それは彼らの責任ですか?OSの問題の詳細...)

JNotifyは Linux システムでもinotifyを使用するため、これもオプションではありません。

残念ながら、マップされたドライブの監視はポーラーに限定されているようです。

ファイルの作成、更新、削除をすぐに検出できるので、おそらく Apache VFS Monitor を試してみます。共有をマウントする必要がありますが、それにより、OS はアプリケーションではなく CIFS 接続の責任を負います。

于 2012-09-19T12:18:28.937 に答える
4

JDK のファイル監視機能は、ネイティブ ライブラリを使用するため、プラットフォームに依存するため、異なるプラットフォームでは異なる動作をする可能性があります。ネットワークドライブでまったく機能することに驚いています-Windowsはネットワークにマップされたドライブに変更をポーリングする必要がありますが、Linuxはそうではありません(当然のことです)。

通常、この種の監視は OS カーネルに実装されており、どのファイルがローカルで変更/作成/などされているかを明らかに知っていますが、ネットワーク ドライブを排他的に制御できないため、OS がネットワーク ドライブで何が起こっているかを知る簡単な方法はありません。

于 2011-12-12T15:33:00.053 に答える
3

私も同じ問題を抱えていました。メインクラスに新しいスレッドを作成し、定期的にファイルに触れて、新しい変更イベントが発生するようにすることで解決しました。

サンプルは、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);
            }
        }

    }

}
于 2015-05-01T10:24:35.933 に答える
1

私もこれに遭遇し、ここにいる他のみんなと同じ結論に達しました (CIFS + inotify = no go)。

しかし、私のワークフローはたまたま inotify に依存するリモート マウントと自動コンパイル ツールの両方に依存していたため、基本的にポーリングを使用して変更を監視し、同じファイルに再度アクセスする (かなり絶望的でハックな) ソリューションを構築することになりました。マウントされた側で、inotify イベントを発生させているようです。それは私の最も誇りに思う瞬間ではありません。

そうは言っても、うまくいくので、楽しんでください:http://github.com/rubyruy/watchntouch

于 2013-05-05T03:51:16.403 に答える
1

リモートの Windows ディレクトリにあるログ ファイルの内容を監視する Python スクリプトで同様の問題が発生しました。

これが私の答えです。

Unix からリモートドライブをマッピングする場合は/etc/fstab//xxx.xxx.xxx.xxx/shareddrive /media/shareddrive cifs username=xxxx,password=xxxx,**directio** 0 0

資格情報ファイルを使用して、パスワードがプレーン テキストにならないようにすることができます。

コマンドは、UNIX のバージョンによって異なる可能性があります。これは、debian でテストされています。意図したとおりに動作するはずです。それが機能するかどうか教えてもらえますか? 私はJavaで同じものを実装することを計画しているので、答えは私にも役立つかもしれません.

于 2012-09-19T10:29:08.103 に答える