基本代码:
my $ContentDate = `date -d '1 hour ago' '+%Y-%m-%e %H:'`;
my $Fail2banNo = `grep Ban /var/log/fail2ban.log | grep $ContentDate | wc -l`;
if (($Fail2banNo > $fail2ban)) {
} else {
}
为什么Perl无法正确完成这些命令? $ fail2ban已经定义为0,所以这不是问题。
fail2ban.log确实包含应该匹配的行(当从shell运行命令时,它匹配):
2018-07-19 xx:11:50,200 fail2ban.actions[3725]: WARNING [iptables] Ban x.x.x.x
我一直遇到的错误是:
grep: 10:: No such file or directory
sh: -c: line 1: syntax error near unexpected token `|'
sh: -c: line 1: ` | wc -l'
Argument "" isn't numeric in numeric gt (>) at /usr/local/bin/tmgSupervision.pl line 3431.
所有命令都可以从bash / shell正常运行,似乎是如果perl不满意将grep传递到另一个grep吗?我尝试了许多不需帮助就将变量($ ContentDate)添加到grep的方法。
答案 0 :(得分:6)
我注意到您接受的答案在一个小时前计算时间戳的方法非常复杂,因此我提出了这种替代方法,它以更有效的方式使用Perl的内置日期和时间处理。
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
use Time::Piece;
my $log = '/var/log/fail2ban.log';
my $fail2ban = 0;
my $ContentDate = localtime(time - 3600)->strftime('%Y-%m-%e %H:');
my $Fail2banNo = qx{grep Ban $log | grep "$ContentDate" | wc -l};
if ($Fail2banNo > $fail2ban) {
say 'Yes';
}
else {
say 'No';
}
但是您真正需要的唯一更改是更改:
my $Fail2banNo = `grep Ban /var/log/fail2ban.log | grep $ContentDate | wc -l`;
收件人:
my $Fail2banNo = `grep Ban /var/log/fail2ban.log | grep "$ContentDate" | wc -l`;
引用$ContentDate
,因为其中包含空格。
答案 1 :(得分:1)
第一个问题是$ContentDate
以换行结尾。
第二个问题是您不正确地从$ContentDate
创建了shell文字(使用grep 2018-07-19 08:
而不是类似grep '2018-07-19 08:'
的东西)。
让我们先解决您的问题。
use String::ShellQuote qw( shell_quote );
my $fail2ban_log_qfn = '/var/log/fail2ban.log';
my $content_date = `date -d '1 hour ago' '+%Y-%m-%e %H:'`;
chomp($content_date);
my $grep_cmd1 = shell_quote('grep', 'Ban', $fail2ban_log_qfn);
my $grep_cmd2 = shell_quote('grep', '--', $content_date);
my $fail2ban_count = `$grep_cmd1 | $grep_cmd2 | wc -l`;
chomp($fail2ban_count);
不过,无需花时间就可以获取日期。
use POSIX qw( strftime );
use String::ShellQuote qw( shell_quote );
my $fail2ban_log_qfn = '/var/log/fail2ban.log';
my $content_date = strftime('%Y-%m-%e %H:', localtime(time - 3600));
my $grep_cmd1 = shell_quote('grep', 'Ban', $fail2ban_log_qfn);
my $grep_cmd2 = shell_quote('grep', '--', $content_date);
my $fail2ban_count = `$grep_cmd1 | $grep_cmd2 | wc -l`;
chomp($fail2ban_count);
也无需花一些时间来计算匹配行。
use POSIX qw( strftime );
my $fail2ban_log_qfn = '/var/log/fail2ban.log';
my $fail2ban_count = 0;
{
my $content_date = strftime('%Y-%m-%e %H:', localtime(time - 3600));
open(my $fh, '<', $log_qfn)
or die("Can't open \"$fail2ban_log_qfn\": $!\n");
while (<$fh>) {
++$fail2ban_count if /Ban/ && /\Q$content_date/;
}
}
答案 2 :(得分:-4)
尝试一下
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $log = "/var/log/fail2ban.log";
my $fail2ban = 0;
my $ContentDate = backintime(3600); #backintime in seconds from now
my $Fail2banNo = qx{grep Ban $log | grep \"$ContentDate\"| wc -l};
if ($Fail2banNo > $fail2ban) {
say "Yes";
}
else {
say "No";
}
sub backintime {
my ($to_today) = @_;
my $temps = time - 60*60*24*0;
$temps = $temps - $to_today;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($temps);
if($sec < 10) {$sec = "0" . $sec;}
if($min < 10) {$min = "0" . $min;}
if($hour < 10) {$hour = "0" . $hour;}
if($mday < 10) {$mday = "0" . $mday;}
$year+=1900; $mon++; if($mon < 10) {$mon = "0" . $mon;}
my $sectime = $year."-".$mon."-".$mday." ".$hour.":";
return($sectime);
}