サイトを構築する際,ウェブで実運用する前に手元のローカル環境で振る舞いを試験することは当然あるわけだが,試験がうまくいったとして,それをそのままウェブにアップすればうまくいくかというと,そう簡単じゃない。ローカル環境からウェブ環境向けのカスタマイズが要るわけで,その環境設定の変更時に,ローカルで気付かなかった不具合が出る可能性も多々ある。その調整の負担はなるべく軽くしたいところ。
ここでは,筆者が試した手法を備忘録しておこうと思う。
● サイトごとの環境を自動設定
要は,環境設定を自動でしてくれる仕組みにすればいいわけだ。
とはいえ,それもまた一筋縄ではない。だいたい,誰でも見れる CGI
では,環境変数(%ENV)にユーザ名やホームディレクトリ(/home/user
など)が渡されないため,どちら(ローカルかウェブ上か)の環境下で実行されているのかをスクリプト自身が知る方法が限られる。
ひとつの方法としては,「ホスト名」は環境変数で渡されるのでそれを利用することが考えられる。まず CGI スクリプトを置いたディレクトリ(/cgi-bin など)に以下のソースを置く。
if( !($_ = $ENV{ HTTP_HOST }) ){ $_=`hostname`; chomp; } if( /^(shanaiserver01|localhost|127\.0\.0\.1)$/ ){ # ローカル試験環境の設定 } elsif( /^www\.hostname\.co\.jp$/ ){ # 実際のウェブ運用上の設定 }
で,「Apache の場合」または実行させるスクリプトが「シンボリックリンクではない場合」は,同じディレクトリに置いた CGI スクリプトで,最初のほうに必ず以下を置くようにして上記を呼び出せば,ローカル環境と実ウェブ上のサイトの設定が自動的にされる。
do "./siteconf.pl";
この方法の利点は,「内容が全く同一のファイルを単純コピーすれば済む」という点。環境に応じて設定ファイルを作り直す必要がない。
◆ hostname を再利用
siteconf.pl 処理終了時に,グローバル変数に hostname を保存しておけば,siteconf.pl の実行から戻ってから CGI 内で個別の環境設定に利用できる。
${^_HOSTNAME}= $_;
do "./siteconf.pl"; if( ${^_HOSTNAME}=~/^(shanaiserver01|localhost|127\.0\.0\.1)$/ ){ # CGI 特有のローカル環境の設定 } elsif( ... (以下「他ホスト環境下の設定」省略)
この ${^_HOSTNAME} のように ^_ で始まる変数は,必ずグローバル扱いになるらしい。詳しくは以下を参照。
あるいは呼び出す側で,たとえば $HOSTNAME などを our 宣言しておいて,そこに siteconf.pl 内で代入しても可能ではある。
◆ Apache 以外,シンボリックリンクは注意
ただ,Apache 以外の HTTP サーバソフトで,同じディレクトリ上にシンボリックリンクを置いて,実際のスクリプトファイルがそこにない状態で使っていた場合,上記「CGI スクリプト側の処理」のような書き方では,うまくいきそうにないケースがあった。筆者のローカル環境で使っている minihttpd というホストは,シンボリックリンクを辿った先で CGI が実行されてしまうらしい。たとえば,以下のような場合。
$> ls /home/user/cgis -rwxr-xr-x userreg.cgi $> ls /home/user/public_html/cgi-bin -rw-r--r-- siteconf.pl lrwxrwxrwx userreg.cgi -> /home/user/cgis/userreg.cgi
userreg.cgi の最初のほうで,前述した do "./siteconf.pl" を実行しているものとする。このスクリプトは,実際は /home/user/cgis にあるが,CGI 公開用ディレクトリの /home/user/public_html/cgi-bin にそのシンボリックリンクを置き,それをブラウザから呼び出した場合は,Apache ではうまくいくが,minihttpd ではダメらしい。調べると環境変数に以下のような違いがあった。
$ENV{ SCRIPT_FILENAME }="/home/user/cgis/userreg.cgi"
$ENV{ SCRIPT_FILENAME }="/home/user/public_html/cgi-bin/userreg.cgi"
minihttpd ではリンク先のディレクトリ上でスクリプトが実行されるようで,そこに siteconf.pl はなく do "……" が無視されるために,サイトの設定が正しく行なわれない。
これを回避するには,何らかの方法でスクリプトが呼び出されたディレクトリの情報を知る必要がある。シェルの pwd コマンドか,Perl のモジュールにある Cwd.pm を使うとうまくいくみたいだ。
$_ = `pwd`; chomp; do "$_/siteconf.pl";
use Cwd; do cwd."/siteconf.pl";
ただ,Cwd の場合は,他のメソッドも含めた準備などで,600 行ものソースを読むので,ひょっとすると pwd のほうが軽いかもしれない。
実行されているスクリプト名が実ファイルの場所ならディレクトリもそっちになり,そこに siteconf.pl はなさそうに思うが,上記のやり方で siteconf.pl と同じ位置が示されるから,これでいいのだろう。
ちなみに $0(=スクリプト名)を見ると,minihttpd ではディレクトリのないファイル名のみだった。Apache ではフルパス名だった。