监视日志文件并根据特定条目采取操作

监视日志文件并根据特定条目采取操作

我想做以下事情:

tail -f 某个文件 { 如果换行符匹配/包含

somestring(执行操作 1;执行操作 2;...;更多操作)

somestring2(执行其他操作)...

somestring999(甚至执行另一个操作)}

这是我目前最接近的:

尾-f /mnt/zandrologs/* | awk '/GRRFIELD/ { system("echo \"test\"") }'

但这只会识别一个参数,并且只会执行一个命令。我需要让它识别多种模式并执行多个命令。最后我把它放在一些 bash 脚本中

也许这不仅仅是继续的方式,但这就是我刚才所得到的。现在它只是读取日志,直到找到字符串并向控制台输出一些垃圾(测试)。我想扩展它,但我将问题限制在我想做的事情的本质上。

感谢您帮助我解决一些基本语法问题。

答案1

如果您喜欢的话,可以继续您的方法。
当然,您可以为每个匹配执行多个命令,并将不同的行与不同的命令序列匹配(也可以为不同类型的行共享一些命令,同时运行更多特定的命令)。
前任:

tail -f /mnt/zandrologs/* | awk '
/GRRFIELD/{ system("echo \"test\""); system("echo \"testG\""); }
/FRRFIELD/{ system("echo \"test2\""); system("echo \"testF\""); }
/FIELD/{ system("echo \"shared command for all lines containing FIELD\"");}'

如果您愿意,您还可以省略换行符并用空格替换它们。另外,您还可以进行更复杂的匹配 - 如果您只匹配 $0 (整行),如您的示例所示,我建议在固定字段和 witdh 模式下使用 awk 以避免将行拆分为字段的开销。

答案2

珀尔文件::尾巴模块非常适合此类任务。它可能是为您的发行版预先打包的(例如在 debian 和衍生品上,sudo apt-get install libfile-tail-perl

例如

#!/usr/bin/perl

use strict;
use File::Tail;

my $dir='/mnt/zandrologs';

# Get the list of logfiles in the target directory
my @logfiles = glob("$dir/*");

# Set up an array of File::Tail objects, one for each filename.
my @logs=();
foreach (@logfiles) {
  push(@logs,File::Tail->new(name => $_));
}

# Now watch those logs and do stuff when the script sees matching patterns
while (1) {
  my ($nfound,$timeleft,@pending)= File::Tail::select(undef,undef,undef,undef,@logs);

  if ($nfound) {
    foreach my $input (@pending) {

      # read the line of data from the current File::Tail object into $_
      $_ = $input->read;
      chomp;

      # Get the filename of the current File::Tail object.
      # This script doesn't use it, so it's commented out.
      # my $fn = $input->{'input'};

      if (m/somestring/) {
         # do stuff here
         # any perl code, including executing external programs with system().
      } elsif (m/somestring2/) {
         # do different stuff here
      } elsif (m/somestring3/) {
         # and more different stuff
      } elsif (m/somestring999/) {
         # yet more different stuff
      }
    }
  }
};

这将永远循环日志文件(或直到被杀死)。如果任何输入文件被旋转,File::Tail将自动关闭并重新打开该文件(即类似于tail -F)。

当一个或多个日志中有新数据时,该File::Tail::select()方法返回:

  • $nfound- 找到的带有待处理数据的 File::Tail 对象的数量(即数组中的元素数量@pending)。
  • $timeleft- 超时之前剩余的时间select(),但此脚本没有将超时值传递给select(它只是传递了除数组undef之外的所有内容@logs)。
  • @pending- 包含新的、未读数据的 File::Tail 对象数组

的每个元素@pending都是一个 File::Tail 对象,具有各种方法(例如read()返回该对象的待处理文本行)和哈希键(例如{'input'}包含文件名)。

详情请参阅man File::Tail和。perldoc -f select


正如所写的,该脚本将忽略该脚本启动之前文件中存在的任何行。您可以通过阅读最后一个来更改它n通过更改此行,甚至从头开始更改整个文件:

push(@logs,File::Tail->new(name => $_));

(首先读取日志文件中的最后 10 行):

push(@logs,File::Tail->new(name => $_, tail => 10));

或(从头开始读取所有日志文件):

push(@logs,File::Tail->new(name => $_, tail => -1));

这是该模块的有效但简单的使用。请参阅 参考资料 了解man File::Tail更多详细信息和替代使用方法。该模块还附带了一些很好的示例脚本。


PS:多年来我经常使用这个模块。例如,我曾经File::Tail在 20 世纪 90 年代维护自己的脚本,用于调用ipchains自动阻止试图做坏事的 IP 地址。然后fail2ban出现了,我转而使用它。直到今天我仍然使用它来监控日志脚本。

相关内容