2010-06-28 59 views
0

我开发一个脚本来阅读和搜索日志文件在工作中的大系统。 它目前是这样工作的:阅读活动日志文件,而不需要一个临时文件

  1. 用户定义的搜索参数
  2. PHP使用了shell_exec(“TAC LOGFILE.LOG> tmpfile.log”)来复制日志文件(和反向线)到一个临时文件
  3. PHP fopen()函数的临时文件
  4. PHP读取通过文件的每一行,并应用搜索参数
  5. PHP删除#做出的临时文件2

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

我的问题是,第2步需要很长的时间,当日志文件> 300MB,并且每天的日志文件很容易500MB,所以搜索这么多的数据实在是费时。

我有几个问题:)上的活动日志文件

  1. 我可以简单地运行的fopen(?
  2. 它可能会导致日志文件的损坏,如果我只是读它,而其他脚本编写呢?
  3. 将它减慢脚本写入日志文件,如果我在同一时间读它?
  4. 我可以让PHP读取文件的每一行而不是转发吗?

我希望是有道理的......

回答

2

要回答的编号问题:

在Unix或Unix类系统:

1:随意fopen()函数任何你想要的。附加到文件的其他进程不会被搞砸。移动文件的其他过程不会被搞砸。其他进程删除文件不会被搞砸。他们的业务将继续取得成功,您的业务也会如此。

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

3:在读取文件时,写入日志的脚本可能不会运行得更慢。文件数据和元数据需要被写入或读入内存中;如果您的搜索将缓存保持为热点,则日志记录甚至可以运行(稍微快一点)。

4:没有线索。 :)

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

首先,你可以先执行搜索和然后扭转结果:

grep danger /var/log/messages | tac 

搜索将不假设你的结果是一个足够小的整体的子集,那么走得更快,但是会倒退。其次,你可以使用dd(1)的skip = BLOCKS参数定期将你的日志文件分割成几部分;通过将文件分成10兆字节块,将倒转一次,并且每次重新处理剩余的部分,您可以分摊全天倒置文件的成本。正确编程需要更多努力,但节省时间可能是值得的。这取决于需要多长时间查询一次。第三,你可以编写你自己的道德等价物tail(1)-f,它将每个新行填充到环形缓冲区文件中。您将会覆盖之前的行,但听起来您的日志轮转已经限制了返回的数据量。 600兆字节的限制可能是合理的。您的查询可能以最近写入的字节开始,直到文件末尾,然后在文件的开头重新开始,如果没有返回足够的结果。这可能需要尽最大的努力才能得到正确的结果,但是可以通过每次写入日志来分摊反转数据库的成本。 (如果写入日志的脚本是突发性的,则这可能会严重地与高峰使用时的磁盘带宽剧本竞争。)

+0

真棒,感谢您回答我的问题:) 使用grep是我想到的一种可能性,但我的搜索很复杂,我还没有查看过grep搜索的具体情况。 我正在考虑自动反转所有日志文件的顺序栏中活动的一个。它应该使搜索档案更快。 – 2010-06-28 10:38:02

1

由于您使用shell_exec已经你可能想在它使用tail

用法:尾[选项] ... [FILE ] ...
将每个FILE的最后10行打印到标准输出。 对于多个FILE,每个FILE前面都有一个标题给出文件名。 没有FILE,或者当FILE是 - 时,读取标准输入。

+0

+1因为提问者不要求提供仅限PHP的解决方案。在PHP中重新实现'tail'并不难,但在这里会过度。不过,我想知道他是否真的只想要尾巴。好像他想要搜索整个文件,只是相反。 – janmoesen 2010-06-28 07:07:28

+0

感谢您的解决方案,但我正在搜索整个文件。我想反过来,因为我限制了比赛的数量,我希望最先找到最新的比赛。 – 2010-06-28 10:34:30

+0

@janmoesen是的,我没有正确阅读@ Valorin的问题。仍然可以使用'grep'然后,然后像[由sarnold下面提示](http://stackoverflow.com/questions/3130358/read-active-log-files-without-needing-a-temp-file/3130999# 3130999) – Gordon 2010-06-28 10:44:06