Skip to content
Advertisement

Sending linux commands in Perl – Grep piped to grep

The basic code:

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 {

}

Why wont Perl complete these commands correctly? $fail2ban is already defined to 0, so that’s not the issue.

The fail2ban.log does contain a line that should match(when running command from shell it matches):

2018-07-19 xx:11:50,200 fail2ban.actions[3725]: WARNING [iptables] Ban x.x.x.x

The error i keep getting is:

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.

All the commands run fine from bash/shell, seems at if perl is not happy with grep being piped to another grep? I’ve tried many different ways of adding the variable($ContentDate) into the grep without helping.

Advertisement

Answer

I notice that the answer you’ve accepted has a rather over-complicated way to calculate the timestamp an hour ago, so I present this alternative which uses Perl’s built-in date and time handling in a more efficient manner.

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

But the only change you actually needed was to change:

my $Fail2banNo = `grep Ban /var/log/fail2ban.log | grep $ContentDate | wc -l`;

to:

my $Fail2banNo = `grep Ban /var/log/fail2ban.log | grep "$ContentDate" | wc -l`;

Quoting $ContentDate because it contains a space.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement