Было упражнение, где нужно в файле логов веб-сервера 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}"