web_dev
@web_dev

Java — WatchService — проверка не занят ли файл другим процессом?

Здравствуйте,

написал небольшой сервис на Java который смотрит на директорию с логами и если в лог что-то дописывается - он реагирует.
Проблема возникает когда пишется лог от nginx, наблюдение ведется также за tomcat и WildFly (на нем и бегает сервис).
AccesDeniedException - эту ошибку я ловлю и обрабатываю, но всё-равно через некоторое время - сервер просто ложиться....

Почему-то только nginx.
Постоянно вот такая ошибка

[0m[0m23:48:21,928 INFO  [com.jdev.logsviewer.listeners.StompDisconnectEvent] (_Watcher_NGINX) Received WatchEvent: 'ENTRY_MODIFY' - for file: access.log
[0m[0m23:48:21,928 INFO  [com.jdev.logsviewer.listeners.StompDisconnectEvent] (_Watcher_NGINX) Received WatchEvent: 'ENTRY_MODIFY' - for file: access.log
[0m[0m23:48:21,928 INFO  [com.jdev.logsviewer.commons.LogsViewerCommonFunctions] (_Watcher_NGINX) Cannot read a file content or file attributes!
[0m[31m23:48:21,929 ERROR [stderr] (_Watcher_NGINX) java.nio.file.AccessDeniedException: /var/log/nginx/access.log
[0m[31m23:48:21,929 ERROR [stderr] (_Watcher_NGINX) 	at sun.nio.fs.UnixException.translateToIOException(UnixException.java:84)
[0m[31m23:48:21,929 ERROR [stderr] (_Watcher_NGINX) 	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
[0m[31m23:48:21,929 ERROR [stderr] (_Watcher_NGINX) 	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
[0m[31m23:48:21,929 ERROR [stderr] (_Watcher_NGINX) 	at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:214)
[0m[31m23:48:21,930 ERROR [stderr] (_Watcher_NGINX) 	at java.nio.file.Files.newByteChannel(Files.java:317)
[0m[31m23:48:21,930 ERROR [stderr] (_Watcher_NGINX) 	at java.nio.file.Files.newByteChannel(Files.java:363)
[0m[31m23:48:21,930 ERROR [stderr] (_Watcher_NGINX) 	at java.nio.file.Files.readAllBytes(Files.java:2981)
[0m[31m23:48:21,930 ERROR [stderr] (_Watcher_NGINX) 	at com.jdev.logsviewer.commons.LogsViewerCommonFunctions.createLog(LogsViewerCommonFunctions.java:48)
[0m[31m23:48:21,930 ERROR [stderr] (_Watcher_NGINX) 	at com.jdev.logsviewer.service.LogsFolderWatcher.run(LogsFolderWatcher.java:58)
[0m[31m23:48:21,930 ERROR [stderr] (_Watcher_NGINX) 	at java.lang.Thread.run(Thread.java:745)


Можно как-то проверять не занят ли файл другим процессом? Когда освободиться тогда и считывать, - становиться в очередь или как-то так... Спасибо за подсказки.
  • Вопрос задан
  • 3140 просмотров
Пригласить эксперта
Ответы на вопрос 1
web_dev
@web_dev Автор вопроса
private void createWatchService(Folder folder) {
		try {
			Path dir = Paths.get(folder.getValue());
			WatchService watcher = FileSystems.getDefault().newWatchService();
			LogsFolderWatcher fileWatcher = new LogsFolderWatcher(watcher, folder, simpMessagingTemplate);
			Thread thread = new Thread(fileWatcher, LogsViewerConstants.WATCHER_PREFIX + folder);
			thread.start();
			logger.info("Added watcher for " + folder + " folder");
			dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}


-------------------------

/**
 * @author JDev
 *
 */
public class LogsFolderWatcher implements Runnable {

	private static final Logger logger = LoggerFactory.getLogger(StompDisconnectEvent.class);

	private WatchService watcher;
	private Folder folderToWatch;
	private SimpMessagingTemplate simpMessagingTemplate;

	public LogsFolderWatcher(WatchService watcher, Folder folderToWatch, SimpMessagingTemplate simpMessagingTemplate) {
		this.watcher = watcher;
		this.folderToWatch = folderToWatch;
		this.simpMessagingTemplate = simpMessagingTemplate;
	}

	/**
	 * In order to implement a file watcher, we loop forever ensuring requesting
	 * to take the next item from the file watchers queue.
	 */
	@SuppressWarnings("rawtypes")
	@Override
	public void run() {
		try {
			// get the first event before looping
			WatchKey key = watcher.take();
			while (!Thread.currentThread().isInterrupted()) {
				// we have a polled event, now we traverse it and
				// receive all the states from it
				for (WatchEvent event : key.pollEvents()) {
					Path dir = (Path) key.watchable();
					Path fullPath = dir.resolve((Path) event.context());

					logger.info("Received WatchEvent: '" + event.kind() + "' - for file: " + event.context().toString());

					Log changedLog = LogsViewerCommonFunctions.createLog(fullPath.toFile(), WatchState.valueOf(event.kind().name()));
					simpMessagingTemplate.convertAndSend("/log/" + folderToWatch, changedLog);
				}
				key.reset();
				key = watcher.take();
			}
		} catch (InterruptedException e) {
			logger.info("Stopping " + Thread.currentThread().getName() + " thread");
		}
	}
}


Хмммм, и как я только что сам заметил - ловлю я ошибку не в том месте, там где я ее ловлю уже слишком поздно она туда не доходит... Как вы думаете если я ее буду ловить в run() - может что-то измениться?

public static Log createLog(File file, WatchState watchState) {

		Path path = Paths.get(file.getPath());
		BasicFileAttributes basicFileAttributes = null;
		Log log = null;
		try {
			basicFileAttributes = Files.getFileAttributeView(path, BasicFileAttributeView.class).readAttributes();

			log = new Log();
			log.setFileName(file.getName());
			log.setCreatedOn(new Date(basicFileAttributes.creationTime().toMillis()));
			log.setModyfiedOn(new Date(basicFileAttributes.lastModifiedTime().toMillis()));
			log.setSize(basicFileAttributes.size());
			log.setWatchState(watchState);
			log.setContent(new String(Files.readAllBytes(path)));
			logger.info("Created Log for file log: " + log.getFileName());

		} catch (Exception exception) {
			if (exception instanceof IOException) {
				logger.info("Cannot read a file " + log.getFileName() + " content or file attributes!");
			} else if (exception instanceof AccessDeniedException) {
				logger.info("The file " + log.getFileName() + " used by another process.");
			}
			exception.printStackTrace();
		}

		return log;
	}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы