情報処理技術2000年前期
第9回 CGIの仕組みと組み込み、Perlによるプログラミング

2000/6/22


CGIについて

CGI(Common Gateway Interface)は、その用語と実態が大きくかけ離れたものとして有名です(笑)。

CGIは、Webサーバーを通じて、ソフトウエア(プログラム)を動かす仕組みです。そうした機能がWebサーバーに組み込まれています。その仕組みを利用して、サーバー上でプログラムを動かしてしまうというのがCGIです。一般のWebページでは、単にリクエストに対応したファイルの中身をクライアントに届けるだけです。一方、CGIは、クライアントからのリクエストは「どのファイル」ということではなく、「どのプログラムを実行するか」ということを含めたリクエストを送ります。その結果、一般にはWebサーバーが機能しているサーバーの中でプログラムが起動し、そのプログラムがさまざまな処理を行います。そして、処理結果やあるいは処理した内容なども含めて結果をWebサーバーに戻し、それがクライアントに送り届けられます。

このように、サーバー上でプログラムを動かすというのがともかく、CGIの特徴です。次のようなメリットがあります。

一方、次のようなハードルもあります。

CGIの利用例

CGIのプログラムとしてよく使われているものは次のようなものです。いずれも、「書き込みをする」という動作を含んだものであることが分かります。一般のHTMLは読み込みのみです。書き込みを行うには、どうしてもCGIのような処理が必要になります。

上記のBBSやチャットの例は、自由に書き込んでかまいません。

CGIを実現する代表的な方法としてのperl

CGIにより、サーバー上でプログラムを動かすわけですが、その動かすプログラムを作成しなければなりません。基本的には、サーバーのOSで機能するプログラムなら基本的には何でもかまわないということにはなっています。プログラムを作成する手法はいろいろありますが、次のような要件があれば、何でもかまいません。

以上のような要件を満たせばいいので、たとえば、C言語で構築することもできるのですが、実はCGIを制作するための代表的な言語としてperlというものがあります。むしろ、現在は、CGIといえば無条件にperlで作るということになってしまっているほどです。ただし、一部では処理能力の点や、あるいはデータベースアクセスなど特殊な処理を必要とするために、perlではなくほかの手法も利用されています。CGIといえば必ずperlというわけではないことは知っておいてもらいたいのですが、一般に入手できるCGI用プログラムは、ほとんどがperlと言ってよいでしょう。

perlはもちろん、以上の条件を満たすのですが非常に重要な特徴があります。それは、一言で言えば、CGIプログラムを作りやすい環境であるということがいえます。まず、言語的、つまりプログラム作成という観点から見れば、次のような特徴があります。

また、プログラムを作る上での、作業面でのメリットも次のようなものがあります。

一方、次のようなデメリットもありますが、これらのデメリットはperlに限らない点もあるので、perlはいろいろな意味でCGI制作言語の中ではもっとも安全な選択肢となっているのです。

perlについては、具体的にはこの授業では行いませんが、実際に利用するCGIはperlで記述されたものです。後で実際にインストールする前に、どんなプログラムなのか中身をのぞいてみることにします。なお、一般に配布されているperlのCGIプログラムは、そのまま使うのではなく、一部を修正して使うようになっているものもあります。そういうものの場合、メモ帳などのテキストエディタで、開いて該当する個所を修正した上で、サーバーにインストールします。ただ、その場合、perlの知識が皆無だと編集作業が怖いと思うかもしれません。プログラム作成までは要求しないとしても、修正くらいはできるようになっておくことが望まれます。

perlについては、インターネットで実に多くの情報源があります。また、オリジナルのマニュアルもインターネットでダウンロードできますが、本格的過ぎて理解はしづらいでしょう。参考になるページを挙げておきます。ほかにもたくさんありますので、検索してみるといいでしょう。

CGIの構造

CGIがどのように機能するのかをもう少し詳しく見ていくことにしましょう。

GETとPOST

まず、Webクライアントからサーバーに対して、どのようなリクエストが送られてくるかということを見てみます。Webサーバーの動作にも関連するのですが、どういう手法かということを「メソッド(method)」と呼んでいます。メソッドには、GETとPOSTがあります。普通はこうしたことはあまり意識しないかもしれませんが、CGIだと意識する必要が出てきます。

まず、GETというメソッドは、Webサーバーに対して、必要な情報を取り出せという命令だと考えてください。Webブラウザのアドレス欄に、アドレスの文字列を入力して、returnキーを押すと、このGETのメソッドが送られます。クライアントからサーバーに、指定したアドレスをGETしろというリクエストが送られ、サーバーはそれに従って、ファイルを呼び出すなどして、結果をクライアントに戻します。

一方、POSTというのは、フォームをつかった場合に利用できる方式で、一般にはデータをサーバーに送り込むという意味合いを持っています。単に送り込んでもどうしようもないので、その送り込んだ結果を受け付ける先をアドレスとして指定します。アドレスを伴うのはGETと同じですが、POSTは、アドレスとは別に、フォームに書き込んだ内容をWebサーバーに送付します。アドレスを送付したあと、フォームに書き込んだ内容をネットワーク経由で送信できる形式に変換し、送信を行うと考えればよいでしょう。

具体的にには、formタグのmethodパラメータで、GETやPOSTを指定し、actionでアドレスを指定することになります。

CGIプログラムのコントロール手法

CGIを利用するときには、アドレスに実際に起動するプログラムを指定します。プログラムは、たとえばperlで記述したテキストファイルですが、通常は拡張子を.cgiにするのが一般的です。アドレスは、URL形式で指定しますので、Webサーバーの公開している場所に置くというのが基本になります。(一部のプロバイダでは置き場所を別に用意していることもあります。)

ここで、アドレスには付随した情報を含めることができます。それを、Query Stringなどと呼びます。形式としては、

http://《ドメイン名》/《CGIプログラムへのパス》?《Query String》
http://www.slis.keio.ac.jp/cgi-bin/wwwboard.cgi?test

のように、一般的なアドレスのあとに、?で区切って情報を記述します。単に記述するだけでなく、「action=write&dir=.」のように、名前付きで情報を記述することがあります。この場合は、「action」という情報の値が「write」という風に解釈されます。ここでは、&が区切り文字、=が名前とデータの区切りになるということを知っておくと良いでしょう。

こうしたQuery Stringの情報は、CGIプログラムに引渡すことができるので、CGIプログラムの動作をコントロールするのによく利用されます。

CGIでの処理内容

CGIプログラムでは、Query StringやあるいはPOSTによって送られた情報を、まずは取り出すという作業が必要になります。perlではそうした作業が比較的簡単にできるようになっているために、CGIで積極的に使われているということがあります。具体定期には、Query Stringは「環境変数」というOSが管理する情報として取得できます。環境変数では、他にメソッドがどちらなのかなど、たくさんの情報が得られるようになっています。また、POSTで送信したデータについては、OSの標準入力から得られます。

そして、プログラムで必要な作業を行い、結果をHTTP(HTMLではない)の形式で作成します。クライアントに戻すデータの作成も、それほど難しくはなく、OSの標準出力という手法をとっているため、プログラム自体は限りなくシンプルに記述できます。

ここで、CGIプログラムは複数のクライアントから同時に実行されるということを忘れないでください。ファイルの読み出しは同時に2つのプログラムで行っても多くの場合は問題ありません。一方、ファイルの書き込みを同時に行うことは非常に問題があります。一般には、どちらかの書き込み処理が正しく行われないことになります。こうした書き込み処理は、複数のプログラムが同時に起動しても、順番に行われる必要があります。そのため、あるプログラムが書き込み中には、別のプログラムは待つという動作が必要で、こうした動作はCGIプログラムに組み込む必要があります。こうした一連の手法を「ロック」と呼んでいます。ロックはいろいろな方式がありますが、いちばん単純なのは、あらかじめ決められた名前のディレクトリを作り、ファイルの書き込みを行い、作業が終わるとそのディレクトリを削除するという方式です。その名前のディレクトリが存在しているときには、別のプログラムがファイルへの書き込みをしているということが判断できるという具合です。こうしたファイルシステムを利用して、状態を記録するという手法がもっとも単純な方法ながら、UNIXを使う場合には確実かつ処理能力に悪影響を施さない方法だといえるでしょう。

掲示板の組み込み例

では、実際に簡単な掲示板のCGIプログラムを実際に組み込んで動かしてみます。動かすまでの過程で、必要な設定がどのようなものがあるかを見ていくことにしましょう。

掲示板の動作原理

こうしたCGIを利用することで、電子掲示板、すなわち、Webブラウザでメッセージを書き込んだり、あるいは書き込んだメッセージを一覧表示するなどの機能を実現することができます。メッセージを書き込む場合には、フォームを使います。フォームに入力した内容を、CGIで受け付けて、たとえばサーバー上のファイルに残します。ファイルの作成方法は千差万別ですが、ともかく、ファイルに書き込みを記録します。

一方、メッセージを読み出す場合には、書き込んだデータを記録したファイルの中身を取り出して、HTMLの形式に整えて、Webブラウザに対して送信すればいいわけです。

こうしたファイルの書き込みや読み込みという機能は、HTMLだけではできません。どうしても、サーバー上でプログラムを実行させないとできないのです。

CGIプログラムの仕様

CGIプログラムは、kimeicho.cgiというファイルで、中身はperlで作成されています。まず、このファイルが必要です。また、このプログラムを動かすためにjcode.plというファイルも必要です。これもダウンロードします。以下のリンクから、files.lzhというファイルをダウロードできます。それを解凍すると、2つのファイルが得られます。

→files.lzhをダウンロード

jcode.plはperlで作られたプログラムが収められており、汎用的に使うようなプログラムの断片を提供するものです。こうしたファイルなどを「ライブラリ」と呼びます。

kimeicho.cgiは次のような使い方をします。まず、メッセージを書き込むときには、POSTメソッドでkimeicho.cgiを呼び出しますが、Query Stringを次のように設定します。

http://......../kimeicho.cgi?action=write&dir=《データファイルのあるパス》

《データファイルのあるパス》というのは、データを書き込むファイルが存在するディレクトリのパスです。たとえば、kimeicho.cgiと同じフォルダを使うのなら、QueryStringは「action=write&dir=.」と指定します。

このdir以降で指定したディレクトリにある、messages.txtとmessages.tmpというファイルを利用します。メッセージは、messages.txtというファイルに溜め込まれますが、補助的にmessages.tmpというファイルも使います。これらは書き込み可能なファイルとして存在しなければなりません。

POSTメソッドを使うので、フォームを使って掲示板に記入する内容を記述しなければなりません。つまり、次のような仕様のフォームを作っておく必要があります。

名前(nameパラメータ) 想定されるオブジェクト タグ例
name テキストフィールド <input type="text" size="75" name="name">
mailaddress テキストフィールド <input type="text" size="65"
name="mailaddress">
message 複数行のテキストフィールド <textarea name="message" rows="4" cols="80"></textarea>

一方、データの読み出しでは、GETメソッドを利用して、kimeicho.cgiを次のような形式で呼び出す必要があります。《データファイルのあるパス》については、書き込み時と同じ設定にしておく必要があります。

http://......../kimeicho.cgi?action=write&dir=《データファイルのあるパス》

それから、《データファイルのあるパス》にindex.htmlという名前のファイルが作られているということが想定されています。書き込みをした後や、あるいはメッセージの一覧表示をした後に、「戻る」ボタンが必要だと考え、その戻り先として、とりあえずは、《データファイルのあるパス》にあるindex.htmlというファイルに固定しました。

想定として、次のようなページ構成になります。

そういうわけで、こうした仕様に合致するindex.htmlファイルを作成します。(作成例

CGIプログラムの利用例を、index.htmlの中にどのように組み込まれるかというところがポイントになります。まず、書き込むメッセージを入力するためのフォームを作成しますが、そのフォームのsubmitボタンをクリックしたとき、POSTメソッドでkimeicho.cgiが呼び出されるようにします。

そして、掲示板の内容を読むのは、リンクで作っていますが、単なるアドレスへのリンクではなくQuery Stringを含んだリンクです。リンクは、無条件にGETメソッドになります。

サーバーへのインストール作業

以下、この色の文字の作業は、一般的にCGIインストールで必要な作業です。黒字はこのkimeicho.cgiで必要とする作業ですが、同じような作業を必要とするような別のCGIプログラムもあります。

フォルダにまとめる すでにいくつかファイルができているので、これをそのままサーバーにアップロードするとややこしくなるだけです。そこで、利用する必要なファイルをまとめたフォルダを作っておきます。たとえば、「myboard」という名前のフォルダを作っておくことにします。ここまでに出てきた、kimeicho.cgi、jcode.pl、index.htmlをこのフォルダに入れておきます。

データを書き込むファイルを用意する さらにmyboardフォルダに、messages.txt、messages.tmpというファイルを作成します。このファイル名でなければなりません。CGIプログラムで、このファイル名で作業するということが決められています。中身は空でもいいのですが、メモ帳は中身が空のファイルを保存できません。その場合は、改行を1つ入れただけのファイルであれば、問題はないので、ともかく2つのファイルを作ります。

ロック用のフォルダを設ける さらに、myboardフォルダ内には、lockという名前のフォルダを作成します。これも、lockという名前のフォルダでなければなりません。

ファイルをコピーする 次に、FTPソフトを起動して、以上のファイルをWebサーバーにコピーします。たとえば、public_htmlの直下に、myboardのフォルダごとコピーすれば良いでしょう。ここで、転送モードは必ず「ASCII」にします。こうしないとプログラムは動作しません。

アクセス権を設定する 次にアクセス権を以下のように設定します。これも、FTPクライアントで設定できますが、できないときには、telnetでログインして、chmodコマンドで行います。

ファイル名 アクセス権
kimeicho.cgi 755
message.txt 666
messages.tmp 666
lock(もちろん、ディレクトリ) 777

アクセス権の設定をしないと正しく機能しません。通常、UNIXでは作成したファイルあるいはFTPでコピーしたファイルは、「実行可能」な設定にはなっていません。kimeicho.cgiについては実行可能にしなければなりません。ここで、UNIXにはアカウントという考え方があるというのを思い出してください。つまり、誰が処理するのかということが本来明確になっているはずです。ただ、実際にCGIプログラムが起動した場合、どのアカウントであるかということは、サーバーの設定に依存することもあり、いちがいにいえません。そこで、オーナー、グループ、全員の3つのアクセス権を同一に設定してしまうのが確実な方法です。つまり、書き込みが必要なmessages.txtは、もしオーナーのアカウントでアクセスするのであれば、600でもいいはずですが、そうでないことも想定されるので、666というアクセス権にします。アカウントが確定された状況では、なるべくセキュリティを確保したいので、余計なアクセス権の付与は行わないのが一般的です。

これでOKのはずです。index.htmlを開けば、書き込みができます。書き込みのテストをして読み出しを行えば、動作は確認できるはずです。

テキストファイルの改行コード

テキストファイルの改行は、OSごとに違ってしまっています。Windowsでは、CR+LFの2バイトですが、UNIXはLFの1バイトです(さらにMacintoshはCRだけの1バイト)。HTMLでは、改行はどれでも同じように扱われるのですが、CGIプログラムは、OSの改行コード形式と違っていては、正しく機能しません。

FTPでASCIIモードで転送することによって、テキストファイルは転送先のOSでの改行コードにあわせて中身が変換されます。Windowsにあるファイルでは、Windowsの改行コードになっていないと、メモ帳のように行末でも改行しないということになり不便です。転送時にFTPでコード変換をするのが基本です。

実際に転送されたファイルが正しくUNIXの改行コードになっているかを調べるには、やはりFTPソフトを使います。FTPソフトでBinaryモードにして、View機能を使います。すると、UNIXサーバーにあるままがダウンロードされて、たとえばメモ帳で開くことができます。行末であるはずの部分が黒い四角で改行されていないのであれば、正しいUNIXのテキストファイルであることが確認できます。

perlプログラムの書き換え

perlのプログラムで、拡張子がcgiのものは、1行目に、perlの処理システムを呼び出す特別な記述を書き込みます。この処理システムは、サーバーごとに存在場所が違っているため、基本的にはサーバーによって書き換えなければなりません。SLISのサーバーでは、以下の記述でOKです。

#!/usr/local/bin/perl

また、プログラムによっては、sendmailというメール送信コマンドを呼び出す必要があります。そのコマンドのパスをプログラムに記述するのですが、SLISのサーバーでは、

/usr/lib/sendmail

というパスで動きます。

本来、こうしたパスは、telnetで接続してwhichコマンド(たとえば「which perl」)で参照するのが基本なのですが、必ずしもwhichコマンドで得られた情報とおりということではなく、結果的にはサーバー管理者より教えられた情報をもとにしないと何も分からないということになります。

その他、メッセージを独自にカスタマイズするようにソースプログラム中に支持がありますが、気をつけることは、もともと、" " で囲ってあった文字列の場合、この"は消さないようにすることです。また、こうした文字列中に"を記述するには、\"と記述することです。なお、文字列を、""で囲まないで記述するような場合もあります。


本日の課題

以下の中から2つを選択して、自分のサイトに組み込むこと。いずれも、インストール方法が記載されているので、それをよく読んで、インストール作業を行うこと。

www-mail Ver 3.00
http://wakusei.cplaza.ne.jp/twn/wwwmail.htm

www-board Ver 2.53
http://wakusei.cplaza.ne.jp/twn/wwwboard.htm

www-chat Ver 2.54
http://wakusei.cplaza.ne.jp/twn/wwwchat.htm

www-lng Ver 2.05
http://wakusei.cplaza.ne.jp/twn/wwwlng.htm

www-count Ver 3.00
http://wakusei.cplaza.ne.jp/twn/wwwcount.htm

www-srch Ver 3.04
http://wakusei.cplaza.ne.jp/twn/wwwsrch.htm

miniBBS
http://www.rescue.ne.jp/cgi-rescue/cgi?minibbs

bbsT-Vote
http://www.mytools.net/cgitools/vote7.html

T-Note
http://www.mytools.net/cgitools/note4.html

TchaT Ver 2.01
http://www.mytools.net/cgitools/chat2.html


参考:CGIプログラム検索サイト http://www.active-line.com/cgi/


←「情報処理技術」のホームページへ