2010年1月17日日曜日

Virtual Boxの共有フォルダ

macbookのVirtual Boxにインストールし、Debian LennyをゲストOSとしていれてみた。

debian があまり使いなれていないのでソース編集はmac側でやりたい。
mac上のあるディレクトリを共有フォルダに設定し、ゲストOS側から参照。


mount -t vboxsf "virtualboxに設定した共有フォルダ名" "マウントポイント"

ってな感じで、Debian から共有フォルダをマウントする。

cakephpは、cakeapp/app/tmp/*の所有者権限をApacheユーザにする必要があるのだけど、
マウントした共有フォルダは所有者がrootのなっており、かつ所有者権限の変更がきない。

なぜだろうと思ったら、mountする際に所有者権限設定するみたいだった。


mount -t vboxsf "virtualboxに設定した共有フォルダ名" "マウントポイント" -o uid="所有者のuid"


-o uid=にwwwユーザを設定して、とりあえず解決しました。

2010年1月16日土曜日

ApacheログをDBに保存するperlスクリプト

Apache Logを解析するためにMySQLに保存したいなーと思ったのでスクリプトを書いてみた。
DBIを利用するのが初めて、perlの理解もいまいちだったので苦労した・・

携帯サイト用なので一応uidも考慮。docomoのuidはパラメータしか取得できないのでちょっと面倒。

テーブルはこんな感じ。とりあえずつくったので、けっこう適当です。
======
CREATE TABLE `ap_log` (
`id` int(11) NOT NULL auto_increment,
`lb` varchar(10) default NULL,
`a_datetime` datetime default NULL,
`remote_host` varchar(256) default NULL,
`remote_user` varchar(256) default NULL,
`x_docomo_uid` varchar(20) default NULL,
`x_up_subno` varchar(256) default NULL,
`x_jphone_uid` varchar(20) default NULL,
`request` varchar(1024) default NULL,
`last_status` int(4) default NULL,
`responsesize` int(10) default NULL,
`response_time` int(10) default NULL,
`recv_size` int(10) default NULL,
`send_size` int(10) default NULL,
`referer` varchar(256) default NULL,
`user_agent` varchar(256) default NULL,
`a_host` varchar(256) default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM
=====

perlスクリプトはこんな感じ。カラムが多くすぎてINSERTのところは意味不明。

アパッチログのパースは、Apache Combined Log を効率的にパースする正規表現メモ を参考にさせて頂きました。おかげで高速に動作しました。ありがとうございます。

(.*)よりも最短マッチの(.*?)のほうが早いそうです。自分では試してはいません(^^;
最短マッチを使わなかった場合、テキストを最後まで読んでしまうから遅くなるのかも。

=====
#!/usr/bin/perl -w
use DBI;

# データソース
my $dsn = 'DBI:mysql:apache_log';
# ユーザ名
my $db_user = 'apachelog';
# パスワード
my $db_password = 'xxxxx';

# データベースへ接続
my $dbh = DBI->connect($dsn, $db_user, $db_password,
{ RaiseError => 1});

if (@ARGV <>
{
die "USAGE: analizelog.pl apachelog\n"
}


my $filename=$ARGV[0];
my $line;
#idはauto incrementのためNULL
my $sth = $dbh->prepare("INSERT INTO ap_log (id,lb,a_datetime,remote_host,remote_user,x_docomo_uid,x_up_subno,x_jphone_uid,request,last_status,responsesize,response_time,recv_size,send_size,referer,user_agent,a_host) VALUES (NULL,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");

open( FH , "$filename" ) || die "Error: $filename $!\n";

while () {
chop;
my ($lb,$datetime,$remote_host,$remote_user,$x_up_subno,$x_jphone_uid,$request,$last_status,$responsesize,$response_time,$recv_size,$send_size,$referer,$user_agent,$host) = /^(.*?) (.*? .*?) (.*?) (.*?) (.*?) (.*?) "(.*?)" (.*?) (.*?) (.*?) (.*?) (.*?) "(.*?)" "(.*?)" (.*?)/;

#docomoのuidはrequestパスから取得。ここも?つけたほうが高速になるような気がする。
if ($request =~ /.*uid=(\w{12})/)
{
$docomo_uid=$1;
}else{
$docomo_uid="-";

}

$sth->execute($lb,$datetime,$remote_host,$remote_user,$docomo_uid,$x_up_subno,$x_jphone_uid,$request,$last_status,$responsesize,$response_time,$recv_size,$send_size,$referer,$user_agent,$host);
}

$dbh->disconnect();
=====

uidを1カラムにすればよかったなー。いつかやろう。
あとリクエストパスとreferも、もうちょっと細分化しないと、
満足な分析には使えないかも。