今日から、アクセスログ集計するスクリプトを作ります。


本日は、接続元のアクセス情報を取得するスクリプトを作ります。




では、早速コーディングです。

-------------------------------

#! c:/perl/bin/perl

#サーバ出力

print <<END;

Content-type: text/html

<!DOCTYPE HTML PUBLIC !-//W3c//DTD HTML 4.01//EN">

<html>

<head><title>かんきょうへんすう</title></head>

<body>
<table border="1">

<tr>
<th>環境変数名</th>
<th>値</th>
</tr>


<tr>
<th>HTTP_REFERER</th>
<td>$ENV('HTTP_REFERER')</td>
</tr>

<tr>
<th>HTTP_USER_AGENT</th>
<td>$ENV('HTTP_USER_AGENT')</td>
</tr>

<tr>
<th>REMOTE_ADDR</th>
<td>$ENV('REMOTE_ADDR')</td>
</tr>

<tr>
<th>REMOTE_HOST</th>
<td>$ENV('REMOTE_HOST')</td>
</tr>
</table>
</body>
</html>

END

--------------------------------------

http://127.0.0.1/tendays/4-1.cgi 実行!


Content-type: text/html

環境変数名
HTTP_REFERER ('HTTP_REFERER')
HTTP_USER_AGENT ('HTTP_USER_AGENT')
REMOTE_ADDR ('REMOTE_ADDR')
REMOTE_HOST ('REMOTE_HOST')


あれあれ・・・・。


環境変数の内容がでていないおかしいぞ。


$ENV('HTTP_REFERER') → $ENV{'HTTP_REFERER'}

$ENV('HTTP_USER_AGENT') →  $ENV{'HTTP_USER_AGENT'}

$ENV('REMOTE_ADDR') → $ENV{'REMOTE_ADDR'}

$ENV('REMOTE_HOST') → $ENV{'REMOTE_HOST'}


かっこがまちがっていたようだ。



http://127.0.0.1/tendays/4-1.cgi 再実行!

環境変数名
HTTP_REFERER
HTTP_USER_AGENT Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705)
REMOTE_ADDR 127.0.0.1
REMOTE_HOST




HTTP_REFERERは、ブラウザが4-1.cgiにアクセスする前に、参照していたページが入ります。

ブラウザに直接URLを入力した場合は、空です。


HTTP_USER_AGENTは、ブラウザのOS等についての情報です。 今回は、Win2000からのアクセスです。


REMOTE_ADDRは、クライアントのIPアドレスです。パソコンから直接アクセスすると、127.0.0.1になります。


REMOTE_HOSTは、クライアントのホストのドメイン名です。パソコンから実行した場合は、空です。


おしまい。

今日の授業で、アクセスカウンターを完成させます。


グラフィカルなカウンタを作ります。


今までは、CGIを直接呼び出していましたが、SSIという機能を使用して

shtmlファイルからcgiファイルを呼び出します。


では早速。


count.datファイルをc:/ApacehGroup/Apache2/htdocs/tendays/に作成


digitディレクトリをCD-ROMからc:/ApacehGroup/Apache2/htdocs/tendays/にコピー。


早速、コーディング。


3-5.cgi

------------------

#! c:/perl/bin/perl

$COUNTFILE = './count.dat';
$IMGPATH = 'digit/';
$FIGURES = 4;

#カウントファイルの更新

open(FILE,"+<$COUNTFILE") or die("エラー:カウントファイルが開けません");

eval{flock(FILE,2);};

$count = <FILE>;

seek(FILE,0,0);

print FILE ++$count;

close(FILE);

#カウント数の整形

$digit = sprintf("%0${FIGURES}d",$count);

#サーバ出力

print "Content-Type: text/html\n\n";

$i = 0;

while($i < $FIGURES) {

$n = substr($digit,$i,1);
print "<img src=\"$IMGPATH$n.png\" alt=\"$n\">\n";
++$i;
}

------------------


3-5.shtml

------------------

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head><title>SSIあくせすかうんたー</title></head>
<body>
<p>あなたは……
<!--#exec cgi="3-5.cgi" -->番目の訪問者です。</p>
</body>
</html>

------------------


http://127.0.0.1/tendays/3-5.shtml 実行!



成功!


こんな感じ




成功成功!



今回のポイント


http://127.0.0.1/tendays/3-5.shtml


SSIにより、CGIスクリプトが実行されている。


3-5.shmlのここね。ここ。


<!--#exec cgi="3-5.cgi" -->


3-5.cgiを呼び出しているだね。


3-5.cgiでは、ここがポイント。


ファイルを開いた後のここ。


#カウント数の整形

$digit = sprintf("%0${FIGURES}d",$count);


変数FIGURESは4だから。


$digit = sprintf("%04d",$count);


$countを513とすると。


sprintf関数で整形すると、0513になる。


つまり、$digitは0513



第2のポイントは、ここ。


$i = 0;

while($i < $FIGURES) {

$n = substr($digit,$i,1);
print "<img src=\"$IMGPATH$n.png\" alt=\"$n\">\n";
++$i;
}


substr関数で変数$digitから文字抜き出している。


例えば変数$digitが0513の場合。


$FIGURESが4だからループの回数は、4回。


1回目ループで、$nは0

print "<img src=\"$IMGPATH$n.png\" alt=\"$n\">\n";が実行され0が表示される。


2回目ループで、$nは5

print "<img src=\"$IMGPATH$n.png\" alt=\"$n\">\n";が実行され5が表示される。


3回目ループで、$nは1

print "<img src=\"$IMGPATH$n.png\" alt=\"$n\">\n";が実行され1が表示される。


4回目ループで、$nは3

print "<img src=\"$IMGPATH$n.png\" alt=\"$n\">\n";が実行され3が表示される。



以上、おしまい。

えらいひさしぶりの更新です。


今日の授業は、ずばり!


アクセスカウンターとしての機能をほぼ完成させます。


とのこと。


早速、はじめます。


いつもの通り、ひたすらコード入力。


よくわからないコードも今回は多数存在します。


あせらないあせらない。後で説明してくれるはずです。


できた!

---------------------------


#! C:/perl/bin/perl


#カウントファイルの読み込み


open(FILE, "+<./count.dat") or die("エラー:カウントファイルが開けません");

eval{ flock(FILE,2);};

$count = <FILE>;


#カウントファイルの書き込み

seek(FILE,0,0);

print FILE ++$count;

close(FILE);


#サーバ出力

print <<END;

Content-type; text/html


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">

<html>

<head><titel>あくせすカウンター</titel></head>
<body>
<p>あなたは・・・・$count番目の訪問者です。</p>

</body>
</html>

END
---------------------------------


さっそく実行っす!


http://127.0.0.1/tendays/3-4.cgi


-----------------------

Content-type; text/html あくせすカウンター

あなたは・・・・9番目の訪問者です。

-----------------------


あれおかしいぞ。


Content-type; text/html あくせすカウンター


これはなんだなんだ



<title>が<titel>になってました。 修正!

</title>が</titel>になってました。 修正!

Content-type; text/htmlのセミコロンはコロンだな。修正!



完成!



今日のポイント


前回の授業との相違点。


アクセスカウンターに同時にアクセスされたときの、制御が追加されています。


以下、その部分説明をまとめます。


#カウントファイルの読み込み


#ファイルを入出力用モードで開くことができたら処理をそのまま実行

# 開くことができなかったらエラーメッセージ。

open(FILE, "+<./count.dat") or die("エラー:カウントファイルが開けません");


#count.datファイルを排他ロックする。

#他の人がファイルを操作できなくする。

eval{ flock(FILE,2);};


#ファイルの中身(カウンターの数字)を変数$countに入れる

$count = <FILE>;

#カウントファイルの書き込み


#count.datファイルの先頭に書き込む位置を移動します。

#ファイルを読み込んだ後の決まりごとのようだ。

seek(FILE,0,0);


#count.datにカウントを+1して書き込みます。

print FILE ++$count;


#ファイルを閉じます

close(FILE);


ここで好奇心にかられ、count.datファイルを削除して実行してみました。


しかし結果は、Internal Server Error になりました。


open(FILE, "+<./count.dat") or die("エラー:カウントファイルが開けません");


die関数が正常に働いていないのでしょうか?


いろいろためしてみましたがうまくいきませんでした・・・・・。


ここは今後の課題かな。


ではおしまい。