如何编写只对新日志条目起作用的脚本

我觉得这应该是一件简单的事情,但我很难找出答案。

我正在试图编写一个脚本监视一个Apache日志文件,并采取一些具体的行动。 但是我应该如何去监视日志文件呢?

每当一个新的行被写入日志,我想要检查这个条目,看看它是否符合我正在寻找,如果是这样的x发生。 当我手动这样做时,我使用了cat或tail -f。 我不想每隔30秒通过cron运行脚本,并浏览整个日志(甚至是最后5行),找出自上次脚本运行后哪些行是新的,然后是如此的一些东西。

有没有办法只检查日志中的单个新条目?

通过cron运行脚本,但使用logtaillogtail2来读取文件将避免每分钟读取整个文件。 Logtail保持跟踪上次读取的位置,并在下次使用时跳转到该位置。

如果你想立即行动新的日志,而不是在cron调用之间等待59秒,你将不得不使用tail -f或者一些等价的东西。

Janne和Khaled的答案都希望能很好地解决这个问题。

您可以使用已经可用的Linux工具,如tailgrepnamed pipes 。 首先,使用以下命令创build一个命名pipe道(fifo):

 $ mkfifo /tmp/myfifo 

其次,创build一个简单的脚本,将从这个fifo文件读取。 这是一个简单的例子:

 #!/bin/bash pipe=/tmp/myfifo while true do if read line <$pipe; then if [[ "$line" == 'quit' ]]; then break fi echo $line fi done echo "Reader exiting" 

该脚本从命名pipe道中读取并将行打印到stdout,直到获得“quit”字样。 这只是一个可以自定义的例子。

第三,使用tail来读取附加到apache日志文件的新行,并将输出redirect到命名pipe道。

 $ tail -n0 -F /var/log/apache2/access.log | grep some_text > /tmp/myfifo 

-F选项意味着按照文件的名称应该使其免于logrotate。 所以,它将始终遵循相同的文件名。 -n0意味着不会得到任何旧的线路。 grep仅用于指导相关的行。

使用此解决scheme,您不需要任何cron作业。 只需运行上面显示的脚本和尾部命令即可。

如果你有syslog-ng (可能rsyslogd也可以)作为syslog-daemon,你可以使用它。

只需configuration它以关注Apache日志文件,或者configurationApache以使用CustomLog指令和logger将日志发送到syslog工具。

Syslog-daemon将使用模式匹配,如果find一些匹配项,则执行$ foo。 例如,在syslog-ng中,您可以设置一个日志文件钩子并像这样过滤它:

 source apache_log { file("/var/log/apache2/access.log"); }; filter apache_match { match("GET /evilscript.php"); }; 

然后syslog-ng调用外部脚本

 destination apache_logmatch_script { program("/usr/local/bin/apachematch.pl"); }; 

最后把所有这些放在一起:

 log { source(apache_log); filter(apache_match); destination apache_logmatch_script); }; 

如果使用这种技术,syslog-ng会产生你的脚本背景,等待新的东西出现。 因此,您需要修改脚本以等待来自STDIN的input; 这里是一个简短的Perl示例:

 #!/usr/bin/perl -w $|=1; while (<>) { printf "Stuff happened, I got this entry: %s!\n", $_; } 

直到我知道你想尝试这种技术,我才会更深入地回答。

你可以保留你读的最后一行的logging。 在从最后的+ 1行到文件和更新logging结束的每次新的运行中。

但请记住日志文件可能会旋转。 所以你应该logging一下inode号码。

fail2ban确实以你想要的方式实现了日志文件监视。 也许看看呢? 你可以借用一些想法或者实际使用它。

你可以使用差异。 将日志文件复制到临时文件。

比较实时日志文件和临时文件。

对生成的差异运行模式匹配。

采取从nagios check_log插件的想法。 有关更多详细信息,请参见http://www.kilala.nl/Sysadmin/index.php?id=715

如果fail2ban不适合你的需要,你可以尝试修改Markus J. Ranum写的flog.c文件:

“这个小实用程序的function相当于”tail -f“,但是在运行时,如果日志轮转器将文件从用户的下面移出,它足够聪明地处理文件的变化。而且,与”tail -f“不同的是,这个程序是当用户注销(!)时足够聪明,并且不会将日志永久地发送给pty,在优雅和性能方面没有任何努力。

您可以修改,以检查是否有新行符合您所需的模式,并采取相应的行动。

如果你想要一个Python解决scheme,请查看Pygtail: https : //github.com/bgreenlee/pygtail

它基于logchecklogtail2工具

 #!/bin/bash while read line; do echo $line > /tmp/output.log mail -s 'Event Msg.' '[email protected]' < /tmp/output.log done < <(tail -n0 -F /var/adm/messages)