【问题标题】:How can I follow a file like "Tail -f" does in Java without holding the file open (Prevent rename/delete)如何在不保持文件打开的情况下跟踪 Java 中的“Tail -f”之类的文件(防止重命名/删除)
【发布时间】:2013-01-30 17:59:28
【问题描述】:

我想在 Java 应用程序中“拖尾 -f”很多日志文件。

我已经通过监视大小和上次更新并在文件大小或上次更新时间发生变化时重复打开文件并读取最后几个字节来实现此功能 - 然后立即关闭它。

这似乎有问题,因为当记录器决定重命名文件时我可能会打开它,这会导致某种问题。

我还想用一种比注意到文件大小减小的机制更可靠地检测“滚动”文件......似乎容易出错但不太可能。

由于我似乎无法访问文件描述符或其他低级文件实用程序,因此我可能无法重现 tail 的行为——但是在不“锁定”文件进行重命名的情况下读取文件是否有任何技巧/删除(Windows 7)

我想另一种可能性是实际产生一个 tail -f 进程并读取进程输出,但这似乎有点重——我在这里扫描了 60 个日志文件,其中一些有很多输出(大多数将是闲置)。

【问题讨论】:

  • 如果您使用的是 JDK 7,您可以使用 java.nio.file.WatchService.poll() 轮询文件。
  • 课堂真整洁!我认为这将解决检测截断的问题,但我仍然有必须打开文件并阅读文本的问题(尽管它也可能让我这样做......我将不得不更仔细地查看)。谢谢
  • 我失去了你。哪个操作系统?Windows 还是 Linux?
  • Windows 7,也许我在 git 中使用“Tail”这一事实让你失望了?

标签: java file tail logfile


【解决方案1】:

Apache Commons 有一个Tailer class,这可以满足您的需求吗?如果可以,它具有滚动检测机制以及阅读内容,因此您将获得所需的一切。

如果不能做到这一点,可能是纯 java 没有办法做到这一点。您需要一些帮助,例如 C 代码,使用带有 SH_DENYNO 参数的 fopen 允许在 Windows 上共享打开。或者然后通过executing a system command 调用尾部实现。

但是由于打开日志文件的代码是导致锁定它的代码,即使这样也可能无济于事。在这种情况下,唯一真正的选择是更改日志记录的工作方式,因为这是锁定文件的罪魁祸首。 Log4j 可以使用SocketAppender 等。

【讨论】:

  • Tailer 类看起来棒极了。我们目前没有使用这部分公地,但值得加入!
【解决方案2】:

使用 apache.commons.io

这是一个简单的例子

public class LogTailTest {

/**
* TailerListener implementation.
*/
static public class ShowLinesListener extends TailerListenerAdapter {
    @Override
    public void handle(String line) {
        System.out.println(line);
    }
}

public static void main(String args[]) {

    TailerListener listener  = new ShowLinesListener();
    File file = new File("./test.log");

    Tailer tailer = new Tailer(file, listener, 1000);
    tailer.run();

    try {
        Thread.sleep(100000);
    } catch(InterruptedException ex) {
        Thread.currentThread().interrupt();
    }

    tailer.stop();
}

}

【讨论】:

  • tailer.run() 块,所以你永远不会到达它后面的行。需要在单独的线程中运行 Tailer。
【解决方案3】:

在 Linux 中你不会有问题,因为锁定只是 advisory。但在Windows 情况有所不同。
这应该取决于您的记录器(我假设是 log4j)打开要记录的文件的模式。
在这个answer 中查找C# 似乎有一个参数dwShareMode 可以用于这种共享。

我相信NIO 会是正确的选择。查看dwShareMode 参数是否可作为NIO API 的一部分使用

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-23
    • 2021-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-04
    • 1970-01-01
    相关资源
    最近更新 更多