2011-12-12 9 views
23

ファイルウォッチャーを実装しましたが、java nioファイルウォッチャーがマップされたドライブにコピーされるファイルのイベントを生成しないことに気付きました。たとえば、Unix上でファイルウォッチャーを実行して、ウィンドウ(H:\)にマッピングされているローカルディレクトリ(/sharedfolder)を見て、このディレクトリにファイルを入れましたが(H:\)、ファイルウォッチャーは任意のイベントを生成しました。今、私がunixパス(/sharedfolder)を参照するマップされたドライブ(H:\)を監視するためにWindows上のファイルウォッチャーを実行し、unixからこのファイルにファイルを置くと、ファイルウォッチャーは変更を識別してイベントを生成します。それはバグのように見える、または私はいくつかのもの、任意の思考が不足しているかもしれません?Java WatchServiceがマップされたドライブを見ている間にイベントを生成しない

答えて

4

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

通常、この種の監視はOS​​カーネルに実装されていますが、これは明らかにファイルがローカルで変更され/作成されるなどの知識がありますが、OSが排他制御を持たないため、その上。

+0

ええ、私が見ているディレクトリは、私がウォッチャーを実行しているマシンと同じです。そのため、転送はネットワークを介して、またはローカルマシン上で行われるため、OSはそのことを認識していなければなりません。ウィンドウがマップされたドライブをポーリングしているのは理にかなっていますが、Unixがローカルフォルダ上のネットワークを介して行われた変更を認識できないことを理解していません。 – Ramcis

+0

@Ramcis:Linuxのネットワーク共有はNFS経由でマウントされ、NFSは設計上、状態レスのプロトコルです。したがって、サーバはどのファイルに何人のクライアントがアクセスしているかを全く知らない。デザインにはいくつかの利点(例えば、オーバーヘッドが少ない)といくつかの欠点があります。 – Robert

1

私は、リモートのWindowsディレクトリ上のログファイルの内容を見ているPythonスクリプトで同様の問題がありました。

ここは私の答えです。

あなたはプレーンテキストでパスワードを避けるために資格情報ファイルを使用することができます/etc/fstab使用//xxx.xxx.xxx.xxx/shareddrive /media/shareddrive cifs username=xxxx,password=xxxx,**directio** 0 0

で、Unixのリモートからドライブをマッピングします。

このコマンドは、unixのバージョンによって変わる可能性があります。これはdebianでテストされています。 これは意図したとおりに動作するはずです。 動作するか教えていただけますか? 私はJavaで同じものを実装する予定ですので、私にとってもその答えが役に立つかもしれません。

+0

これはもうbtwを動作させません。私はそれが多少フレークな方法で(とにかくubuntuで)動作していたと思いますが、最近のアップデート後には全く動作しなくなりました。私は私のひどい回避策を説明する答えを加えました。 – rubyruy

20

CIFS経由でマウントされたWindows共有を監視しようとするのと同じ問題があります。 filesystem events for CIFS mountsを入手できないようです。

Java 7 NIO FileWatcherのLinux実装では、inotifyが使用されます。 InotifyはLinuxカーネルサブシステムで、ファイルシステムの変更がローカルディレクトリには最適ですが、明らかにCIFS mountsではありません。

Oracleでは、this bugを修正することは優先順位が高いようには見えません。 (OSの問題の多くは...)

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

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

  • Apache VFS DefaultFileMonitorディレクトリ(マウント株)の標準Java APIに基づいて
  • ファイルポーラーをポーリングします。それは、ファイルの作成、更新を検出し、外に削除されるためjCIFS
  • カスタムファイルポーラーは、

私はおそらくApacheのVFSモニターを試してみましょう(そうシェアがホストにマウントする必要はありません)ボックス。共有をマウントする必要がありますが、それはOSにCIFS接続の責任であり、私のアプリケーションではありません。

1

私もこの問題に遭遇し、他の人たちと同じ結論に達しました(CIFS + inotify = no go)。

しかし、私のワークフローは、inotifyに依存するリモートマウントと自動コンパイルツールの両方に依存していたため、基本的にポーリングを使用して変更と接触を監視する(かなり厄介な&ハッキー) を実行するマウントされた側で再び同じファイルがinotifyイベントを起動しているようです。それは私の誇りに思う瞬間ではありません。

が楽しむ、それが仕事をして、と言ったので、た:http://github.com/rubyruy/watchntouch

1

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

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

    } 

} 
関連する問題