Analogは存在していないサーバにはApacheログを解析するために、awkでも行えますが、今回Perlでもっと自由に簡単に行ってみます。IPアドレスを検出するために、IP情報が必要ですが、サーバのログによってホストで記録される場合があります。その場合、スクリプトで変換する機能も追加します。
#!/bin/env perl
use Cwd;
use Net::DNS;
use Socket;
my $progressMarker = 100000;
my $res = Net::DNS::Resolver->new;
$| = 1;
my $inputFile = $ARGV[0];
my $limit = $ARGV[1];
my $logFile = getcwd . '/' . $inputFile;
my %stats;
my $topLimit = 0;
if ($limit ne "")
{
$topLimit = $limit;
}
print "Scanning $inputFile ....";
my $progressCnt = 0;
open(LOG, $logFile) || die "Cannot open $logFile $!";
my $totalHits = 0;
while(my $line = )
{
my @fields = split(/\s/, $line);
if ($progressCnt % $progressMarker == 0)
{
print '.';
}
my $ip = $fields[0];
$progressCnt++;
$stats{$ip}++;
$totalHits++;
}
close(LOG);
print "done.\n";
print "Sorting IP by visit count ...";
@ipList = sort { $stats{$b} $stats{$a} } keys %stats;
print "done.\n";
printf("%-10s%-20s%-60s%-10s%-5s\n","RANK",
"IP ADDR",
"HOST",
"VISITS",
"% OF VISITS");
my $rank = 0;
foreach my $thisIP (@ipList)
{
my $cnt = $stats{$thisIP};
my $host = "n/a";
my $reverseIP = join('.', reverse split(/\./, $IP)).".in-addr.arpa";
my $query = $res->query("$reverseIP", "PTR");
if ($query)
{
foreach my $rr ($query->answer)
{
next unless $rr->type eq "PTR";
$host = $rr->rdatastr;
}
}
else
{
$err = $res->errorstring;
if ($err eq "NOERROR")
{
my $iaddr = inet_aton($thisIP);
$host = gethostbyaddr($iaddr, AF_INET);
}
if ($host eq "")
{
$host = "unknown (dig -x $thisIP)";
}
}
$rank++;
printf("%-10d%-20s%-60s%-10d%-4.2f%\n",$rank,
$thisIP,
$host,
$cnt,
($cnt * 100/$totalHits));
if ($rank >= $topLimit)
{
exit;
}
}
VN:F [1.9.11_1134]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.11_1134]