Документация по ОС FreeBSD Четверг, 16.05.2024, 05:41
Приветствую Вас Гость | RSS
Меню сайта

Категории каталога
Apache [58]
DNS [25]
FTP [27]
Mail [74]
Samba [24]
Squid [46]
SSH [23]
VPN [35]
РРР [20]
Net [173]

Главная » Статьи » Сеть » Net

Пишем perl-скрипт для trafd
Работа с текстом

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

Сисадмины знают, как утомительно выискивать в этих протоколах необходимую информацию или анализировать оную. Хорошо, если у вас на машине только один лог - bootlog.txt, а если десяток, и ежедневно надо шефу давать отчет, кто с какого компьютера куда лазил в Интернете, сколько было посещений вашего сайта, у кого в почтовом ящике 90% развлекательных рассылок с www.sexygirls.com, а 10% - служебной корреспонденции, то вам без инструментария не обойтись. Лучше всего для этих целей использовать perl, - за 10-15 минут можно написать любой анализатор лога на свой вкус.

Анализатор лога

К примеру, есть лог учета трафика машин вашей сети по работе в интернет (вполне реальный лог демона trafd). Обычно он имеет такой вид:
from to bytes total date time
ws-5.game.net ws-1.game.net 1884 3228 07.10.01 19:04:47
forwarder5.spylog. ws-1.game.net 2164 3164 07.10.01 19:04:47
ws-5.game.net 62.146.24.217 1802 3162 07.10.01 19:04:47
ws-5.game.net entropy.agava.ru 1315 3035 07.10.01 19:04:47
sovet.yandex.ru ws-1.game.net 2729 2933 07.10.01 19:04:47
forwarder5.spylog. ws-5.game.net 2409 2905 07.10.01 19:04:47
ws-1.game.net forwarder5.spylog. 1537 2861 07.10.01 19:04:47
ws-1.game.net search.rambler.ru 1006 2062 07.10.01 19:04:47

Задача: по определенной машине извлечь всю статистику - общее количество байт переданное и принятое извне, и список сайтов, с которыми данный хост (машина) обменивался данными.

Как видим, запись лога состоит из 6 полей определенной длины, поля не разделяются. (Обычно поля разделяются табуляцией или запятыми). Еще определено, что в данном случае в значении поля не может быть пробела. Можно попробовать разделить поля по пробелам. Алгоритм прост = перебирать файл по строке, строку разбивать на поля, и, если совпадает с требуемым хостом, то суммировать данные. Проще простого.

Если вы думаете, что сейчас начнутся циклы с нескончаемым уровнем вложенности, то заблуждаетесь - это оставьте другим языкам программирования. Тут намного проще:
tr/ / /s;
($add1,$add2,$stemp,$totsize,$date,$time) = split(/ /,$_);

Вот эти две строчки делают всю работу: сначала из строки ($_) удаляют лишние пробелы, оставляя по одному, и затем режет ее на переменные (split), используя в качестве разделителя пробелы.
Если вы с perl не знакомы, то следует пояснить: переменные в perl в основном начинаются со знака доллара $, а переменную по "умолчанию" обозначают как $_.

Хитрая конструкция tr/ / /s; обозначает следующее: найти в переменной "по умолчанию" все пробелы и сжать их tr/ / /s

Чтение файла

Чтобы получить строки из файла, для этого его нужно только открыть и в цикле уже обрабатывать строки:
open FILE,"trafd.log";
while () {
tr/ / /s;
($add1,$add2,$stemp,$totsize,$date,$time) = split(/ /,$_);
....
}

Весьма непривычно и на первый взгляд, лишено смысла. Но, поверьте - работает и весьма эффективно. На тех же сях(язык C) эта обработка заняла бы по крайней мере в четыре раза больше кода. Здесь же конструкция:
while ()
эквивалентна такой (на абстрактном языке):
while(!eof(FILE)) $str = readln(FILE); }

Передача параметров в скрипт

Дальше нужно лишь выделить нужные нам записи и просуммировать их траффик. Адрес нужного нам хоста мы будем передавать в командной строке. Кроме того, в качестве параметра можно передавать и имя лог-файла. Как этот параметр получить в perl скрипте:
$req_addr = shift;
$filename = shift;

Чтобы было ясно: параметры получаем по очереди из командной строки, сдвигая их оператором shift. Это простейший метод, и при его использовании требуется соблюдать очередность параметров. Таким образом переменной $req_addr было присвоено значение первого параметра, а переменной $filename - значение второго параметра.

Хэши

Далее - банальная проверка условия и подсчет траффика:
$totalin = 0;
$totalout= 0;
if ($add1 eq $req_addr) {
# подсчитываем входящий траффик$totalin += $totsize;
# запомним хост-корреспондент и траффик на него$dh{$add2} += $totsize;
}
if ($add2 eq $req_addr) {
# подсчитываем исходящий траффик$totalout += $totsize;
# запомним хост-корреспондент и траффик на него$dh{$add1} += $totsize;
}

В условии использован оператор eq, т.е. оператор сравнения == для текстовых выражений. А хитрая конструкция вида $dh{$add1}+=$totsize записывает в именованный массив (хэш) переменную $totsize, причем оператором += суммирует первоначальное содержимое элемента хэша со значением, хранящемся в $totsize. Что такое хэш (hash)? Это массив, у каждого элемента которого есть собственное имя и значение, т.е.:
%dh = ('www.yahoo.com', 9845, 'www.yandex.ru', 23632,.....);
# или можно записывать так:
%dh = (
www.yahoo.com=> 9845,
www.yandex.ru=> 23632,
...=>.....);

Нужно помнить, что хэш в целом начинается не с $, а с "процента" - %, но при прямом обращении к элементу нужно использовать запись вида $x{$y} = $value;.

Полный текст скрипта

Вот и все куски кода готовы - нужно из них слепить программку - анализатор лога. Что у нас получится :

#!/usr/bin/perl
# первая строка в perl программе - всегда путь на диске к интерпретатору
# в данном случае - в Unix - стиле, но можно,
# например = c:perlbinperl.exe
# Хотя в MS Windows это не обязательно, если это не CGI скрипт.
$req_addr = shift; # параметр - адрес хоста
$filename = shift; # параметр - имя лог-файла
print $filename,"n";
if ( $filename eq 0 ) { # не передали имя лог-файла
$filename = "/var/log/trafd.log"; # берем имя по умолчанию
}
print $filename,"::",$req_addr,"n";
open FILE,$filename; # открываем файл
$totalin = 0;
$totalout= 0;
while () {
tr/ / /s;
($add1,$add2,$stemp,$totsize,$date,$time) = split(/ /,$_);
if ($add1 =~ $req_addr) {
$totalin += $totsize;
$dh{$add2} += $totsize;
}
if ($add2 eq $req_addr) {
$totalout += $totsize;
$dh{$add1} += $totsize;
}
}
close FILE; # не забыть закрыть файл
# Последнее - распечатать результат
print "Статистика по хосту ",$req_addr,"n";
print "Исходящий траффик :",$totalin,"n";
print "Входящий траффик :",$totalout,"n";
print "n";
print "В сумме по удаленным хостам:n";
foreach $key (sort keys(%dh)) {
foreach (split("", $dh{$key})) {
($out = $_);
format STDOUT =
@<<<<<<<<<<<<<<<<<<<<<<<< == @>>>>>>>>>>>>>>>> байт
$key, $out
.
write();
}
}
Всего-то - 45 строк с комментариями! Последнее пояснение - конструкция

Форматированный вывод

format STDOUT =. Это, как вы догадались, строка форматирования вывода в файл STDOUT (т.е. на экран по умолчанию).
В шаблоне скобки <<<<<< указывают выравнивание переменной по левому краю, скобки >>>>>> - по правому. Если использовать символы |||||||, то это обозначит выравнивание по центру, ####.## - вывод числа с N знаками после запятой. В поле будет выводится столько символов, сколько есть в строке шаблона.
Если вместо знака @ перед шаблонами поставить @*, то данная переменная будет выводится в колонку, если не поместится на одной строке. Если вместо @ использовать ^, то выведется символов столько, сколько есть в строке шаблона, а переменная будет содержать остаток невыведенных символов.
Программа готова, можно пользоваться и особых любителей в рабочее время лазить по сайтам сомнительного содержания можно будет "пощемить", чтобы не загружали траффик и не мешали сисадмину рубиться в "Counter-Strike".
 

(c) 2001-2002 Daemon News Russia
Категория: Net | Добавил: oleg (27.11.2007)
Просмотров: 1116 | Рейтинг: 0.0/0 |
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Форма входа

Beastie

Друзья сайта

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
links

Copyright MyCorp © 2024