0

I need bash script to search in the log words Failed and failure. But only from last hour

cut -c 5- /var/log/mail.log | awk '($0 >= from)' from="$(LC_TIME=C date +'%_d %H:%M:%S' -d -1hour)" |grep -i 'Failed:\|failure'

Example log file

Nov  1 01:00:00 localhost pushmail[55555]: 666666666666: Failed 
Nov  2 15:00:00 localhost pushmail[55556]: 666666666666: Failed 
Nov  3 11:00:00 localhost pushmail[55557]: 666666666666: Failed 
Nov  3 12:00:00 localhost pushmail[55558]: 666666666666: Failed 
Nov  3 13:30:00 localhost pushmail[55559]: 666666666666: Failed 
Nov  3 13:40:00 localhost pushmail[55560]: 666666666666: Failed 
Nov  3 14:00:00 localhost pushmail[55561]: 666666666666: Failed 
Nov  3 15:00:00 localhost pushmail[55562]: 666666666666: Failed 
Nov 14 15:00:00 localhost pushmail[55563]: 666666666666: Failed 

I use cut to remove local month name. But when I have in log entry form two day ago i have it in results.

3
  • I don't use Linux mail, so I don't know the format of the mail log file. If you could amend your question to show in the original log format a few each of included records and earlier records, both excluded and falsely included, then I shall be able to assist.
    – AFH
    Commented Nov 3, 2017 at 13:10
  • Hi! AFH i add some exaple log records.
    – myhell
    Commented Nov 3, 2017 at 13:21
  • Hope this works :) grep -E "$(date +"($(date +%H)|%H)":%M:%S --date='last hour').*(Failed|failure)" /var/log/mail.log
    – Paulo
    Commented Nov 3, 2017 at 15:02

3 Answers 3

1

The most reliable solution I could find is:

while read -r rec
do   age=$(($(date +%s)-$(date -d "${rec:0:16}" +%s)))
     [ $age -ge 0 -a $age -le 3600 ] && \
     grep -Eiq 'failed|failure' <<< "$rec" && echo "$rec"
done </var/log/mail.log

This uses date to convert logged times into seconds since the start of 1970 and then compares these with the seconds value for the current time. This will work in all cases, including the hour after midnight, except the first hour of a new year, because date -d defaults to the current year when none is specified. I assume you will have better things to do than run this script at the dawn of a new year.

The check for the record age being non-negative eliminates future records, as I found in the Nov 14 record when testing on 3rd November. I simulated calling at different times by adding a -d parameter to the first date call, which in the answer gets the current time reference.

1
  • (Sorry for the delay in answering, but I didn't get your update before going out this afternoon.)
    – AFH
    Commented Nov 4, 2017 at 0:02
0

The problem is that "14">" 3" because 1>" ". You need to use leading zeroes in your dates. For example, you can put all the commands into one awk:

awk '{ date = sprintf("%02d %s",$2,$3) }
     date>from && /Failed|failure/ { print }
' from="$(LC_TIME=C date +'%d %H:%M:%S' -d -1hour)"

I changed the %_d to %d to get leading zeroes from date. In the awk the sprintf uses %02d to put a leading zero to field 2, the date.

0
0

awk '($0 >= from)' from="$(LC_ALL=C date +'%b %_d %H:%M:%S' -d -1hour)" ~/mail.log |grep -i 'Failed\|failure'

Hi! Thanks everyone for help! In my case this script work. if you want to change range of time from 1 hour you can do this chcenaging value example -d -60minutes or -d -2days

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .