无需临时文件即可读取活动日志文件

时间:2010-06-28 06:01:19

标签: php

我正在开发一个脚本来读取和搜索工作中的大系统的日志文件。 它目前的工作方式如下:

  1. 用户定义搜索参数
  2. PHP使用shell_exec(“tac logfile.log> tmpfile.log”)将日志文件(并将其反转)复制到临时文件
  3. PHP fopen()是临时文件
  4. PHP读取文件的每一行并应用搜索参数
  5. PHP删除#2
  6. 中生成的临时文件

    我决定使用这种方法,因为每隔几秒就会写入日志文件,我需要向后读取日志文件。

    我的问题是,当日志文件大于300MB时,第2步需要很长时间,并且每天的日志文件很容易500MB,因此搜索这么多数据非常耗时。

    我有几个问题:

    1. 我可以在活动日志文件上运行fopen()吗?
    2. 如果我在其他脚本写入时只是读取它会导致日志文件损坏吗?
    3. 如果我同时阅读,那么写入日志文件的脚本是否会变慢?
    4. 我可以告诉PHP向后阅读文件的每一行而不是向前阅读吗?
    5. 我希望这是有道理的......

2 个答案:

答案 0 :(得分:2)

回答编号问题:

在Unix或类Unix系统上:

1:随意(f)任何你想要的东西。附加到文件的其他进程不会被搞砸。移动文件的其他进程不会被搞砸。删除文件的其他进程不会被搞砸。他们的行动将继续成功,你的也将如此。

2:读取文件不会阻止编写者写入,除非文件系统正在应用强制文件锁定。这是不太可能的,因为它是一个很大的性能损失。 (有关强制锁定的详细信息,请参阅系统的fcntl(2)联机帮助页。)

3:在您阅读文件时,写入日志的脚本可能不会运行得慢。需要将文件数据和元数据带入内存进行写入或读取;如果你的搜索保持缓存热,那么日志记录甚至可以更快地运行(

4:没有线索。 :)

我可以想到解决这个问题的几种可能方法:

首先,您可以先执行搜索,然后然后反转结果:

grep danger /var/log/messages | tac

搜索速度不会更快,但如果您的搜索结果是整体的一小部分,则会进行反转。

其次,您可以使用dd(1)的skip = BLOCKS参数定期将日志文件分成多个部分;通过将文件分成10兆字节块,将一次转换为,并且每次重新处理剩余部分,您可以分摊全天逆转文件的成本。正确编程需要更多的努力,但节省时间可能是值得的。这取决于需要进行查询的频率。

第三,你可以编写自己的道德等价的tail(1)-f,它将每个新行填充到一个环形缓冲区文件中。您可以随时覆盖以前的行,但听起来您的日志轮换已经限制了返回的数据量。 600兆字节的限制可能是合理的。您的查询可以从最近写入的字节开始,一直读到文件的末尾,然后如果没有返回足够的结果则在文件的开头重新开始。这可能需要尽最大努力才能获得正确,但是通过每次单独的日志写入来分摊逆转数据库的成本。 (如果写入日志的脚本是突发性的,那么在高峰使用时,这可能会严重影响磁盘带宽的脚本。)

答案 1 :(得分:1)

由于您已经使用shell_exec,因此您可能希望在其中使用tail

  

用法:tail [OPTION] ... [FILE] ...
  将每个FILE的最后10行打印到标准输出。   如果有多个FILE,则每个文件前面都有一个标题,表示文件名。   没有FILE,或者当FILE是 - 时,读取标准输入。