さて,買ってきた本は,「Windowsで学ぶCGI&Perl」である.・・・とゆーか,近所の本屋さんでCGI関係っていうとこれしかなかった・・・.それにしてもLinuxはどーした>>わたし.
発行日がなぜか未来なのが気になるけど,とりあえずCD-ROMからActivePerlというやつをインストール・・・しようとしたら,いきなりエラーメッセージが出て終わってしまった.
「このインストレーションパッケージはWindowsインストーラサービスでインストールできません.新しいバージョンのWindowsインストーラを含むWindowsサービスパックをインストールする必要があります.」
・・・なんですと?
Microsoftのサイトから
http://download.microsoft.com/download/platformsdk/wininst/1.1/w9x/EN-US/InstMsi.exe
をダウンロードして実行しろってさ.へーへーわかりました.どーせならこれもCR-ROMに入れといてくれればいいのに.
Windows Installerを実行してから,再度ActivePerlインストールにトライ.インストールが終わるとリリースノートが出てきたけど・・・やっぱりエーゴ.わけわからん.
さて,ちゃんとインストールできたかな〜〜.MS-DOSコンソールを開いて,バージョン情報を表示してみる.
C:\WINDOWS>perl -v
コマンドまたはファイル名が違います.
ありっ?
インストール中にエラーメッセージも出なかったし,"perl"ってフォルダもちゃんとできてるし,その中の"bin"ってフォルダにはちゃんと"perl.exe"ってファイルもある.これで実行できないっていうのは・・・
これは,よーするに,いわゆる「パスが通ってない」状況ではないかしら? パスを通すのってどうやったっけな.
C:\WINDOWS>set path=c:\perl\bin
でよかったっけ・・・?
C:\WINDOWS>perl -v
あ,できたできた.
さてつづいてWWWサーバのインストールだ.WWWサーバはAN HTTPDというやつ.
インストール方法は,zipファイルを解凍して,フォルダ名を「httpd」にするという,いたってシンプルなもの.
さて,動作確認.httpd.exeを起動して,ブラウザも起動し,
http://localhost/readme.html
を見てみると,httpdの説明が現れた.おっけ〜〜! 動作確認終了.
このlocalhost(=ドキュメントルート)は,デフォルトではさっき作ったhttpdフォルダを指しているらしい.
ドキュメントルートの場所はオプション設定で変更できる.ほかにも,perlやらCGIやらもオプション設定してやらなければならない.この辺はよくわからないので書いてあるがままやっておこう.
はて? SSIってなんだろ? どっかで聞いたような気がするんだけどな.Server Side Include・・・HTMLのなかにCGIの実行結果を埋め込むモノ・・・って,本には書いてある.
<!-- #include virtual="./sample.cgi" -->
HTMLのなかに,こーゆー風に書くんだって.アクセスカウンタなんかに使うものらしい.でも今わたしが使っているアクセスカウンタは,HTMLファイルの中に,
<IMG SRC="http://www6.tkcity.net/~yuri/cgi-bin/count/ct.cgi">
こんなふうに書いてあって,SSIは使ってないみたい.ただCGIの結果を画像ファイルとして出力しているだけ.
CGIが使えてもSSIが使えないホームページスペースも結構あるとか.・・・? よくわからない.
とりあえず,TkCityのユーザサポートには,「SSIを使用するときは,htmlのファイル名をshtmlとしてください」って書いてあって,ファイル名を変えさえすればいちおう使えるみたいだけど・・・. 何がどう違うんだか?
でも,ナゾがひとつ解けたぞ.
今まで,ほかの人のページを見るとき,なんで*.shtmlってのがあるのかな〜〜って不思議だったんだけど,そーか,あれはSSIとやらを使ってたのね.
とゆーわけで,PerlもWWWサーバーもインストールしたし,さっそくプログラムに行ってみよ〜〜〜!
原理はとっても簡単(なように思われる).カウンタ値を保存してあるファイルの値を読み込み,+1して保存する.そして新しいカウンタ値を表示する.
アクセスカウンタには,SSIを使う方法と使わない方法があるそうだ.何がどう違うかっていうと・・・
さっきも書いたけれど,SSIの場合は,
<!-- #include virtual="./counter.cgi" -->
をHTMLの中に記述し,アクセスカウンタ本体であるcounter.cgiの出力結果は,たとえばカウンタ数が12ならば,
<IMG SRC="./images/0.gif">
<IMG SRC="./images/1.gif">
<IMG SRC="./images/2.gif">
こんなふうになる.そして,HTMLファイル中で,アクセスカウンタを呼び出している部分がそっくり,CGIの出力結果に置き換わってブラウザに表示される.出力する結果は画像である必要もなく,
<h1>012</h1>
のようにテキストで書き出すこともできる.・・・地味だけど.
一方,SSIを使わない場合は,HTML中に
<IMG SRC="http://www6.tkcity.net/~yuri/cgi-bin/count/counter.cgi">
こう記述し,CGIをIMGタグで呼び出す.IMGタグなので,CGIが出力する結果は画像ファイル一個の名前に限られる.たとえば,CGIの出力結果counter.gifを受け取ると,CGIを呼び出している部分は,
<IMG SRC="counter.gif">
に置き換わり,ブラウザに表示される.
ただし,カウンタみたいに数字がいくつか並ぶ場合は,各数字をつなげて,一個のファイルにまとめるという作業が必要になる.
よーするに,HTMLとCGIとの間でやり取りするデータが違うってことなのかしら・・・?
ま,いいや.とりあえずSSIでやってみよっ!
Perlプログラムの最初の一行は"#!"ではじまる「お約束」,Perl本体のある場所の宣言だ.今わたしはPCでWWWサーバを動かしていて,Perl本体はC:\perl\bin\perlにあるので・・・
#!C:/perl/bin/perl
この一文から,プログラムは始まるのである・・・
わからないことは,ひとつずつつぶしていくしかない.というわけで,まずは「ロック」のお話.
アクセスカウンタってのは,アクセス回数を保存してあるファイルの内容を読み込んで,それに+1して再びファイルに書き出す,ただこれだけのものなんだけれど・・・ホームページの場合,不特定多数の人が同時にアクセスするかもしれないってことを考えなくちゃいけない.
ある人がアクセスファイルの内容を読み込んだ,そこまではいい.その後,それに+1をしてアクセスファイルに書き出そうとする・・・その直前に,別の誰かがアクセスファイルの内容を読み込んだ場合にどうなるかってことだ.
最初の人も後から来た人も,同じカウンタファイルの値を読み込み,それぞれ+1するだけ・・・つまり,せっかく二人も来てくれたのに,カウンタは1しか増えないことになってしまう.
こういう事態を避けるため,カウンタ値を読み込んでから+1して書き出すまでの間,ほかの人がカウンタファイルを読み込めないようにする.これをロックという.後から来た人は,最初の人がカウンタファイルに書き出し終わるのを待って,改めてカウンタファイルを読み込む.
これは,ワードやエクセルのファイルを使っているときにもけっこう出てくる.誰かが編集中のファイルを別の人が編集しようとしても,読み込み専用でしか開けない,というやつだ.
手順としては,
この本には,いろいろやり方があるけど・・・と前置きを置いた上で,ひとつの方法を紹介していた.やり方がいっぱいあるなら,どうせならいっぱい紹介してくれればいいのに・・・.
紹介されているやり方は,"lock"という名のディレクトリを使用するもので,lockディレクトリがある間はロックがかかっていると考える.
まず,何か処理をするためにロックをかける,すなわちlockディレクトリを作る.無事lockディレクトリを作ることができたら,処理を始める.もしlockディレクトリを作れなかったら,lockディレクトリがすでに存在する=誰かがすでにロックをかけているということなので,しばらく待ってからまたトライする.
処理を終えたら,ロックを外す,つまりlockディレクトリを削除する.そうするとロックが外れるのを待っているほかの誰かがまたロックをかけ,処理を始めることができる.
そっかー,aska.cgiで出てきたlockディレクトリのナゾがやっと解けたわ・・・.
この「ロック」部分をサブルーチンとして,アクセスカウンタCGIから呼び出す形にする.サブルーチンファイルって,ファイルのおわりにナゼか「1」ってのを書かなきゃエラーになっちゃうんだそーだ.
さて,無事ロックがかかったら,ファイルの内容を書き換えてアンロックをし,HTMLタグを生成するわけである.
具体的にいうと,たとえばカウンタ数が23なら,
<IMG SRC="./images/0.gif">
<IMG SRC="./images/2.gif">
<IMG SRC="./images/3.gif">
というやつが出力される必要がある.言うまでもないけど,imagesディレクトリ下の0.gifとか1.gifとかっていうファイルは,それぞれの数字に対応する画像だ.サンプルプログラムによると,まずは$count_imgという変数にカウンタ数"023"を入れておいて,
$count_img =~ s/(.)/<IMG SRC=".\/images\/$1.gif">/g;
で,変数$count_imgにカウンタ表示用のタグが生成されるらしい・・・ここでは,パターンマッチングを使って置換をしているわけだ.
なんかいろんな演算子をいっぱい使ってるからわけわかんなくなってるわけで,ひとつずつつぶしていくと・・・
まず,「=~」だけど,これは,この演算子の左側の変数を右側のパターンマッチングの対象とするって意味.つまり,今は,変数$count_imgに代入されている「023」が対象パターンってことになる.
次の「s///」は文字列の置換である.「s/置換前/置換後/パターン修飾子」だから,ここでは,「(.)」を「<IMG SRC=".\/images\/$1.gif">」に置き換えるということだ.パターン修飾子の「g」がついているから,該当する文字をひとつ残らず置換する.「g」がなければ,置換は最初の一文字についてしか行われないみたい.
さて,そこで,この「(.)」って何なの? って話なんだけど・・・.「()」って,対象パターンをグループ化するものなんだって.そして中の「.」は任意の一文字を指すもの・・・よくわかんないけど,ここでは,「0」「2」「3」の文字それぞれを一つずつのグループとして扱っているということになる.
あと,「$1」ってのはグループ化した値を呼び出す,つまりこれも「0」「2」「3」それぞれってわけ.
なんか自分でもよくわからなくなってきちゃったけど,こうやって,
「0」を「<IMG SRC=".\/images\/0.gif">」
「2」を「<IMG SRC=".\/images\/2.gif">」
「3」を「<IMG SRC=".\/images\/3.gif">」
というふうに置換している.なんで「/」の前に「\」がついているのかよくわからないけど,多分置換の区切りを示す「/」と区別するためだろうと思う.
HTMLを出力するときは,出力のあたまには,やはりお約束のHTTPヘッダとゆーやつをつける.
print "Content-type:text/html\n\n";
MYサーバで実行してみると・・・わーいカウンタ増えてる! 更新するたびに増えていってる!
じゃあTkCityにアップロードだっ!
・・・あれっ?
どーして,動かないのよっ!(怒)