Собственно, есть настроить Apache так, чтобы он сразу писал логи в БД. Однако, появилась необходимость разово залить существующий текстовый лог в базу с целью быстренько проанализировать. По-быстрому найти рабочий скрипт не удалось, оказалось проще написать свой велосипед.
<?php /* Читает лог Апача и помещает его в таблицу базы данных */ $log_src = '/path/to/file/access_log'; // Имя файла лога для чтения $sql_host = 'localhost'; // параметры подключения к БД $sql_user = 'test'; $sql_pass = ''; $sql_db = 'test'; $sql_max_counter = 100; // Строк лога на один запрос $table_name = 'statslog'; // Имя таблицы ////////////////////////////////////////////////////////////////////////////////////////////////// error_reporting(E_ALL); // Запросы на удаление/создание таблиц $sql_drop_table = <<<SQL DROP TABLE IF EXISTS `{$table_name}` SQL; $sql_create_table = <<<SQL CREATE TABLE `{$table_name}` ( `ip` varchar(25) DEFAULT NULL, `accessdate` date DEFAULT NULL, `accesstime` time DEFAULT NULL, `themethod` varchar(7) DEFAULT NULL, `thepage` varchar(250) DEFAULT NULL, `theproto` varchar(10) DEFAULT NULL, `thecode` char(3) DEFAULT NULL, `thebytes` int(11) DEFAULT NULL, `theref` varchar(250) DEFAULT NULL, `browser` varchar(250) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 SQL; echo '<pre>'; $fsrc = fopen($log_src, 'r'); $month = array(); $month['Jan'] = '01'; $month['Feb'] = '02'; $month['Mar'] = '03'; $month['Apr'] = '04'; $month['May'] = '05'; $month['Jun'] = '06'; $month['Jul'] = '07'; $month['Aug'] = '08'; $month['Sep'] = '09'; $month['Oct'] = '10'; $month['Nov'] = '11'; $month['Dec'] = '12'; $sql_counter = 0; // Счет строк для одного запроса $str_counter = 0; // Счет прочитанных строк mysql_connect($sql_host, $sql_user, $sql_pass) or die(__LINE__.' Error: ' . mysql_error()); mysql_select_db($sql_db) or die(__LINE__.' Error: ' . mysql_error()); mysql_query($sql_drop_table) or die(__LINE__.' Error: ' . mysql_error()); mysql_query($sql_create_table) or die(__LINE__.' Error: ' . mysql_error()); while($str = fgets($fsrc)) { $str_counter++; preg_match( '/(\d+\.\d+\.\d+\.\d+)\s+-\s+-\s+\[([^:]+):(.+)\s+.+\]\s\"([^\"]+)\s([^\"]+)\s([^\"]+)\"\s(\d{3})\s(\d+|-)\s\"([^\"]*)\"\s\"([^\"]*)\"/', $str, $m ); $mm = explode('/', $m[2]); $m[2] = "{$mm[2]}-{$month[$mm[1]]}-{$mm[0]}"; // Правка даты unset($m[0]); // Полный шаблон нам не нужен echo '.'; // Индикатор строки if($sql_counter == 0) { // Начало запроса $sql_string = "INSERT INTO `{$table_name}` VALUES "; } if($sql_counter < $sql_max_counter) { // Дописываем разобранную строку в запрос $sql_counter++; $sql_string .= "\n" . '("' . implode('","', $m) . '"),'; } if($sql_counter == $sql_max_counter) { // Запись строк в базу и обнуление счетчика mysql_query(rtrim($sql_string, ',')) or die(__LINE__.' Error: ' . mysql_error() . "\n$sql_string\n$str_counter"); echo "| $sql_counter | $str_counter \n"; // Индикатор запроса $sql_counter = 0; } } if($sql_counter) { // Последние строки в базу mysql_query(rtrim($sql_string, ',')) or die(__LINE__.' Error: ' . mysql_error() . "\n$sql_string\n$str_counter"); } echo ":\n$str_counter"; // Индикатор окончания fclose($fsrc); ?>
За безглючность не ручаюсь. Возможно, придется немного допилить регулярку.