我觉得这应该是一件简单的事情,但我很难找出答案。
我正在试图编写一个脚本来监视一个Apache日志文件,并采取一些具体的行动。 但是我应该如何去监视日志文件呢?
每当一个新的行被写入日志,我想要检查这个条目,看看它是否符合我正在寻找,如果是这样的x发生。 当我手动这样做时,我使用了cat或tail -f。 我不想每隔30秒通过cron运行脚本,并浏览整个日志(甚至是最后5行),找出自上次脚本运行后哪些行是新的,然后是如此的一些东西。
有没有办法只检查日志中的单个新条目?
通过cron运行脚本,但使用logtail或logtail2来读取文件将避免每分钟读取整个文件。 Logtail保持跟踪上次读取的位置,并在下次使用时跳转到该位置。
如果你想立即行动新的日志,而不是在cron调用之间等待59秒,你将不得不使用tail -f或者一些等价的东西。
Janne和Khaled的答案都希望能很好地解决这个问题。
您可以使用已经可用的Linux工具,如tail , grep和named 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
它基于logcheck的logtail2工具
#!/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)