2016-03-23 2 views
0

Мне бы хотелось, чтобы мой скрипт Perl разбирался в syslogs.Perl scripting для syslog

Мой скрипт запускается на cron на почасовой основе для вывода некоторых статистических данных. Я заметил, что это занимает почти 5-10 минут, чтобы закончить в течение дня (syslogs архивируются ежедневно), так как файлы системного журнала несколько ГБ и сценарий делает простой:

open LOG, $logfile or die "fatal error. Could not open $logfile" 

Проблема заключается в том, что изначально первые журналы журналов - первые строки в журналах. По мере того как день прогрессирует, «текущий час» записей журнала в syslog теперь, скажем, от 600000 до 700000. Таким образом, каждый час он становится медленнее и медленнее.

Сложный подход состоял бы в том, чтобы выполнить grep-файл против файла на основе времени и сохранить результаты в файле tmp, после чего мой скрипт perl обработает файл tmp, а затем удалит файл tmp, повторите.

Есть ли более программный способ гарантировать, что я не перечитываю тысячи строк каждый раз?

SK

+1

Время, необходимое для открытия файла, не зависит от того, насколько оно велико. 5 или 10 минут - это долгое время для поиска даже нескольких гигабайт. Не могли бы вы разместить фактический код поиска? – Schwern

+0

Я добавил печать после 'while () {$ count ++; print line $ count \ n "' и его прирост со скоростью 5000 строк в секунду. Однако к 7-му часу мои текущие часы журналов находятся на линиях 600000-70000. Код довольно длинный, а на поле нет в этой сети так сложно переносить, что и маленький фрагмент. В принципе, я не хочу перечитывать строки 1-600000 за каждый час, когда я проверяю журнал на наличие журналов текущего часа. Надеюсь, это имеет смысл. – scryptKiddy

+0

Фактический поиск находится прямо после печати выше, в котором говорится: 'if ($ _ = ~/^ $ time_search_str /) {... делать некоторые вещи' – scryptKiddy

ответ

7

У вас есть куча возможных решений.


Первый заключается в том, чтобы внедрять ежечасно, а не ежедневно, поворот журнала. Тогда ваша программа должна прочитать только часовой файл журнала. Вероятно, это хорошая идея, если ваши журналы попадают в диапазон гигабайта в день.

Если это невозможно, возможно, это будет сделано для повышения эффективности вашего поискового кода. Первым шагом будет запуск профайлера кода, например Devel::NYTProf, чтобы узнать, где ваша программа тратит свое время.


Вместо того чтобы делать линейный поиск, вы можете сделать binary search. Предполагая, что ваши записи лог-файлов являются чем-то вроде этого:

Mar 22 01:22:34 blah blah blah 
Mar 22 01:22:35 blah blah blah 

seek на полпути к файлу, читать частичную строку, выбросить его, и прочитать следующую полную строку. Проверьте его метку времени. Если его слишком новый, seek назад половина оставшегося пространства, если он слишком старый, seek переместите половину оставшегося пространства. Повторяйте, пока не найдете начало часа.

За миллиард записей для этого потребуется около войти (2) или 30 шагов.


Другой вариант - прочитать файл назад. Начните с конца (самая новая запись в журнале) и вернитесь, пока не нажмете начало часа. File::ReadBackwards может сделать это довольно эффективно.


Вы можете изменить статистику журнала программу, чтобы написать свои результаты в базу данных, в том числе положение в лог-файл последней записи он написал. Затем в следующий раз он запустит его seek s в эту позицию, проверит его правильность и читает вперед.


И наконец, рассмотрите возможность использования базы данных. Вы можете иметь журнал syslogd для самой базы данных, это позволяет избежать накладных расходов каждой программы, которая должна войти в базу данных. Например, rsyslog и syslog-ng могут это сделать.

+0

Все замечательные предложения Шверна. Я определенно не контролирую вращение журнала, но я тоже об этом подумал. Что касается профилирования, то это интересный инструмент, я определил причину с помощью распечаток $ count. Они печатались в течение нескольких минут, пока, наконец, я не ударил строку поиска, и мой код начал обрабатываться.
Мне нравится метод двоичного поиска, напоминает мне метод полушагового. Я предполагаю, что 'seek' является функцией PERL?
Я действительно думал о чтении файла назад, но не уверен, как он будет храниться в переменной. В других словах я должен был бы отменить процесс. – scryptKiddy

+0

База данных - это то, к чему я стремлюсь, особенно потому, что они хотят исторической статистики, однако я сосредоточен на первом шаге, который заключается в исправлении обработки, которая, кажется, берет навсегда, отсюда и пост. – scryptKiddy

+3

['seek()'] (http://perldoc.perl.org/functions/seek.html) - это функция Perl, ее общая для большинства языков программирования, и она перемещает курсор вокруг файла так же, как в редактор. Что касается базы данных, вам не нужно ждать, пока кто-то установит сервер базы данных, вы можете использовать [SQLite] (https://en.wikipedia.org/wiki/SQLite). – Schwern