извлечение последних 10 минут из файла журнала [дубликат]
этот вопрос уже есть ответ здесь:
пытаясь найти простой способ просмотра последних событий (менее 10 минут), я пробовал это:
awk "/^$(date --date="-10 min" "+%b %_d %H:%M")/{p++} p" /root/test.txt
но это работает не так, как ожидалось...
файлы журнала в форме :
Dec 18 09:48:54 Blah
Dec 18 09:54:47 blah bla
Dec 18 09:55:33 sds
Dec 18 09:55:38 sds
Dec 18 09:57:58 sa
Dec 18 09:58:10 And so on...
6 ответов
вы можете сопоставить диапазон дат с помощью простого сравнения строк, например:
d1=$(date --date="-10 min" "+%b %_d %H:%M")
d2=$(date "+%b %_d %H:%M")
while read line; do
[[ $line > $d1 && $line < $d2 || $line =~ $d2 ]] && echo $line
done
например, если d1='Dec 18 10:19'
и d2='Dec 18 10:27'
тогда выход будет:
Dec 18 10:19:16
Dec 18 10:19:23
Dec 18 10:21:03
Dec 18 10:22:54
Dec 18 10:27:32
или через awk
если вы хотите:
awk -v d1="$d1" -v d2="$d2" ' > d1 && < d2 || ~ d2'
вот хороший инструмент диапазон любой Вы хотите от -10 до сих пор
sed -n "/^$(date --date='10 minutes ago' '+%b %_d %H:%M')/,$p" /var/log/blaaaa
это (обычная) работа для perl!:
простой и эффективный:
perl -MDate::Parse -ne 'print if/^(.{15})\s/&&str2time()>time-600' /path/log
эта версия печатает последние 10 минут события, до теперь, С помощью
на Баш можно использовать date
команда для анализа временных меток. The спецификатор формата"%s " преобразует заданную дату в количество секунд с 1970-01-01 00:00:00 UTC. Это простое целое число легко и точно выполнять основную арифметику.
если вы хотите сообщения журнала от последних 10 минут фактического времени:
now10=$(($(date +%s) - (10 * 60)))
while read line; do
[ $(date -d "${line:0:15}" +%s) -gt $now10 ] && printf "$line\n"
done < logfile
Примечание ${line:0:15}
выражение расширение параметра bash что дает первый 15 символов строки, т. е. сама метка времени.
если вы хотите, чтобы сообщения журнала За последние 10 минут относительно конца журнала:
$ lastline=$(tail -n1 logfile)
$ last10=$(($(date -d "$lastline" +%s) - (10 * 60)))
$ while read line; do
> [ $(date -d "${line:0:15}" +%s) -gt $last10 ] && printf "$line\n"
> done < logfile
Dec 18 10:19:16
Dec 18 10:19:23
Dec 18 10:21:03
Dec 18 10:22:54
Dec 18 10:27:32
$
вот умеренное повышение производительности на:
$ { while read line; do
> [ $(date -d "${line:0:15}" +%s) -gt $last10 ] && printf "$line\n" && break
> done ; cat ; } < logfile
Dec 18 10:19:16
Dec 18 10:19:23
Dec 18 10:21:03
Dec 18 10:22:54
Dec 18 10:27:32
$
это предполагает, что записи журнала находятся в строгом хронологическом порядке. Как только мы сопоставим метку времени в вопросе, мы выходим из цикла for, а затем просто используем cat
сбросить оставшиеся записи.
в python вы можете сделать следующее:
from datetime import datetime
astack=[]
with open("x.txt") as f:
for aline in f:
astack.append(aline.strip())
lasttime=datetime.strptime(astack[-1], '%b %d %I:%M:%S')
for i in astack:
if (lasttime - datetime.strptime(i, '%b %d %I:%M:%S')).seconds <= 600:
print i
поместите строки из файла в стек (список python). поп последний элемент и получить разницу между последовательными элементами даты, пока вы не получите разницу менее 600 секунд.
запуск на Вашем входе, я получаю следующее:
Dec 18 10:19:16
Dec 18 10:19:23
Dec 18 10:21:03
Dec 18 10:22:54
Dec 18 10:27:32
решение Ruby (протестировано на ruby 1.9.3)
вы можете передать дни, часы, минуты или секунды в качестве параметра, и он будет искать выражение и на указанный файл (или каталог, в этом случае он будет добавлять '/ * ' к имени):
в вашем случае просто вызовите скрипт следующим образом: $0-m 10 "expression" log_file
Примечание: также, если вы знаете местоположение "ruby", измените shebang (первая строка скрипта), для безопасности причины.
#! /usr/bin/env ruby
require 'date'
require 'pathname'
if ARGV.length != 4
$stderr.print "usage: #{} -d|-h|-m|-s time expression log_file\n"
exit 1
end
begin
total_amount = Integer ARGV[1]
rescue ArgumentError
$stderr.print "error: parameter 'time' must be an Integer\n"
$stderr.print "usage: #{} -d|-h|-m|-s time expression log_file\n"
end
if ARGV[0] == "-m"
gap = Rational(60, 86400)
time_str = "%b %d %H:%M"
elsif ARGV[0] == "-s"
gap = Rational(1, 86400)
time_str = "%b %d %H:%M:%S"
elsif ARGV[0] == "-h"
gap = Rational(3600, 86400)
time_str = "%b %d %H"
elsif ARGV[0] == "-d"
time_str = "%b %d"
gap = 1
else
$stderr.print "usage: #{} -d|-h|-m|-s time expression log_file\n"
exit 1
end
pn = Pathname.new(ARGV[3])
if pn.exist?
log = (pn.directory?) ? ARGV[3] + "/*" : ARGV[3]
else
$stderr.print "error: file '" << ARGV[3] << "' does not exist\n"
$stderr.print "usage: #{} -d|-h|-m|-s time expression log_file\n"
end
search_str = ARGV[2]
now = DateTime.now
total_amount.times do
now -= gap
system "cat " << log << " | grep '" << now.strftime(time_str) << ".*" << search_str << "'"
end