如何在不保持文件打开的情况下跟踪Java中的“Tail -f”之类的文件(防止重命名/删除)

时间:2013-01-30 17:59:29

标签: java file tail logfile

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

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

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

我还想检测一个“Rolled”文件,其机制更加确定,而不是注意到文件大小减少......看起来容易出错但不太可能。

由于我似乎无法访问文件描述符或其他低级文件实用程序,因此我可能无法重现尾部的行为 - 但是有没有任何技巧来读取文件而不“锁定”它以进行重命名/ delete(Windows 7)

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

3 个答案:

答案 0 :(得分:7)

Apache Commons有一个Tailer class,那会做你想要的吗?如果可以,它具有滚动检测机制以及阅读材料,因此您可以获得所需的一切。

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

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

答案 1 :(得分:5)

使用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();
}

}

答案 2 :(得分:1)

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

我相信NIO将成为可能。查看dwShareMode API

中是否有NIO参数可用