我想做以下事情:
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
出现了,我转而使用它。直到今天我仍然使用它来监控日志脚本。