![]() |
|
Модераторы: korob2001, ginnie |
![]()
|
|
| box |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 506 Регистрация: 27.2.2007 Репутация: нет Всего: 0 |
есть текстовый файл с логом и мне ничего не стоит распарсить его и закидать в базу на примере :
но проблема в том что скрипт вызавается каждую минуту а лог обновляется по мере поступления данных , как реализовать что б скрипт записывал в базу только новые данные что поступили с момента прошлого обновления лога . и еще , лог может периодически обнулятся , тоесть файл просто удаляется и создается новый , пустой . в таком случае по мере поступления данных в лог тоже должно происходить дописывание в базу . |
|||
|
||||
| Egik2 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 302 Регистрация: 29.7.2008 Где: Агудзера Репутация: 1 Всего: 11 |
Если у тебя в логе есть временная метка, а если нет то лучше сделать
То как вариант могу предложить писать в какой-нить отдельный файл, дату записи, которую ты последнюю вставил в базу, а потом начинать с этой даты. -------------------- Три великие добродетели программиста: лень, нетерпение и самомнение (Larry Wall) a-nav.com developer-blog.ru world-poetry.org |
|||
|
||||
| arto |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1495 Регистрация: 31.10.2004 Репутация: 38 Всего: 40 |
perldoc File::Tail
Добавлено через 31 секунду или просто tail |
|||
|
||||
| box |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 506 Регистрация: 27.2.2007 Репутация: нет Всего: 0 |
дело в том что я спецом убрал временную метку из логов дабы урезать размер лога , да и время выполнения скрипта возрастет если я буду парсить временную мерку и сравнивать ее с записью из базы. а если лог будет 1-5 гигов то сервер то и будет делать что все время парсить логи. нужно както по другому . |
|||
|
||||
| klem4 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 27.7.2008 Репутация: 2 Всего: 2 |
Не использовать временные метки - странное решение, но можно и без них решить Вашу задачу. Хранить (где угодно) кол-во строк лог-файла, при запуске скрипта сравнивать хранимую цифру с реальным кол-вом строк в логе, и если она меньше, парсить строки, номера которых больше хранимого индекса. Затем пересохранять индекс.
|
|||
|
||||
| box |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 506 Регистрация: 27.2.2007 Репутация: нет Всего: 0 |
а как быть если файл логов обнулен , тогда счетчик не поможет
|
|||
|
||||
| klem4 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 27.7.2008 Репутация: 2 Всего: 2 |
обнулен файл, обнуляй и счетчик, не вижу в чем проблема.
|
|||
|
||||
| ramus |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 53 Регистрация: 21.2.2008 Репутация: 1 Всего: 1 |
0) Лог не содержащий время - не лог
1) Если лог размером 1-5 гига, то предложение "при запуске скрипта сравнивать хранимую цифру с реальным кол-вом строк в логе" ОЧЕНЬ сильно нагрузит бессмысленной работой сервер (надо читать 1-5 гигов одного и того же файла при каждом запуске программы) 2) Вам рекомендовал уважаемый arto команду tail - это правильное решение. 3) если же хочется реализовать самому, то посмотрите команды seek и tell. Идея такова: Когда Ваша программа в первый раз дочитает лог до конца (с записью в БД распарсенных значений), надо в конце файла вывод команды tell сохранить для следующего запуска вашей программы(в БД или в файле). При следующем запуске вы зачитываете последнее сохраненное значение и встаете на эту позицию файла лога командой seek, пропустив уже отпарсенное. Команда seek работает почти мгновенно, почти не зависит от размера файла и практически не нагружает сервер. Опять читаете лог до конца файла с записью в БД распарсенных значений и записываете новое значение tell в БД или файл. Узнать, что файл лога отрезался можно сравнив размер зачитанный из БД и реальный размер файла лога. Если реальный размер меньше, то наверняка файл отрезался. При этом Ваша программа должна читать файл с начала. Правда могут быть нюансы если запуски программы реже чем отрезки файла лога. Если Ваша программа должна работать ТОЛЬКО на UNIX(Linux) я бы для этого кроме размера проверял бы еще i-node файла, так как имя лога обычно бывает одно и тоже, а меняется только сам файл, т.е. i-node. |
|||
|
||||
| klem4 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 27.7.2008 Репутация: 2 Всего: 2 |
Никогда не слышали про замечательную команду wc ? На логе 300+mb, wc -l Отрабатывает менее чем за 1 секунду. |
|||
|
||||
| ramus |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 53 Регистрация: 21.2.2008 Репутация: 1 Всего: 1 |
Кстати, а что за БД используется Вами? Она поддерживает переменные привязки (bind)?
Я бы на месте админа БД убил бы эту сессию вместе с разработчиком такой проги ;) Если БД - ORACLE, то код while(<LOG>){ my ($ip_temp, $host_temp, $string_temp) = split(/\|/, $_); $query = "INSERT INTO log (ip, host, string) VALUES ('".$ip_temp."', '".$host_temp."', '".$string_temp."')"; $query_handle = $connect->prepare($query); $query_handle->execute(); } очень быстро забьет sql area сервера БД, понизив тем самым общую производительность сервера код должен быть таким (примерно, я не проверял): my $query = "INSERT INTO log (ip, host, string) VALUES (?, ?, ?)"; $query_handle = $connect->prepare($query); while(<LOG>){ my ($ip_temp, $host_temp, $string_temp) = split(/\|/, $_); $query_handle->execute($ip_temp, $host_temp, $string_temp); } |
|||
|
||||
| klem4 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 27.7.2008 Репутация: 2 Всего: 2 |
К моему последнему сообщению: на логе 1.2G результат более плачевный. Так что если файлы большие то вариант мой действительно не проходит.
|
|||
|
||||
| ramus |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 53 Регистрация: 21.2.2008 Репутация: 1 Всего: 1 |
На логе 300+mb, wc -l Отрабатывает менее чем за 1 секунду.
Забавно А знаете что она (wc) реально делает? Это говорит, что либо файл уже в кеше, либо сервер ОЧЕНЬ мощный (например дисковая система на внешнем массиве по FC), так как чтение 300MB/секунду это хорошо (естественно если ВЕСЬ сервер не в вашем распоряжении и на нем еще идет полезная работа) Я против загрузки сервера тупой работой. |
|||
|
||||
| box |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 506 Регистрация: 27.2.2007 Репутация: нет Всего: 0 |
да нет , не то это все и сервер ложится при использовании базы , не вывозит нагрузки уже при 10 метровом логе.хоть проц 2 ядра и рама 4 гига .
не вариант юзать базу данных в моем случае , а так хотелось ! |
|||
|
||||
| shamber |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1422 Регистрация: 5.9.2006 Где: Россия Репутация: 17 Всего: 18 |
box, а ложиться скорее всего из-за, того что Вам ramus написал по поводу prepare и execute
|
|||
|
||||
| Egik2 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 302 Регистрация: 29.7.2008 Где: Агудзера Репутация: 1 Всего: 11 |
А почему она должна ложиться? Я всегда думал, что prepare statement наоборот помогает, позволяет держать базе в кэше объект SQL statement, что избавляет от необходимости каждый раз парсить запрос. -------------------- Три великие добродетели программиста: лень, нетерпение и самомнение (Larry Wall) a-nav.com developer-blog.ru world-poetry.org |
|||
|
||||
| shamber |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1422 Регистрация: 5.9.2006 Где: Россия Репутация: 17 Всего: 18 |
||||
|
||||
| Egik2 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 302 Регистрация: 29.7.2008 Где: Агудзера Репутация: 1 Всего: 11 |
Ну ведь он, это и советует:
Не надо: То есть prepare происходит для каждой записи, что неправильно - и по идее одно и то же, что вставка без prepare. И как должно быть То есть идет подготовка выражения с самого начала, а потом используется подготовленное. Разве это не правильно? -------------------- Три великие добродетели программиста: лень, нетерпение и самомнение (Larry Wall) a-nav.com developer-blog.ru world-poetry.org |
|||
|
||||
| shamber |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1422 Регистрация: 5.9.2006 Где: Россия Репутация: 17 Всего: 18 |
ramus, предложил верное решение.
позднее время, а также то,что чукча писатель, а не читатель(чукча -> я), и не позволило, вам увидеть эту мысль в моей фразе. Каюсь |
|||
|
||||
| ramus |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 53 Регистрация: 21.2.2008 Репутация: 1 Всего: 1 |
"хоть проц 2 ядра и рама 4 гига ."
У нас особо "одаренные" программисты таким образом "напрягали" гораздо более крутой сервер - 8 двухядерных итаниумов с 64 гигами оперативки. Я не говорю, что это предложение панацея от всего, но то, что надо один раз отпарсить SQL, а потом многократно использовать с разными данными-это существенно облегчит жизнь серверу и админу. "что prepare statement наоборот помогает, позволяет держать базе в кэше объект SQL statement, что избавляет от необходимости каждый раз парсить запрос." Как раз в Вашем варианте происходит парсинг для каждой строки лога, так как каждый раз строка разная, например INSERT INTO log (ip, host, string) VALUES ('1.1.1.1', 'host_temp', 'string') INSERT INTO log (ip, host, string) VALUES ('2.2.2.2', 'host_temp', 'string') В предложенном мной варианте парсинг (в том числе определение плана выполнения) выполняется один раз, INSERT INTO log (ip, host, string) VALUES (:ip, :host, :string) в области хранения SQL запросов ( SQL area) будет только ОДНА строчка (от нашей сессии). Число execute для нее будет равняться числу строк в логе. В Вашем же случае число строк в sql area БД будет равно числу строк в логе и для каждой такой строки число execute будет =1. PS Лучше много раз по разу, чем ни разу много раз ;) |
|||
|
||||
| box |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 506 Регистрация: 27.2.2007 Репутация: нет Всего: 0 |
пишу следующее :
такой вариант работает только в том случае если лог не обноляется , но у меня он периодически обнуляется и получается что новая запись в базе не добавится пока кол-во строк в новом файле не будет больше чем кол-во записей в базе , вообщем бред получается . вообщем вопрос номер один "как определить что лог обновился а не просто еще не успел набрать того кол-ва строк что в базе" |
|||
|
||||
| shamber |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1422 Регистрация: 5.9.2006 Где: Россия Репутация: 17 Всего: 18 |
У вас тут с логикой все совершенно жестко. Вам предложили пару вариантов, но вы их не хотите использовать, вместо этого изобретаете велосипед, и удивляетесь что ничего не работает. Чем Вам не нравится вариант с seek? Добавлено @ 11:29 ну добавьте в скрипт, чтение параметров файла, к примеру время последней модификации. и все проблемы решены Это сообщение отредактировал(а) shamber - 26.1.2010, 11:30 |
|||
|
||||
| ginnie |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1287 Регистрация: 6.1.2008 Где: Москва Репутация: 38 Всего: 49 |
box, у меня вот какой вопрос возник: если у Вас лог периодически обнуляется и этот процесс никак не завязан со скриптом, Вы, случайно, часть данных не теряете (которые добавилась после запуска скрипта, но до обнуления лога)?
-------------------- Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг) |
|||
|
||||
| box |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 506 Регистрация: 27.2.2007 Репутация: нет Всего: 0 |
"ну добавьте в скрипт, чтение параметров файла, к примеру время последней модификации. и все проблемы решены"
к сожалению это проблемы не решает потому как время модификации файла будет меняться каждый раз когда добавляется новая строка файла. у меня была идея создавать lock файл или запись в бд о том что файл обновлен и потом соответсвующим образом обрабатывать лог но это займет больше ресурсов. |
|||
|
||||
| shamber |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1422 Регистрация: 5.9.2006 Где: Россия Репутация: 17 Всего: 18 |
||||
|
||||
| arto |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1495 Регистрация: 31.10.2004 Репутация: 38 Всего: 40 |
интересно, когда вы повторите функциональность обыкновенного tail?
который может следить хоть за дескриптором, хоть за именем... |
|||
|
||||
| box |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 506 Регистрация: 27.2.2007 Репутация: нет Всего: 0 |
приведите пожалуйста пример использования tail в перле , а то я нашел только для командной строки .
|
|||
|
||||
| klem4 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 27.7.2008 Репутация: 2 Всего: 2 |
А почему не хотите использовать tail коммандной строки из perl ?
|
|||
|
||||
| arto |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1495 Регистрация: 31.10.2004 Репутация: 38 Всего: 40 |
tail | perl самое простое.
либо perldoc -f open |
|||
|
||||
| klem4 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 27.7.2008 Репутация: 2 Всего: 2 |
Дак можно прямо в перл получать результат tail
|
|||
|
||||
| arto |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1495 Регистрация: 31.10.2004 Репутация: 38 Всего: 40 |
нет.
я так понял, что вы не прочитали man tail ? |
|||
|
||||
| klem4 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 27.7.2008 Репутация: 2 Всего: 2 |
не совсем понял, какоe отношение имеет способ вызова tail к прочтению/не прочтению мною man'а. |
|||
|
||||
| arto |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1495 Регистрация: 31.10.2004 Репутация: 38 Всего: 40 |
а вы прочитайте.
|
|||
|
||||
| mvsgt |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 209 Регистрация: 27.3.2009 Репутация: 1 Всего: 1 |
||||
|
||||
![]()
|
| Правила форума "Perl" | |
|
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Perl: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |