Архив документации OpenNet.ru / Раздел "Perl" / Индекс
Простой анализатор логов на хеше хешей массивов
#!/usr/bin/perl

open F, "</var/log/rambler.access.log" or die "can't open: $!\n"; @mass=<F>; close F;

for $gr(grep{!$m{$_}++} map{/S?E?T (.*?) / if /usr/ or m!/~user/!} @mass){
  for $line(@mass){
    ($ip, $n, $m, $data, $k, $method, $url, $protocol, $status, $size, $from, $brouser) =
      split /\s/ => $line;
    push @{$hash{$gr}{$ip}}, $size if $line=~m!$gr!;
  }
}
for $a(sort keys %hash){ my ($u, $j);
  print "file $a: \n\t";
  for $key(sort keys %{$hash{$a}}){ $j++;
    print "  '$key' \t => [ ";
    print 1+$#{$hash{$a}{$key}};
    my $i;
    for(@{$hash{$a}{$key}}){$i+=$_}
    print " $i";
    $u+=$#{$hash{$a}{$key}}+1;
    print " ]\n\t";
  }
  print "  dlya $a hitov $u, hostov $j\n";
  print "\t\n";
}
эта программа сплитит каждую строчку лог-файла по разделютелю пробел. Если написать обработчик логов, т.е. программу, которая анализирует, по чему можно сплитить лог, то все здорово. А вообще по хорошему, необходимо, чтобы при установке программы она сама запрашивала, какие логи за что ответственны и как их анализировать. Главный принцип работы - структурирование по ip-адресу, строится хеш для страницы, потом хеш для адреса, и массив каждому ключу этого хеша вес скачанной информации. Рамерность массива - число запросов данного ip к данному файлу. сумма элементов for(@{$hash{$a}{$key}}){$i+=$_} - полный рамер величины информации, выкачанной пользователем. При помощи небольших изменений(тут нужно знать схему построения хеша хешей массивов) можно выделять и сортировать любую информацию по любым броузерам или охвату территории. Соотвественно условие map{/S?E?T (.*?) / if /usr/ or m!/~user/!} говорит о том, что нужно сплитить. Изменим программу допустим как-то так:
#!/usr/bin/perl
use CGI 'param';
$dir1=param('d1');
$dir2=param('d2');
open F, "</var/log/rambler.access.log" or die "can't open: $!\n"; @mass=<F>; close F;

for $gr(grep{!$m{$_}++} map{/S?E?T (.*?) / if /$dir1/ or m!$dir2!} @mass){
  for $line(@mass){
    ($ip, $n, $m, $data, $k, $method, $url, $protocol, $status, $size, $from, $brouser) =
      split /\s/ => $line;
    push @{$hash{$gr}{$ip}}, $size if $line=~m!$gr!;
  }
}
for $a(sort keys %hash){ my ($u, $j);
  print "file $a: \n\t";
  for $key(sort keys %{$hash{$a}}){ $j++;
    print "  '$key' \t => [ ";
    print 1+$#{$hash{$a}{$key}};
    my $i;
    for(@{$hash{$a}{$key}}){$i+=$_}
    print " $i";
    $u+=$#{$hash{$a}{$key}}+1;
    print " ]\n\t";
  }
  print "  dlya $a hitov $u, hostov $j\n";
  print "\t\n";
}
Вводя команду вида bash2-05$ log.pl d1=www d2=/~user/ получим данные о числе заходов пользователя на данную страницу и статистику по файлам. Не знаю, как насчет других анализаторов логов, но этот намного легковесней и состоит из пары десятков строк. Но, он имеет очень большой минус, он весь логфайл держит в памяти, т.к. для полной статистики по логфайлу необходимо анализировать весь лог. Введя условия в map{/S?E?T (.*?) / if /usr/ or m!/~user/!}, можно ограничить выборку конкретной директорией. Хотя впрочем это не настолько трудная задача, можно читать каждую дирректорию по отдельности. В любом случае при анализе логов происходит полное чтение логфайла, в предложенном варианте программы чтение однократное, но и машину повесить может. Но, вобщем, это решабельно...


Архив документации на OpenNet.ru