Анализ лога Apache - считаем запросы с localhost на Ruby
Было упражнение, где нужно в файле логов веб-сервера Apache (или любого другого веб-сервера) посчитать, сколько запросов пришло с локального хоста localhost (IP 127.0.0.1) и сколько из других мест.
Лог-файл выглядит вот так:
examples/data/apache_access.log
127.0.0.1 - - [10/Apr/2007:10:39:11 +0300] "GET / HTTP/1.1" 500 606 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)" 127.0.0.1 - - [10/Apr/2007:10:39:11 +0300] "GET /favicon.ico HTTP/1.1" 200 766 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)" 139.12.0.2 - - [10/Apr/2007:10:40:54 +0300] "GET / HTTP/1.1" 500 612 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)" 139.12.0.2 - - [10/Apr/2007:10:40:54 +0300] "GET /favicon.ico HTTP/1.1" 200 766 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)" 127.0.0.1 - - [10/Apr/2007:10:53:10 +0300] "GET / HTTP/1.1" 500 612 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)" 127.0.0.1 - - [10/Apr/2007:10:54:08 +0300] "GET / HTTP/1.0" 200 3700 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)" 127.0.0.1 - - [10/Apr/2007:10:54:08 +0300] "GET /style.css HTTP/1.1" 200 614 "http://machine.local/" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)" 127.0.0.1 - - [10/Apr/2007:10:54:08 +0300] "GET /img/machine-round.jpg HTTP/1.1" 200 17524 "http://machine.local/" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)" 127.0.0.11 - - [10/Apr/2007:10:54:21 +0300] "GET /unix_sysadmin.html HTTP/1.1" 200 3880 "http://machine.local/" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)" 217.0.22.3 - - [10/Apr/2007:10:54:51 +0300] "GET / HTTP/1.1" 200 34 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)" 217.0.22.3 - - [10/Apr/2007:10:54:51 +0300] "GET /favicon.ico HTTP/1.1" 200 11514 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)" 217.0.22.3 - - [10/Apr/2007:10:54:53 +0300] "GET /cgi/machine.pl HTTP/1.1" 500 617 "http://contact.local/" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)" 127.0.0.1 - - [10/Apr/2007:10:54:08 +0300] "GET / HTTP/0.9" 200 3700 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)" 217.0.22.3 - - [10/Apr/2007:10:58:27 +0300] "GET / HTTP/1.1" 200 3700 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)" 217.0.22.3 - - [10/Apr/2007:10:58:34 +0300] "GET /unix_sysadmin.html HTTP/1.1" 200 3880 "http://machine.local/" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)" 217.0.22.3 - - [10/Apr/2007:10:58:45 +0300] "GET /talks/Fundamentals/read-excel-file.html HTTP/1.1" 404 311 "http://machine.local/unix_sysadmin.html" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.3) Gecko/20061201 Firefox/2.0.0.3 (Ubuntu-feisty)"
Алгоритм:
Нам нужно два счетчика: один для подсчета хитов с 127.0.0.1 и один для хитов с других адресов. Затем нужно пройтись по всем строкам, извлечь IP-адрес, и на его основе увеличить один из счетчиков.
Мы предполагаем, что программа будет использовать вот так: ruby apache_localhost.rb data/apache_access.log. Таким образом, мы предполагаем, что пользователь укажет имя файла с логом в качестве аргумента команды.
Тем не менее, в первых строках мы проверяем, передал ли пользователь вообще имя файла с помощью количества элементов в ARGV. Если количество полученных аргументов не равно 1, то мы говорим пользователю, как пользоваться нашей программой и завершаем работу (exit).
Затем мы копируем имя файла из ARGV во внутреннюю переменную filename. В основном для наглядности кода.
Затем мы создаем два счетчика и устанавливаем их в 0.
Затем мы открываем файл на чтение и читаем строку за строкой с помощью each. В каждой итерации переменная line будет содержать текущую строку из файла.
IP-адрес это первое значение в строке до пробела. Есть несколько способов получить это значение из строки. В этом случае мы используем метод index объекта line, передавая ему пробел. Метод вернет позицию первого пробела в line. Так как нумерация начинается с 0, то этот номер будет также и длиной IP-адреса. Поэтому мы записали полученный результат в переменную length.
Мы можем использовать эту переменную для извлечения подстроки из line, которая начинается с 0 и включает length символов. Для этого нужно передать индекс начала подстроки и длину подстроки, которую мы хотим извлечь. Это и будет IP-адрес из текущей строки.
Осталость только проверить, что полученное значение совпадает с 127.0.0.1 (localhost) и увеличить соответствующий счетчик.
examples/ruby/apache_localhost.rb
if ARGV.length != 1 then puts "We need the name of the log file" exit end filename = ARGV[0] local = 0 remote = 0 fh = open filename fh.each do |line| length = line.index(' ') ip = line[0, length] if ip == '127.0.0.1' then local = local+1 else remote = remote+1 end end puts "Number of remote requests is #{remote}. Number of local requests was #{local}"

Published on 2016-02-27