C'S SERVER Personalのサブドメインサービスはアクセスログを取得できるので、面白半分でエディタで開いてみたところ、あまりの量の多さにびっくり(これまで見たことなかったもので...(^_^;)。よく見ると、1ファイルの転送が1行で記録されており、トップページに1度アクセスしただけで20行程のログ...。こりゃ人間の見るものじゃないなと思い、リンク元が同じものを1行にまとめるプログラムを作ってみることにしました。
プログラムの作成には、文字列の扱いが簡単にできそうで、かつインターネットで広く使われているPerl*1を使うことにしました。早速、オライリー・ジャパンの初めてのPerl 第3版*2(通称「リャマ本」)を買ってきて、本を見ながら作ってみました。
#!/usr/bin/perl -w
use strict;
# ログファイルの整理プログラム log.pl [-dhrDHR] ver.1.0
# オプション d:date, h:host, r:referer を整形して出力
# D:date, H:host, R:referer を整形せずに出力
# 入力するログファイルのフォーマット
# host ident authuser date "request" status bytes "referer"
# "user-agent"\n
# date = [day/month/year:hour:minute:second zone]
# day 2桁, month 3文字, year 4桁, hour 2桁, minute 2桁, second 2桁
# zone (+|-)4桁
# 出力するログファイルの標準フォーマット(-dhr)
# date host referer
# date = day/month/year:hour:minute:second
# day 2桁, month 3文字, year 4桁, hour 2桁, minute 2桁, second 2桁 計20桁
# host 後半20文字
# referer 前半37文字,自分のサイトアドレスは / に置き換える
my $my_site = 'http://masaharu.la.coocan.jp/blog/'; # 自分のサイトアドレス
my $check = 10; # 遡ってチェックする行数
my @before_host = (' ') x $check;
my @before_referer = (' ') x $check;
my $option = '-dhr';
if (@ARGV) {
if ($ARGV[0] =~ /^-[dhrDHR]/) {
$option = shift @ARGV;
}
}
foreach (<STDIN>) {
/(^\S+).+(\[\S+ \S+\]) "[^"]+".+"([^"]+)" "[^"]+"\n/;
my $host = $1;
my $date = $2;
my $referer = $3;
# 遡ったチェック行数内で host と referer が同じ場合は出力しない
my $out = 1; # 初期値 = 出力する
foreach (0..$check - 1) {
if (($host eq $before_host[$_]) &&
($referer eq $before_referer[$_])) {
$out = 0;
last;
}
}
pop @before_host; # 配列の末尾を削除
pop @before_referer;
unshift @before_host, $host; # 配列の先頭に追加
unshift @before_referer, $referer;
# 出力
if ($out == 1) {
if ($option =~ /^-.*d/) { # 秒まで
print substr($date, 1, 20), ' ';
} elsif ($option =~ /^-.*D/) { # そのまま
print "$date ";
}
if ($option =~ /^-.*h/) { # 後半20文字
printf "%20.20s ", substr($host, -20, 20);
} elsif ($option =~ /^-.*H/) { # そのまま
print "$host ";
}
if ($option =~ /^-.*r/) {
if ($referer =~ /^($my_site)/) { # 前半36文字
print '/', substr($referer, length($my_site), 36);
} else { # 前半37文字
print substr($referer, 0, 37);
}
} elsif ($option =~ /^-.*R/) { # そのまま
print $referer;
}
print "\n";
}
}
コメント、変数の宣言及びオプション処理を除くと、10行有るか無いかって感じですね。これを実行してみるとこんな感じに...。
7月2日のログを入れてみました
ソートしてグラフを描かないと使い物にならないという声が聞こえてきそうですが、うちのサイトの場合、1日分だとターミナルの1ページに収まってしまい、これで十分という噂も...(^_^;
次回は、1週間分ぐらいのデータで、グラフが描けるようなプログラムを作ってみようと思います。*3