Подтвердить что ты не робот

Java WatchService не генерирует события во время просмотра подключенных дисков

Я реализовал наблюдатель файлов, но заметил, что просмотрщик файлов java nio не генерирует события для копирования файлов на сопоставленные диски. Например, я запустил наблюдателя файлов в Unix для просмотра локального каталога (/sharedfolder), который отображается в окнах (H:\), а затем я поместил файл в этот каталог (H:\), но наблюдатель не генерировал никакого события. Теперь, если я запускаю наблюдателя файлов в окнах, чтобы отслеживать подключенный диск (H:\), который ссылается на путь unix (/sharedfolder), а из unix я помещаю файл в эту папку, наблюдатель файла идентифицирует изменение и генерирует мероприятие. Это похоже на ошибку, или может быть, я что-то пропустил, какие-то мысли?

4b9b3361

Ответ 1

У меня та же проблема, когда я пытаюсь посмотреть, как установлен общий доступ к Windows через CIFS. Кажется, невозможно получить события файловой системы для монтирования CIFS.

В Linux-реализации NIO FileWatcher для Linux используется inotify. Inotify - это подсистема ядра Linux, которая замечает изменения файловой системы, которая отлично работает для локальных каталогов, но, очевидно, не для монтирования CIFS.

В Oracle, похоже, не является высоким приоритетом исправление этой ошибки. (Это их ответственность? Больше проблем с ОС...)

JNotify также использует inotify в системах Linux, так что это тоже не вариант.

Таким образом, мониторинг подключенных дисков, к сожалению, ограничивается опросами:

  • Apache VFS DefaultFileMonitor для опроса каталогов (смонтированный общий ресурс)
  • File Poller на основе стандартного Java API.
  • Пользовательский файл Poller с jCIFS (поэтому общий ресурс не нужно монтировать на хосте)

Я, наверное, попробую Apache VFS Monitor, потому что он обнаруживает создание файлов, обновления и удаление из коробки. Требуется смонтировать общий ресурс, но это дает ОС ответственность за соединения CIFS, а не мое приложение.

Ответ 2

Функция просмотра файлов в JDK зависит от платформы, поскольку она использует собственные библиотеки, чтобы она могла вести себя по-разному на разных платформах. Я удивлен, что он работает на сетевых дисках вообще - Windows должна опросить подключенные к сети диски для изменений, в то время как Linux не делает (по праву, поэтому я должен сказать).

Обычно такой мониторинг выполняется в ядре ОС, который, очевидно, имеет знания о том, какие файлы были изменены/созданы локально, но нет никаких простых способов для ОС знать, что происходит на сетевом диске, поскольку оно не имеет исключительного контроля над он.

Ответ 3

У меня была та же проблема. Я решил это, создав новый поток в главном классе и периодически касаясь файлов, чтобы сработало новое событие изменения.

Пример опроса dir на каждые 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);
            }
        }

    }

}

Ответ 4

У меня были аналогичные проблемы с Python script просмотр содержимого файла журнала в удаленной директории Windows.

Вот мой ответ.

При сопоставлении удаленного диска с Unix в /etc/fstab используйте //xxx.xxx.xxx.xxx/shareddrive /media/shareddrive cifs username=xxxx,password=xxxx,**directio** 0 0

Вы можете использовать файл учетных данных, чтобы избежать использования пароля в виде обычного текста.

Команда может меняться в зависимости от версии unix, это было проверено под debian. Он должен работать по назначению. Можете ли вы сказать мне, работает ли это? Я планирую реализовать один и тот же материал на Java, поэтому ответ может быть полезен и мне.

Ответ 5

Я тоже столкнулся с этим и пришел к такому же выводу, что и все остальные (CIFS + inotify = no go).

Однако, поскольку мой рабочий процесс зависел как от удаленных монтировок, так и от инструментов автоматической компиляции, которые полагаются на inotify, я закончил создание (довольно отчаянное и хакерское) решение, которое в основном просто использует опрос, чтобы следить за изменениями, а затем затрагивает те же файлы снова на смонтированной стороне, которая, похоже, запускает события inotify. Это не мой самый гордый момент.

Сказав это, он работает, поэтому наслаждайтесь: http://github.com/rubyruy/watchntouch