用Perl-Grep管道将linux命令发送到Grep



基本代码:

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中。

我注意到您接受的答案有一种非常复杂的方法来计算一小时前的时间戳,所以我提出了这个替代方案,它以更有效的方式使用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,因为它包含空格。

第一个问题是$ContentDate以换行结束。

第二个问题是,您不正确地从$ContentDate创建外壳文字(使用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/;
}
}

试试这个

#!/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);
}

最新更新