Разработчику. Сборник рецептов PHP
Задавайте вопросы

Анализ файла протокола веб-сервера

Вернуться назад

Задача

Необходимо сделать расчеты на основании информации, содержащейся в файле протокола доступа к веб-серверу.

Решение

Откройте файл и проанализируйте каждую строку с помощью регулярного выражения, соответствующего формату файла протокола. Приведенное ниже регулярное выражение соответствует комбинированному формату протокола NCSA:

$pattern = '/^([^ ]+) ([^ ]+) ([^ ]+) (\[[^\]]+\]) "(.*) (.*) (.*)" ([0-9\-]+)
       ([0-9\-]+) "(.*)" "(.*)"$/';

Обсуждение

Эта программа анализирует строки в комбинированном формате протокола (Combined Log Format) NCSA и показывает список страниц, отсортированных по количеству запросов к каждой странице:

$log_file = '/usr/local/apache/logs/access.log';
$pattern = '/^([^ ]+) ([^ ]+) ([^ ]+) (\[[^\]]+\]) "(.*) (.*) (.*)" ([0-9\-]+)
       ([0-9\-]+) "(.*)" "(.*)"$/';
$fh = fopen($log_file,'r') or die($php_errormsg);
$i = 1;
$requests = array();
while (! feof($fh)) {
       // читаем каждую строку и удаляем начальные и конечные пробельные символы
if ($s = trim(fgets($fh,16384))) {
              // сравниваем строку с шаблоном
              if (preg_match($pattern,$s,$matches)) {
                      /* помещаем каждую совпавшую часть в переменную
                     * с соответствующим именем */
              list($whole_match,$remote_host,$logname,$user,$time,
                     $method,$request,$protocol,$status,$bytes,$referer,
                     $user_agent) = $matches;
              // ведем учет каждого запроса
              $requests[$request]++;
       } else {
              // выводим предупреждение, если строка не соответствует шаблону
              error_log("Can't parse line $i: $s");
       }
     }
     $i++;
}
fclose($fh) or die($php_errormsg);
// сортируем массив (в обратном порядке) по количеству запросов
arsort($requests);
// выводим отформатированные результаты
foreach ($requests as $request => $accesses) {
              printf("%6d %s\n",$accesses,$request);
}

Шаблон, используемый в функции preg_match(), соответствует строкам в комбинированном формате протокола, таким как:

10.1.1.162-david [20/Jul/2001:13:05:02-0400] "GET /sklar.css HTTP/1.0" 200
278 "-" "Mozilla/4.77 [en] (WinNT; U)"
10.1.1.248- - [14/Mar/2002:13:31:37-0500] "GET /php-cookbook/colors.html
HTTP/1.1" 200 460 "-" "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)"

В первой строке значение 10.1.1.162 представляет IP-адрес, с которого пришел запрос. В зависимости от настроек сервера, вместо него может стоять имя хоста. Когда значения массива $matches присваиваются списку отдельных переменных, то имя хоста запоминается в переменной $remote_host. Следующий дефис (-) означает, что удаленный хост не предоставил имя пользователя через identd,* поэтому переменной $logname присвоено значение «-».

Строка david содержит имя пользователя, предоставленное броузером с помощью базовой аутентификации HTTP, и присваивается переменной $user. Дата и время запроса, сохраненные в переменной $time, заключены в скобки. Этот формат даты и времени не распознается функцией strtotime(), поэтому, если вы хотите сделать вычисления, основанные на дате и времени запроса, то должны выполнить обработку для выделения каждой части форматированной строки времени. Следом, в кавычках, стоит первая строка запроса. Она состоит из метода (GET, POST, HEAD и т. д.), хранимого в переменной $method; запрошенного URI, хранящегося в переменной $request, и протокола, находящегося в переменной $protocol. Для запросов GET строка запроса является частью URI. Для запросов POST тело запроса, содержащее переменные, в протокол не заносится.

После запроса идет статус запроса, хранящийся в переменной $status. Статус 200 означает, что запрос успешно выполнен. После статуса находится размер ответа в байтах, присвоенный переменной $bytes. Последние два элемента строки, причем каждый из них в кавычках, это страница, с которой сделана ссылка, если таковая имеется, хранящаяся в переменной $referer,** и строка пользовательского агента, иденти-

____________________________________________________________________
* identd, определенная в RFC 1413, считается хорошим способом удаленной идентификации пользователей. Однако он не отличается защищенностью и надежностью. Квалифицированное объяснение можно найти на http://www.clock.org/~fair/opinion/identd.html.

** Правильным написанием этого слова является «referrer». Однако в оригинальной спецификации HTTP (RFC 1945) это слово ошибочно записано как «referer», поэтому часто в контексте встречается написание с тремя «r».
____________________________________________________________________


фицирующая броузер, который послал запрос, и хранящаяся в переменной $user_agent.

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

Такой способ определения статистики протоколов доступа к веб-серверу легок, но не очень гибок. Требуется модификация программы для различных видов отчетов, ограниченных диапазонов данных, форматирования отчетов и многих других целей. Наилучшим решением для получения всесторонней статистики веб-сайта является применение таких программ, как analog, Она предоставляет много типов отчетов и настроек конфигурации, которые должны удовлетворить практически любое ваше пожелание.

Вернуться назад

Рейтинг@Mail.ru

Яндекс.Метрика

Индекс цитирования

Рейтинг Сайтов ДОСКИ.РУ