Windows 用 Perl CGI プログラム作成の留意点

開発環境の Windows では期待通り動作したのに、納品してみたら「動かない」「エラーになる」と言われた経験をもとに、Windows で稼動する Perl の CGI プログラムを書くときのマイナーな留意点をご紹介します。

問題の発生した Windows 環境は直接アクセスできない事が多いので理由についてはあいまいですが、経験則としてご紹介します。

一般的な留意点( binmode を使う、fork は避ける、など)については下記の Microsoft サイトなどを参照して下さい。
http://www.microsoft.com/japan/technet/prodtechnol/windows2000serv/technologies/iis/deploy/depovg/lintowin.mspx

対象者

Perl で 一通り CGIプログラムは書ける方、UNIX ではうまくいくんだけど、Windows にしたらよく分からないエラーが出たんだけど??という疑問をお持ちの方を対象としています。

BEGIN、END、INIT ブロックを使用しない。do も避ける

IISで稼動させる場合、BEGIN、END、INIT ブロックが期待通り実行されない場合があります。
IISの設定(アプリケーションプールの設定?)によるのではないかと予想していますが、問題の具体的な原因は不明です。

具体的な現象としては、INIT ブロックで設定した変数の初期化が行われないなどがあります。

同様に、do の利用も避けた方がよさそうです。
do の中でエラー処理(ブラウザ画面つまり STDOUT にエラー表示)をしていた場合、環境によってはそれが表示されない場合がありました。

他の処理(たとえばシステム内ファイルへのエラーログの書き込みなど)なら実行できたのかどうか、という点については不明です。

大量の書き出しを直接行わない

Apache2.x でよく発生しますが、$|=1; などでフラッシュを設定していても処理が完全に終わるまで書き出しが行われない場合があります。

このため、大量の出力をメモリ内に溜め込んでしまって処理が終わらなくなる事があります。
STDERRへの出力(warn)も同様に溜め込んでしまうので、開発中にエラーログに大量のデバッグ出力をしていると処理が終了しなくなる場合もあります。

Apache2.x のバグのようなのですが、「問題が解消された」という記載があるバージョンでも同様の問題が発生したことがあり、他の要因もありそうです。

問題解消の方法

ファイルシステム内に大きなファイルを書き出す場合、処理を行うプログラムを別に Perl で書いて、CGI からは system コマンドで実行したら問題が解消しました。
必要なパラメータは別プログラム側で Getopt::Std モジュールなどを利用して、CGIからはオプションとして渡します。

イントラネットのユーザ管理に注意

システム内にファイル(例えば掲示板のログファイルなど)を生成する機能のある CGI をイントラネットで使用する場合、ウェブサーバが IIS であれば実行ユーザに注意する必要があります。
ユーザ設定に気をつけないと、一度作成したファイルを他の人がCGIにアクセスした時に更新できなくなる場合があります。

IIS の場合、アクセスしているユーザは「IUSR_****」(「インターネット インフォメーション サービスへ匿名アクセスするためのビルトイン アカウント」)だと思っている場合が多いのですが、IISのデフォルトでは 「IUSR_****」による匿名認証のほか、「Windows 統合認証」(旧いWindowsの場合は「Windows NT チャレンジ/レスポンス 認証」)も並行して行う設定になっており、どちらも使える場合、後者が優先されます。

また、書き出されるファイルはCGIにアクセスした時のユーザの所有となります。

イントラネットの場合、Windows ドメインにログオンしている状態で CGIにアクセスしますので、CGIが作成するファイルは、作業中のマシンにログオンしているドメインユーザのものとなります。
このため、これを後で他のユーザが変更しようとすると、パーミッションの問題で変更できないという問題が生じます。
書き出すファイルを保存するディレクトリの設定で「Everyone」にフルコントロールを与えている場合でも、これはホストに直接ログインしているユーザに対する権限設定となりますので、ネットワーク経由のユーザは別口で解釈されエラーが起こります。

問題解消方法

この問題の解消には、いくつかの選択肢があります。

1.Windows 統合認証の利用をやめる(IISのプロパティで、チェックをはずす)

2.ディレクトリのプロパティ設定で「ネットワークユーザによる変更を許可する」設定にする。(バージョンによってはこの設定は無い場合もあります。)

3.Windows 統合認証 と 匿名アクセスを両方無効にし、基本認証をかけて、CGIにアクセスするユーザを1つにまとめる。
(ディレクトリに書き込み権限のあるローカルユーザのアカウントとパスワードを使用します。)