それ多分IIS7でできるよ

mayuki
2010-12-13

こんにちは、mayuki です。

いま竹芝のすき家ユーザーに大人気なWebサーバーと言えば当然IIS7ですよね。そんなIIS7でPerlアプリケーション動かしたいですよね。
ご存じかと思いますがIISはWindows Server上で動作するWebサーバーで、IIS7はWindows Server 2008(Vista)世代のWebサーバーのことです。IIS7はIIS6からアーキテクチャまるごとだいぶ変わっているのでいろいろ便利でおもしろくなっています。

最近Perlでプログラムを書いたりしていないのですがPerlで書かれたアプリケーションをそんなIIS7で動かす機会はあったのでその時得たハマリどころなどを書いてみます。

対象動作環境

  • Windows Server 2008/2008 R2
  • IIS 7/7.5
  • Win32なPerl (Active Perlなど)

時代も時代ですのでIIS6のことは忘れましょう。あれは過去の遺物です。

IIS7でPerlアプリケーションを動かす手段

IIS7でPerlのアプリケーションを動かすには次の3つの手段があります。

  • CGIで動かす
  • FastCGIで動かす
  • ARR(Application Request Routing)を使う

それぞれ利用するパターンはこんな感じですね。

CGI
ごく普通のCGIアプリケーションを使う場合。
FastCGI
アプリケーションがFastCGIに対応している場合。
ARR(Application Request Routing)
ARRというのはIIS7の追加モジュールで、Apacheで言うところのmod_proxyでリバースプロクシにするというのと同じですので、アプリケーションが単体で起動できるようなものの場合に使えます。

それぞれの利点・欠点はこんな感じです。

CGI
利点ははまらなければ簡単。欠点は遅いのとクセではまるとちょっと厄介。
FastCGI
利点は高速なところ。欠点は設定がややこしく動かなかった場合の原因究明の難易度はかなり高い。
ARR(Application Request Routing)
利点はアプリケーションが起動すれば丸投げなので動く動かないで言うと簡単。欠点はモジュールの追加と設定知識

今回はCGIにフォーカスして説明します。なんか長くなりそうだし…。

とりあえずCGIで動かす

ということでもっとも基本的なCGIでPerl アプリケーションを動かす為の設定をしてみます。CGIの設定方法は割とWebに転がっているのでざっくりと説明します。

とりあえず簡単なCGIスクリプトを用意します。以下のような内容でindex.cgiとして保存しておきます。

use strict;
use CGI;

my $q = CGI->new;

print $q->header(-charset => 'utf-8');
print "初春かわいい";

ではこれをどこか公開するためのフォルダに配置しましょう。今回は C:\InetPub\wwwroot がサイトのルートとして、その下の C:\InetPub\wwwroot\Perl\ に設置することにします。

ファイルを設置したらインターネット インフォメーション サービス (IIS) マネージャを起動しましょう。
起動できたら先ほどファイルを設置したディレクトリをサイトのツリーから探し出します。

そして見つかったらそのフォルダを選択して、コンテキストメニューを開きます。開いたメニューの中に「アプリケーションへの変換」というのがあるのでそれを選択します。そうするとディレクトリがアプリケーションとして設定されます。

で、アプリケーションに変換できたら、真ん中の機能ビューで「ハンドラ マッピング」というのを開きます。開くとハンドラの一覧が出てきますので、その右側のペインの「操作」から「モジュール マップの追加」を選択します。

「モジュール マップの追加」ダイアログが出てきますので以下のように値をうめます。

要求パス
*.cgi
モジュール
CgiModule
実行可能ファイル (オプション)
"C:\Program Files\Perl\bin\perl.exe" "%s" %s
名前
CGI-perl

ちなみに各項目を簡単に説明しておくと…

要求パス
どの名前でリクエストが来たらハンドルするかという設定で、例えば*.plにすれば.plファイルでCGIが発動するようになります。
モジュール
IIS7のCGIモジュールを指定しています。これでCGIの設定だと認識されます。
実行可能ファイル
スクリプトインタプリタの指定です。Perlの実行ファイルと引数を渡す設定です。 引数の "%s" がスクリプトファイル名になります。二つ目はないとモジュール的にダメですが何だか忘れました。
名前
名前は先ほどのハンドラ 一覧や設定のキーとしてのみ利用されるモノなのでかぶらない限り自由につけることができます。


というわけで設定したらOKを押して閉じましょう。OKを押すと

この ISAPI 拡張機能を有効にしますか? [はい] をクリックすると、[ISAPI および CGI の制限] の一覧の "許可済み" の項目に、拡張機能が追加されます。[ISAPI および CGI の制限] の一覧に拡張機能の項目が既に存在する場合は、"許可済み" に更新されます。

とか言われますので「はい」を押します。

では早速ブラウザで http://localhost/Perl/index.cgi にアクセスしてみましょう。無事表示されましたか?ここまでで動かなかった人は次のトラブルシュートをご覧ください。

こんな感じで普通のCGIなアプリケーションも設定すれば動くでしょう。

CGIが動かないお!!!1

さて、CGIの設定をしましたが先ほどのような簡単なモノならともかくそこら辺に転がっていたりするモノを動かしてみると案外動かなかったりします。というわけでトラブルシュートです。

"404 - ファイルまたはディレクトリが見つかりません。"

ハンドラの設定が間違っているときによく表示されます。例えばPerlのパスが違うなどです。

"502 - Web サーバーがゲートウェイまたはプロキシ サーバーとして動作しているときに、無効な応答を受信しました。"

このメッセージは何らかの理由でCGIが死んだりしたときに出てきます。Apacheで動かしたときの500相当ですね。

まずはPerl.exeで直接実行してみましょう。そもそもモジュールが足りなくて死んだりする場合はすぐわかります。

動かしてみて大丈夫そうだったけどやっぱりIISで動かない…。そういうときはスクリプトの頭に

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

とか書いて実行してみましょう。こうすると大体動作して、何かwarningが頭についていたりするのが見えたりするようになります。

IIS7にはFREBという失敗した要求のナントカカントカというログ機構が備わっていますが、CGIのエラーはろくに情報がないのでこのローテクで回避するのが楽です。IISでCGIを動かすときにはおぼえてて損はないと思います。

で、warningが原因で502になるというのはどういうことかというと、どうやらIISのCgiModuleはSTDERRをSTDOUTと同様にクライアントへ出力しようとしてしまい途中でエラーとなるようです。
20世紀スクリプトを動かす場合などにこまったりしますね。

例えば先ほどのコードもこんな感じにするとすぐ動かなくなります。Apacheではerror.logにはなにやらでますが一応動きます。

use strict;

warn "------\n\n";
print "Content-Type: text/html; charset=utf-8\n\n";

print "初春かわいい";

で、じゃあどうするのかという話なのですが手っ取り早い方法はスクリプトの頭に

BEGIN { close(STDERR); }

とか書いてしまう方法です。これで忌まわしきWarningでエラーになることがなくなります。

本当のエラーが出たらCGIは死ぬし元々情報は残らないのでそこで調べればいいと思います。STDERRをどこかのファイルに出すなり、その辺はどうとでもやりようがありそうです。

ちなみにSTDERRに吐いてても処理しきってしまえれば動くことはあるので、知らないうちにヘッダーにwarningがでていることがあります。そういう意味でもSTDERRを何とかしておいた方が良いかもしれません。

/App/index.cgi は動くのに一階層下の /App/Hauhau/nantoka.cgi がうごかないお…

IISのCgiModuleはIISでアプリケーションに指定したディレクトリをワーキングディレクトリとして起動します。

そのため /App/ をアプリケーションとして指定してあっても /App/Hauhau/ をアプリケーションとして指定していない場合、 /App/ をワーキングディレクトリとして /App/Hauhau/nantoka.cgi を起動するのでPerlアプリケーション内で各種読み込みのパスが期待と異なってしまうことがあります。

というわけでCGIファイルを含むディレクトリはすべてアプリケーションに変換しておくのが安全です。

まとめ

  • IISでCGI動かすのは文章にすると長くてめんどくさい(けど実際の操作自体は少ない)
  • なぜかエラーになったらSTDERRを疑う
  • なぜかエラーになったらIISでのアプリケーションの設定を疑う

というわけでちょっとクセがありますがコツをつかめばCGIは楽勝ですね。FastCGIとかARRとかについてもふれる機会があればいずれ。

みなさんもIIS7でクリスマスをエンジョイしてください。