15

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

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

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

我还想检测一个“滚动”文件,其机制比注意到文件大小减小...似乎容易出错但不太可能。

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

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

4

3 回答 3

8

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

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

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

于 2013-01-30T20:58:56.013 回答
6

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

}

于 2013-03-07T18:54:07.163 回答
1

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

我相信NIO这是要走的路。查看dwShareMode参数是否可作为NIOAPI的一部分使用

于 2013-01-30T20:31:55.190 回答