Reputation: 6365
I have huge xferlog and I'm trying to parse it. My log file like this:
Wed Nov 5 16:41:36 2014 1 10.8.0.6 0 /home/spy/16.41.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:42:07 2014 1 10.8.0.6 0 /home/spy/16.42.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:43:45 2014 1 10.8.0.6 0 /home/spy/16.43.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:44:34 2014 1 10.8.0.6 0 /home/spy/16.44.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:45:57 2014 1 10.8.0.6 0 /home/spy/16.45.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:46:52 2014 1 10.8.0.6 0 /home/spy/16.46.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:46:55 2014 1 10.8.0.6 0 /home/spy/16.46.2.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:47:23 2014 1 10.8.0.6 0 /home/spy/16.47.txt b _ i r spy ftp 0 * c
My bash script reads the log file(while all line) and does something. I need to run my script for the without last 5 mins of my log file(not last few lines, because I don't know how many line).
How can I do?
Bash script like this:
#!/bin/bash
while read -r ...
do
...
done < $LOG
My second question, how can I pass lines that in last 5 minutes interval:
Log:
Wed Nov 5 16:41:36 2014 1 10.8.0.6 0 /home/spy/16.41.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:42:07 2014 1 10.8.0.6 0 /home/spy/16.42.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:43:45 2014 1 10.8.0.6 0 /home/spy/16.43.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:44:34 2014 1 10.8.0.6 0 /home/spy/16.44.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:44:59 2014 1 10.8.0.6 0 /home/spy/16.44.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:45:00 2014 1 10.8.0.6 0 /home/spy/16.45.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:46:52 2014 1 10.8.0.6 0 /home/spy/16.46.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:46:55 2014 1 10.8.0.6 0 /home/spy/16.46.2.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:47:23 2014 1 10.8.0.6 0 /home/spy/16.47.txt b _ i r spy ftp 0 * c
Last line 16:47:23. I need to pass 16:45:00-16:49:59 lines. I need to print:
Wed Nov 5 16:41:36 2014 1 10.8.0.6 0 /home/spy/16.41.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:42:07 2014 1 10.8.0.6 0 /home/spy/16.42.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:43:45 2014 1 10.8.0.6 0 /home/spy/16.43.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:44:34 2014 1 10.8.0.6 0 /home/spy/16.44.txt b _ i r spy ftp 0 * c
Wed Nov 5 16:44:59 2014 1 10.8.0.6 0 /home/spy/16.44.txt b _ i r spy ftp 0 * c
So when I have new line like this:
Wed Nov 5 16:50:00 2014 1 10.8.0.6 0 /home/spy/16.50.txt b _ i r spy ftp 0 * c
I need to pass 16:50:00-16:54:59.
Upvotes: 0
Views: 399
Reputation: 246847
Since you say your file is quite large, you don't want to parse and call date
for every line, that would be quite slow. That leaves parsing the file with a language that has date parsing facilities. Here's some perl:
perl -MTime::Piece -MTime::Seconds -Mautodie -e '
sub entry_time {
Time::Piece->strptime(substr(shift, 0, 24),"%a %b %e %T %Y");
}
$filename = shift;
$last_line = qx{ tail -n1 $file };
$last_time = entry_time $last_line;
$five_minutes_ago = $last_time - 5*ONE_MINUTE;
open $fh, "<", $filename;
while (<$fh>) {
$time = entry_time $_;
last if $time > $five_minutes_ago;
print;
}
close $fh;
' xferlog
with bash
entry_time() {
date -d "$(cut -c 1-24 <<< "$1")" +%s
}
LOG=xferlog
cutoff=$(( $(entry_time "$(tail -n1 "$LOG")") - 5*60 ))
while IFS= read -r line; do
t=$(entry_time "$line")
(( t > cutoff )) && break
echo "$line"
done < "$LOG"
Upvotes: 2