[ CGI集 | CGI解説 | Perl解説 | HTML解説 | LinuxMemo | Q&A | QuizLink ]      

MyTools.NET - CGIってなあに?

 実はここに書いてあることを理解しなくても、ページの説明どおりにやれば掲示板の設置はできます。でも仕組みを理解しておいたほうがHP作りが数倍楽しくなります。CGIという言葉しか知らない全くの初心者から、自分の家でサーバ立てて実験したいというマニアな方までどうぞ。

目次

CGIってなあに? 〜 「CGIを書く」「CGIはこちらからダウンロード」は誤り

 CGIは正確にはCommon Gateway Interface。技術的に言うと「WWWサーバが外部プログラムを呼び出すための仕様」です。ここで注意していただきたいのは「仕様(Interface)」という言葉。CGIはJavaのようなプログラミング言語ではない、ということです。「プログラムの実行結果をページとして表示させるための橋渡し役(Gateway)」であって、縁の下の力持ちなのです。

 ですから「CGIを書く」というと、「WWWサーバに外部プログラムを実行させるインターフェースを書く」という意味になってしまいます。これは厳密には正しい言葉ではないことが分かると思います。CGI用に書かれたプログラムのことをCGIプログラムといいます。先ほどの表現は、正しくは「CGIプログラムを書く」ということになります。(現実にはそこまで細かく区別する必要もないですが。私もしてませんし:p。)

 CGIプログラムに使う言語は何でも構いません。<HTML>〜</HTML>の間を表示するようなプログラムを書き、いくつかの規則を守れば、あとの処理は全てサーバがやってくれます。標準出力(いわゆるprint文)が可能な言語であれば構いません。CでもshでもJavaでも大丈夫です。(ただし、サーバマシンにその言語の実行環境があることが絶対条件です。)

 当ページのCGIプログラムはすべてPerlという言語で書かれています。他のページもPerlを使用していることが多いようです。PerlはCGIを書くのに向いている言語だからです。(詳しい解説は後述。)

[index]

 

CGIの仕組み 〜 生かすも殺すも設定次第

 CGIプログラムの動作は、通常のHTMLの場合と比較すると分かりやすいです。通常のHTMLの場合、ユーザがHTMLのURLをリクエストすると、WWWサーバは指定されたHTMLファイルをユーザに返します。この際、WWWサーバはHTMLファイルに手を加えることはありません

 それに対しCGIの場合、ユーザがCGIプログラムのURLをリクエストすると、WWWサーバがCGIを通してそのプログラムを実行し、その実行結果をユーザに返す、という手順が行われます。(下図)

 HTMLファイルは .html、画像ファイルには .gif, .jpg と決まっているように、CGIプログラムにも特定の拡張子を付ける必要があります。これはWWWサーバの設定で決めますが、多くの場合.cgiという拡張子になっています。WWWサーバはリクエストされたリソースの拡張子を見て、それが通常のリソースなのかCGIプログラムなのかを判定するわけです。

 また、「特定のディレクトリ下でのみCGIプログラムの実行を許す」という設定にすることも可能です。これは、サーバ内のあちこちにプログラムが分散し、メンテナンスがしづらくなることを防ぐためのものです。よく「プログラムの内容がそのまま表示されてしまう」というケースがありますが、これはCGIプログラムを置いた場所がCGI実行可能な場所でないことが考えられます。

 CGIは外部プログラムを実行するため、サーバに非常に負荷がかかります。(詳しくは後述。)この負荷を嫌い、WWWサーバによってはCGIの使用を全面禁止にしているところもあります。設定で「CGI禁止」になっているサーバでは、ユーザがどうあがこうとCGIを使うことはできません。

CGIプログラムの動作


[index]

 

CGIで何ができるの? 〜 HTML + CGI = 掲示板?

 CGIを使うと、

  • フォームからの入力を受け取る
  • サーバ上にあるファイルを読み込む
  • サーバ上のファイルにデータを保存する
  • (ブラウザに)プログラムで生成した文字などのデータを出力する

等のことができます。例えば、掲示板やチャットは、「フォームに会話を書き込む内容を受け取りサーバ内のデータファイルに保存するデータファイルを読み込むそれを整形してHTMLとして表示する」という流れで構成されています。

 どんなに複雑で高機能なCGIプログラムでも、この基本的な流れは変わりません要はこの流れの中にいかに複雑な処理を織り込むかです。データファイルに票数を保持しておけば「投票システム」になりますし、データファイルに問題、選択肢、解答を保持しておいて、フォームからの入力と比較して、正しければ○を、間違っていれば×を出力するようにすれば「クイズシステム」になります。

 又、プログラミング言語の持つ機能も、当然使うことができます。例えば、Perlの場合、

  • 現在時刻の取得(time
  • ファイルの更新時刻の取得(stat
  • 文字の簡単な暗号化/復号化(crypt
  • 全てのUNIXコマンド

などを使うことができます。特に最後の機能は便利な反面、「CGIは危険」と言われる原因の一つになっています。(詳しくは後述)

[index]

 

CGIで何ができないの? 〜 最大の弱点はセッションレスとGUI

 逆に、CGIでは以下のことができません。

(1) CGIプログラム側が任意のタイミングでユーザ画面を書きかえるようなシステム
.....例えば、「誰かが書き込んだときに、そのチャットルームに接続している全ユーザのブラウザにその書き込み内容を反映させる」というようなことはできません。
 WWWで利用されている通信方法(HTTP)は、ブラウザがページを要求する毎にサーバに接続しに行き、ページを読み込み終えたら接続を切る、という形態です。(このHTTPのように、接続状態を保持しない通信方法のことを「セッションレスなプロトコル」といいます。)CGIもこのHTTPサーバ側では「今このページを見てる(接続している)のは誰と誰」というような接続状況の情報を持ちません。従って、サーバにあるプログラム側から、ユーザのブラウザに働きかける、ということは一切できません。ユーザが画面を更新するには、ブラウザのリロードボタンを押すしかありません。良くあるCGIチャットシステムでは「一定時間毎に」リロードすることによって情報を更新していますが、これはICQのような真のリアルタイムなチャットとは違うことが分かると思います。

(2) (単体で)別のサーバにあるファイルを読み書きするようなシステム
.....CGIプログラムはサーバ内で動く単体のプログラムです。単体のプログラムが使用できるファイルは、通常同一サーバ内のものだけです。例えば、「自分のプロバイダにCGIプログラムを置いて、http://www.yahoo.co.jp/ にあるデータファイルを読み込んで使用する」ということはできません。"Socket" や "CORBA" と呼ばれる技術を使用すれば不可能ではありませんが、その場合受け手側のプログラムも書く必要があります。(掲示板程度でそこまでやる価値はないでしょう。)

(3) HTML(ブラウザ)の表現範囲を超えるようなGUI
.....CGIは実行結果を呼び出し元のブラウザに返します。HTMLを吐き出すようなプログラムを書けば、それがページとして表示され、GIF画像を作るようなプログラムを書けば、その画像がブラウザに表示されます。しかし、別のアプリケーションを立ち上げたり、特殊なデザインのページを作ったりすることはできません。例えば、簡単なグラフ表示でも、Excelのグラフ作成機能を使うわけにも行かず、HTMLで<IMG>タグのSIZEを大きくしたり小さくしたりという小技で対処するしかありません。「折れ線グラフ」は実質不可能です。いくらプログラムといっても、表現がブラウザ、HTMLの外に出ることはありません。要するに、「ブラウザ、HTMLにできないことはCGIプログラムにもできない」ということです。

[index]

 

フォームの入力を受け取る仕組み 〜 掲示板もチャットもカウンターも要はコレ

 WWWブラウザがCGIプログラムに値を渡す仕組みの簡単な例を解説したものが下図です。まず、HTML文書の中に文字を入力する「フォーム」を配置します。一つのフォームには複数の入力欄を設けることができます。それぞれの入力欄には「NAME」というラベルがつけられています。フォームには、入力された文字をどのCGIプログラムに渡すか、という属性「ACTION」があります。ユーザがフォームの入力欄に文字を入力し、「SUBMIT」ボタンを押すと、入力内容がCGIプログラムに環境変数(GET)又は標準入力(POST)を通して渡されます。どちらを通すかはフォームのMETHOD属性で変更できます。具体的には「NAME=値&NAME=値&…」と入力の数だけ続いた文字列となってプログラムに送信されます。プログラム側では、この文字列を受け取り、処理を施した結果を標準出力にHTMLで出力するようなコードを書けばよいのです。
ブラウザがCGIプログラムに値を渡す仕組み


[index]

 

Perlって何? 〜 私は最初「ぺり」と読んでました

 Perl(パール)は,正式には「Practical Extraction and Report Language(データ抽出とレポート作成用の実用的な言語)」。名前の通り(?),「様々なデータを処理してレポートを出力するのに向いているプログラミング言語」です.他のプログラミング言語と比べて以下のような特徴があります。

  • スクリプト言語である
    ..... CやJavaは、実行の前にコンパイル(=テキストで書いたプログラムをマシンが理解できるバイナリコードに直す作業)が必要です。実行は早いですが、プログラムを書き直すた度にコンパイルする必要があります。一方、Perlはコンパイルの必要ないスクリプト言語です。書いてすぐに実行できるので開発は非常に楽ですが、実行する度にインタプリタ(=テキストで書いたプログラムを理解しながら実行するためのソフト?)を通す必要があるので速度は遅いです。

  • テキスト処理に優れている
    .....Perlには文字列処理の関数が多数揃っています。PerlがCGIプログラムによく使われる理由の一つは、この強力なテキスト処理機能にあります。詳しくはなぜPerlなの?をご覧下さい。

  • 様々なプラットフォーム上で稼動
    .....Perlインタプリタはフリーソフトです。UNIX, Windows, Macなど主要なプラットフォームほとんどに移植されています。

  • 変数の型がない
    .....CやJavaの変数は、整数ならint、文字ならcharというように型を宣言する必要があります。しかし、Perlの変数には型という概念がありません。原則として変数宣言すら必要なありません。宣言や型に気をつかう必要がなく便利な反面、宣言していない変数を利用してもエラーが出ないので、バグのあるプログラムを作りやすく、注意深くコーディングしないと混乱するという欠点があります。

 Perl独自の変数型を簡単に紹介しておきます。Perlでは変数の型をC言語のような宣言ではなく、頭につく記号で判断します。カッコ内は各変数の頭につく記号である。詳しくはPerl専門書を参考にしてください。

  • スカラー変数 ($) … 文字列、数値が一つだけ入る。
    [例] $var = "Hello!";

  • 配列変数 (@) … 複数の値が入る。数値をインデックスとして用いる。
    [例] @array = (1, 2, 3);
    ($array[0] = 1; $array[1] = 2; $array[2] = 3; と等価)

  • 連想配列 (%) … 複数の値が入る。文字列をインデックスとして用いる。
    [例] %hash = ( 'A' -> 'apple', 'B' -> 'banana', 'C' -> 'cheese');
    ($hash{'A'}= 'apple'; $hash{'B'} = 'banana'; $hash{'C'} = 'cheese'; と等価)

[index]

 

なぜCGIにはPerlを使うの? 〜 テキスト処理ならおまかせ

 CGIプログラムの言語として、なぜPerlが使用されるのか。その理由、Perlのテキスト処理系の命令が充実していることにあります。以下に簡単な実例を上げて紹介します。
  • [例1] フォームから渡された値を分割する
    ..... フォームの入力を受け取る仕組みでも説明したとおり、WWWブラウザのフォームから送信されたデータは、「NAME=値&NAME=値&…」という文字列となってプログラムに渡されます。データを処理するためには、まずこのつながった文字を分割して変数に収める必要があります。この処理にはPerlの split という関数が活躍します。split は、第一引数で指定された文字で第二引数の文字列を分割し、配列に収める関数です。以下ではフォームから渡されたデータが$bufferという変数に格納されていると仮定します。
    @array = split(/&/, $buffer);
    foreach $data(@array){
      ($name, $value) = split(/=/, $data);
      $FORM{$name} = $value;
    }
    foreachは、配列の全ての要素に対して {} 内の処理を行う、という意味です。このコードによって、$bufferへの入力は $FORM{<NAME>} という連想配列に全て格納されます。例えば、NAME が foo1 の入力欄へ入力されたものは、$FORM{'foo1'}で参照できます。



  • [例2] フォームに入力された値の妥当性を調べる
    ..... 例えば、アンケートを取るCGIプログラムを作成するとき、電話番号をいれるべき場所に英文字が入力されたらエラーを返す、というような入力の妥当性チェックの仕組みが欲しいところです。Perlは正規表現による強力なパターンマッチング機能を持っています。例えば、$tel の値が電話番号の形式になっているかどうかを調べるには、以下のように書きます。
    if($tel =~ /\d+-\d+-\d+/){
      print "OK!";
    }
    else{
      print "NG!";
    }
     ここで、「\d+」というのは、「半角数字の1回以上の繰り返し」という意味です。例えば、「03-3671-2500」はOKになるが、「ABC-DEF-GHI」はNGになります。



  • [例3] CSVファイルを読みこんで表示する
    ..... 例えば、名前、電話番号、住所などのデータがカンマ区切りで何百行も入っているlog.csv というファイルがあります。これをHTMLで見やすいように整形してみます。
    open(FILE, "log.csv");
    @logs = <FILE>;
    close(FILE);
    print "<H3>名簿リスト</H3><UL>";
    foreach $data(@logs){
      ($name, $tel, $address) = split(",", $data);
      print "<LI>名前:$name, 電話番号:$tel, 住所:$address<BR>\n";
    }
    print "</UL>";
     1〜3行目により、log.csv の中身を一行ごとに配列@logsの中に収めます。あとは例1のforeachとsplitを使って値を分割します。フォームで回収したアンケートデータなどはこのようなCSV(カンマ区切りテキスト)ファイルに収めておき、閲覧するときに整形して表示することができます。

 これらの例のように、CGIプログラムによく使用される文字列処理は、そのほとんどがPerlの標準関数として用意されています。これらの例と同じ処理を行うCのプログラムを書こうとすると、非常に複雑なものになります。(Cに慣れている優秀なプログラマなら楽なのかもしれませんが、少なくとも私のような似非プログラマにとっては難しいですね。)この手軽さが、PerlがCGIプログラミングに使用される理由です。

[index]

 

Perlは重くてダメって聞いたけど? 〜 要は適材適所

Perlって何?にも書いたように、Perlはスクリプト言語です。コンパイル言語と比べると、実行時にインタープリタを通す必要がある分だけどうしても遅くなります。

  • Perlコード → インタプリタ → 実行
  • Cバイナリ → 実行

 しかし、遅いといっても、ネットワークの遅さに比べれば微々たるものです。よく「このCGIチャットは重い」とか「これは軽い掲示板だ」とか言いますが、その重さ軽さはプログラムの書き方によるものよりも、ネットワークの混雑によるところ、若しくはサーバの負荷状態(詳細は下記)によるところの方が大きいです。掲示板やチャット程度なら、どんな書き方をしてもその処理速度に大した違いはありません。(何万行もの配列に対して何度もforeachするなど、よっぽど無茶なコーディングをしてるなら別ですが。。。)自分のローカルマシンにWebサーバを入れて、そこでCとPerlのCGIの体感速度を比べてみれば、「書き込み」ボタンを押して返事が返ってくるまでの時間差はほとんどないことがわかります。

 とは言うものの、Cはやっぱ早いです。混雑していないサーバの場合、簡単なCGIでも、Perlだとボタンを押すと一拍置いてから次の画面が出てきますが、Cだと普通のHTMLページを見てるのと変わらないくらいのタイミングで次の画面が出てきます。まあ、意識しないとわからない程度の差ですが。こちらにCで書いたものとPerlで書いたものがあります。体感速度の違いを実感してください。

また、CとPerlでは「速度」にはあまり差がありませんが、「負荷」という点ではけっこう差があります。巨大なサイズのPerlプログラムを何回も呼び出していると、簡単にCPU負荷が100%に達します。通常のホームページスペースは一台のサーバを複数の人でシェアして使っていますので、そのうち一人が重いCGIで負荷をかけると、ほかの人のCGIが動かなくなったり、通常のHTMLですら表示が遅くなったりします。プロバイダの中には「負荷の高いCGIは削除します」と宣言しているところもありますが、それは共用スペースを一人が占領するのを防止するためなのです。

まとめると、

  • Perlも重いが、ネットワークやサーバはもっと重い
  • Cは軽いけど、開発効率を考えるとやっぱPerlが一番
ということになるでしょうか。

[index]

 

CGIは危険と聞いたけど? 〜 ハサミだって包丁だって危ないじゃん

 包丁は野菜を切るのに便利ですが、使い方によっては人を傷つけることもあります。それと同じ意味で「CGIは危険」というなら、確かに危険です。悪意を持つ人が自分のサーバのディスクをあふれさせたり、永久ループで異常負荷をかけたりするプログラムはいくらでも書くことができます。(ホントにやってはいけません。サーバのログを見れば誰がやったかすぐにバレます。)要するに、「危険な使い方をしなければ大丈夫」ということです。

 しかし、本人だけが使うならともかく、多人数の人が使う掲示板、チャット、投票などのCGIでは、悪意のある人が意図的に異常動作させることもあります。たとえば、単純な掲示板でも、発言欄に何100MBもの文章を書きこんだ場合、もしその人のサーバースペースが5MBしかなかったら、容量が溢れてしまうかもしれません。

 CGIプログラムを組む場合は、こういったありとあらゆる攻撃の可能性を考え、注意深くコーディングする必要があります。逆にいえば、「攻撃の穴がないようにプログラムを組めば大丈夫」ということです。しかし「どんなところに穴があるのか」という判断は普通の人にはわからない場合が多いです。いくつか挙げてみますと、

  • 「ファイルロックは完全にその仕組みを理解してから使え」
  • 「シェルで実行する文のオプションをブラウザから直接渡すのはやめろ」
  • 「読み込むファイルの名前を直接変数で指定するのはやめろ」
  • 「掲示板などのデータファイルに掲示板の削除キーを書くときは気をつけろ」
  • 「ライブラリ(.pl)ファイルに管理パスワードを書くのはやめろ」
  • 「IPアドレス、Cookieを信用するな」
  • 「タグ付けは必要なものだけ許可しろ」

 はっきり言って「穴」の識別は「経験則」によるところが非常に多いです。よく「素人がCGI組むと危険だからやめろ」といわれるのは、この「穴」の判断がつかないからだと思います。しかし、誰でも最初は素人なのです。私も最初のころは永久ループするCGI書いてサーバごと止めてしまったこともあります。(誉められたもんじゃないですが。)恐れずにどんどん書いていきましょう。「経験則」といっても不条理に記憶しなければならないものでもなく、それぞれの穴にはちゃんとした理由があるので、その意味を理解しながら覚えていくとセキュリティの勉強にもなってよいでしょう。

[index]

 

SSIってのもあるって聞いたけど? 〜 できることに大した違いはないけど。。。

 SSI(Server Side Include)は、CGIと同じく、インタラクティブなページを作るための「WWWサーバの一機能」です。CGIは<HTML>から</HTML>までを出力するプログラムを書き、それを実行します。それに対しSSLは、通常のHTML文書の中にコメントタグを使って
<!--#exec <実行するプログラム>-->
と書いておくと、そこにプログラムの実行結果が埋め込まれる、というものです。 プログラム自体はPerlでもCでもshでも何で書いても結構です。簡単な例を示すと、

[HTML]
こんにちは。あなたは<!--#exec ./count.pl -->人目の訪問者です。

[count.plの仕様]
・数値ファイル count.txt の中身を読み、1増やす
・現在の数値を桁ごとに分解
・「<数字>.gif」を表示するIMGタグを出力
・現在の数値を count.txt に収める

という具合にしておくと、カウンターができあがります。(サンプル)

 SSIの非常に便利な点は、「通常のHTMLに埋め込むだけなので、デザインが楽」という点につきます。上のカウンタの場合、FrontPageなどのHTMLエディタソフトで作ったページの好きな部分にタグを埋め込むだけで、カウンタ付きのページが作れます。

 ただし、以下のような欠点があります。

  1. 重い
    ..... SSIの動作手順は、「ページのリクエストを受ける」→「サーバはHTML文書の中からSSLタグを探す」→「SSLタグ部分を実行し結果を埋め込む」→「完成した文書を返す」となっています。書いている感覚では普通のHTMLなのですが、実行に関してはCGIと同じコストがかかります。さらに、全体がプログラムであるCGIとは違い、実行部分を探したり、結果を埋め込む作業が入る分、CGIよりも余計な手順がかかっています。

  2. 他に対して悪影響
    ..... WWWサーバをSSI対応にしておくと、たとえSSLタグがない普通のHTML文書でも「実行タグを探す」という動作が入る分遅くなります。SSIのせいで通常のHTML文書すら遅くなってしまいます。それを避けるために、最近はほとんどのサーバでは、「SSIタグを含むHTML文書は独自の拡張子(.shtml)にする」設定になっています。それなら、.html のときはそのまま返し、.shtmlのときはSSIとして処理する、という具合にサーバ側で判断し、通常のHTMLに関して余分なステップを入れないようにすることができます。

    #文化的?に「HTML文書の拡張子は .html である」という意識があるためか、あまり「トップページが .shtml」というサイトを見たことがありません。

  3. 危険
    ..... SSI は、UNIXシェルのコマンド(要するにtelnetで実行できるコマンド)なら何でも実行できてしまいます。「HTMLにSSLタグを書くだけ」という手軽さがある分、それだけ間違いも犯しやすいです。CGIでもUNIXコマンドは実行できますが、パーミッションを変えたり、言語それぞれの書き方があったりと知識が必要で、「うっかり」重要なコマンドを実行してしまうことはあまりありません。

 2〜3年前までは拡張子.htmlでもSSIが使えるサーバがほとんどでした。最近は「SSIを使うには設定が必要」若しくは「禁止」になっていることが多いようです。

[index]

 

CGIを使うのに必要なものは? 〜 知識は無くとも

 「自分のページに掲示板やカウンタを付けたい」、と思った場合、以下のような方法が考えられます。

  1. レンタルサービスを使う
        長所:申し込むだけで使えるので手軽、プログラムの知識が全く必要ない
        短所:URLが変わってしまう、個人情報の入力を求められることがある、広告がはいる
     掲示板やカウンターを貸し出してくれるページへ行けば、すぐに利用できます。自分のプロバイダに付属している場合もあります。順番としては、自分のプロバイダにサービスがあるか調べる、無ければ外部に求めるのがよいと思います。プロバイダのサービスなら広告が入ることはあまりありません。また、支配権は先方にありますので、「いきなりログを消された」という話も聞いたことがあります。また、せいぜい掲示板とカウンターくらいで、それ以上のものを貸し出しているところはあまりありません。

  2. CGIを配布しているページへ行き、自分のHPにインストールする
        長所:ある程度はデザインを選べる、URLが変わらない、全て自分でコントロールできる、設置実績のあるものを選べる
        短所:CGIの知識が少々必要、容量などの管理が必要、基本的に無保証
     当ページのようにCGIプログラムを無料または有料で配布しているページがたくさんあります。気に入ったものを拾ってきて自分でインストールすれば、自由に使えます。

     最近はフリーのCGIを「掲示板」「投票」のようにジャンル別に分けて紹介しているページもあります。また、大抵のCGIは「無保証」を唄っています。不具合によりサーバがダウンするようなことになった場合、責任は自分で取ることになります。また、「改造を禁ず」とか「商用利用は有料」とか、色々条件のついているものもありますので、使う前に「規約」を調べることをお勧めします。

  3. 自分でCGIを作る
        長所:全て自由
        短所:プログラミング言語の知識が必要
     配布されているものがどうしても気に入らない場合、又は希望に沿うものがない場合、自分で作ってしまえばいいのです。究極的にはこれを目指しましょう

[index]

 

私のプロバイダはCGIを使えるの? 〜 悩む前に直接聞け

CGIが使えるかどうかを確かめるには以下のような方法があります。

1, プロバイダの管理者に聞く
2, プロバイダの説明ページを読む

 当たり前ですが、これが一番手っ取り早いです。プロバイダのサポートに以下のようなメールを書きましょう。

「自分のページでCGIを使いたいのですが可能でしょうか。」

 この問いに対して、CGIが利用できる場合は「使えます」と返事が返ってきます。しかし、利用できない場合は「使えません」と素直に返事がくることは あまりないようです。。よくあるのが、

「弊社提供のCGIをご利用になれます」
「掲示板、カウンタをご利用になれます。詳しくはxxxをご覧下さい」

というような回答です。これは「プロバイダが設置済みのCGIのみ利用できる」という意味です。逆に言えば「会員が独自に設置するCGIは利用できない」という意味です。掲示板、カウンタ、フォームメールなどに限定されていることが多いです。

# プロバイダへ質問する場合も、
「自分のページで独自のCGIを使いたいのですが可能でしょうか」
と「独自の」一言入れておくとよいかもしれません。(それでも回りくどい言い方しか返って来ないこともあるようですが。。。)

「使える」という場合も、いくつか特殊な設置方法をする必要がある場合もあります。詳細は後述。必ずプロバイダの解説ページの指示に従うようにしてください。

ちなみに代表的サーバで利用できるところは、
biglobe, Hi-Ho, nifty, freeweb, BigNet, Sakura-Net, RimNet
利用できないところは、
geocities, asahi-net、so-net(別契約で可能)
です。

利用できないほうに入っていてもあきらめてはいけません。無料サーバを利用する、という手もあります。詳しくは後述。

[index]

 

能書きはいいからどうやって使うの? 〜 3つの作業を覚えよう

 ここでの解説はPerlで書かれたCGIプログラムに限定しています。他の言語(C,sh等)に関しては専門書などを参考にしてください。

 あなたのページに当ページや他で配布されているCGIプログラムを利用するための唯一の条件は、「自分のページを置いているサーバがCGIを許可している」ことだけです。それさえ確認できれば、あとは説明書に沿ってインストール作業を行うだけです。説明書はCGIプログラムと一緒に配布されています。

「インストール」というと難しく聞こえますが、どんなに高度なCGIプログラムでも、具体的に行う作業は以下の3つの組合せです。逆に言えば、この3つの操作さえ理解してしまえば、どんなCGIプログラムでも設置できます。

1, 環境に合わせたファイルの書き換え
2, FTPによるファイルの転送
3, パーミッションの設定

 1 は、テキストエディタ(メモ帳など)を使ってファイルの書き換えを行う作業です。大別して「サーバ特有の設定」と「表示や機能制御のための設定」の二種類があります。具体的には、前者はPerlのパスやライブラリのパス、後者はフォント色やタイトル文字などです。この辺は説明書やファイル中の注意書きに忠実 に従えば問題ないはずです。

 2 は、普通のページを更新するときにHTMLファイルをFTPソフトで転送するのと全く同じ作業です。ただ一点注意しなければいけないのは、「プログラム(*.cgi)ファイル転送する場合は必ずアスキーモードにする」ことです。アスキーモードに関する解説は後述。転送モードの切り替え方法はお使いのFTPソフトのヘルプを参照してください。

 3 は、同じくFTPソフトを使った作業になります。ファイルを一つずつ選択して、その属性を「707」や「606」といった数字で指定していきます。どの数字にすればよいかは説明書に必ず書いてあります。この作業はCGIプログラムを「実行」したり、フォームへの書き込みをファイルに「記録」するために必要な作業です。パーミッションに関する解説は後述。

 2,3 の具体的な方法はお使いのFTPソフトに依存します。ヘルプで「パーミッション」「属性」「アスキーモード」等をキーワードに探してみてください。

[index]

 

FTPのアスキーモードって何? 〜 某雑誌社のことではありません

 FTPでファイルを転送する方法には、「アスキーモード」と「バイナリモード」の二種類があります。前者はテキストファイル(HTML、プログラム等)を送るために、後者はバイナリファイル(画像、ワード、パワーポイントファイルなど)を送るために使います。すごーく砕けて言うと、「メモ帳で開いて読めるのがテキストファイル、読めないのがバイナリファイル」という区分になります。ファイルの種類によって転送方法を変える理由は「改行コード」です。

 Windows(CR+LF), UNIX(CR), Mac(LF) それぞれ改行コードが異なります。例えば、Windowsのメモ帳で作ったファイルと、UNIXのテキストエディタ(Mule等)で作成したファイルでは、全く同じ文章、改行の回数でも、サイズが微妙に違います。これは、改行コードがUNIXでは1バイト(CR)、Windowsでは2バイト(CR+LF)であるためです。

以下のサンプルは、UNIX上で作成したテキストファイルです。これをファイルに保存してWindowsの「メモ帳」で開くと、改行されずに一行につながっています。これは、改行コードの相違によって起こる現象です。ブラウザで直接見るとちゃんと改行されていますが、これはブラウザが改行コードの差異を吸収してくれているからです。通常のHTMLはバイナリモードでもアスキーモードでも大丈夫なのはこのためです。

 インタプリタやコンパイラは、自分自身のプラットフォーム向けの改行コード以外は全て異常な文字と判別し、「プログラムに異常な文字が混ざっている」としてコンパイル段階でエラーを返します。従って、改行コードが違うとプログラムの実行ができません。

 ファイルを「アスキーモード」で転送すると、テキストファイル中の改行コードを送り先のプラットフォームのものに自動的に変換します。従って、「アスキーモードで送る」ということは、「改行コードを送信先のサーバに合わせて変換する」と同義です。これにより、プログラム実行時のエラーを防ぎます。

 一方、「バイナリモード」はこの改行コードの変更は行わず、ファイルをそのまま送信します。画像ファイルやHTMLファイルなど、プログラム以外のファイルを送る場合はこちらを利用します。

 (Perlプログラムの場合)一般的には、*.cgi,*.txt等の拡張子のファイルは「アスキーモード」、それ以外の「*.gif,*.html」等は「バイナリモード」で送っておけば大体間違いはありません。ただし、説明書に異なる記述がある場合はそちらに従ってください。

 どんなFTPソフトにもこの二種類の転送モードを切り替える機能は必ずついています。(アスキーモードを「Raw Text」と呼んでいたり、名前が微妙に違っていることがあります。)中にはファイルの拡張子(html,gif,cgi等)で自動的に転送モードを切り替えてくれるものもあります。(FFFTPなど。)これなら転送時にいちいちモードを意識する必要がありませんので便利です。

 "ASCII" は「American Standard Code for Information Interchange(情報交換用米国標準コード)」、"Binary" は「2つの、2進の」の意味です。

[index]

 

パーミッションって何? 〜 606、705、暗号のナゾを解け

 パーミッションは英語で「許可」の意味。UNIXの世界では「ファイルにアクセスするための権限」という意味で使っています。パーミッションを理解するには、まずUNIXのユーザの概念から学ぶ必要があります。

 Windowsマシンを利用するときは、PCの前へ座ってユーザ名/パスワードを入力してログオンし(入力が必要ない場合もあります)、自分のデスクトップを呼び出し、終了したらログオフします。ユーザ毎に異なるデスクトップを持つことはできますが、ひとつのPCは同時に一人のユーザしか利用できません。WindowsやMacのような「一人が使っているとき他の人は一切使えない」マシンを「シングルユーザOS」と言います。

 これに対し、UNIXはひとつのマシンを複数のユーザが同時に利用できます。といっても、二人で椅子に半分ずつ座ってひとつのキーボードを分け合って使う、という意味ではありません。一台のUNIXサーバに対して、キーボードとディスプレイとターミナルソフトだけの入ったクライアントマシン(X端末)を複数台用意して、ネットワーク経由でUNIXサーバに数人のユーザが同時にアクセスして利用します。このようなOSを「マルチユーザOS」と呼びます。

 マルチユーザOSの特徴は、クライアントがロースペックで済むところです。大量の計算処理をすばやく行うには、CPUもメモリも沢山積んだハイスペックなマシンが必要です。しかし、それを社員の数だけ用意すると莫大な金額になります。しかし、実際に一人が計算処理をやらせるのはせいぜい一日に数回程度。残りの時間は遊んでいたりします。

 そこで、ひとつのハイスペックなサーバに対して、最低限の表示能力があるクライアントをつなげる、という方式が生まれました。クライアントの役割は「サーバから送られてきた情報を表示する」ことだけですので、高速なCPUや大きなメモリは必要ありません。重い計算はサーバに任せます。WindowsマシンをX端末にするソフトも市販されています。ただし、インターネット環境ではネットワークが遅いので、X端末の変わりに文字対話式の「telnet」を用いてUNIXサーバにアクセスすることが多いです。

 UNIXでは、ユーザを「グループ」という単位でくくることができます。例えば、aaa, bbb, ccc, ddd, eee という5人のユーザがいたとき、

adminグループ: aaa, bbb, ccc
userグループ: aaa, ddd, eee

という具合に、admin や user といったグループを作成して、そこに各ユーザを所属させることができます。一人のユーザが複数のグループに属することも可能です。

 さて、マルチユーザOSでは複数ユーザが一つのマシンを同時に使うわけですから、例えばAさんの大事なファイルをBさんに勝手に消したり、Cさんが沢山の動画ファイルを保存したためにサーバ全体のハードディスクが足りなくなった、という自体が起こると困ります。マルチユーザOSはこれら複数ユーザ環境特有の問題に対する様々な解決策を備えています。

 その解決策のひとつが「パーミッション」です。これは他ユーザのファイルへのアクセスを制御するためのものです。例えば、Aさんの持つ sample.txt というあるファイルに対して、自分以外のユーザがアクセスできないようにするには、UNIXコマンドで、

% chmod go-rwx sample.txt

と書きます。chmod は「ちぇんじもーど」と読みます。ファイルのパーミッションを変えるためのコマンドです。「go-rwx」の部分は後ほど解説します。

 権限は「読み込み(read)」「書き込み(write)」「実行(execution)」の三種類。それを「自分(user)」「グループ(group)」「その他(others)」の3つの対象に設定できます。その他(others)は「自分でも同じグループでない人」の意味です。

現在のファイルのパーミッションを確認するには、ls -l コマンドを使います。

% ls -l sample.txt
-rwxrw-r-- aaa admin sample.txt

最初にある「-rwxrw----」がこのファイルのパーミッションを表しています。その後ろの「aaa」はそのファイルの所有者、次の「admin」はそのファイルを所有するグループです。

 最初の一文字は○○○、次の3文字「rwx」は所有者(user)、その次の3文字「rw-」はグループ(group)、最後の3文字「---」はその他(others)に与えているパーミッションです。つまりこの例の場合、「所有者は読み書き実行可、グループは読み書き可、それ以外のユーザは何もできない」という意味になります。もうお分かりかと思いますが、3文字のうち「r」が読み込み、「w」が書き込み、「x」は実行を、それぞれ表しています。実行に関しては、そのファイルがプログラムである場合のみ意味をなします。

先ほどの、

% chmod go-rwx sample.txt

は、「sample.txt に対して、グループ(g)とその他(o)から読み(r)書き(w)実行(x)権限を奪いなさい(-)」という意味になります。

「go-rwx」の部分は以下のような文法になっています:

A) a(all),u(user),g(group),o(others)の4種類
B) +(与える),-(奪う)の2種類
C) r(read), w(write), x(execution)の3種類

です。

 しかしこれだと、例えば「グループから読みを奪い、かつ、他人には実行権を与える」のように、グループとその他で権限を変えようとすると、2度コマンドをうつ必要があります。その場合、パーミッションを数字で与える方法があります。ある1対象へのパーミッションは「rw-」などの3文字で表現されますが、一文字目を 4, 二文字目を 2, 三文字目を 1 と数字に置き換えます。例えば「r--」なら「4」、「rw-」なら 4+2=6、という具合になります。それを3つの対象に対して並べると、前述の a) の場合、

% chmod 600 sample.txt

となります。これで sample.txt の権限は 「-rw-------」となります。

パーミッションはファイルにかける 場合とディレクトリ(フォルダ)にかける場合とで意味が違ってきます。ディレクトリにおいては、

  • r: そのディレクトリにファイルを置く
  • w: そのディレクトリにあるファイルを読む
  • x: そのディレクトリ内のファイル一覧を参照する
という意味になります。

[index]

 

CGIプログラムのパーミッション設定 〜 私を呼ぶのは誰?

 パーミッションの知識を踏まえて、今度はCGIプログラムにおけるパーミッションの設定方法について解説します。

 UNIXは「何らかの操作を行う場合は必ずユーザがいなければならない」という絶対条件があります。Apache等のUNIX上で動くWebサーバは、ブラウザからのリクエストを受けて、URLに対応するファイルを取り出してブラウザに送り返す、という操作を行っています。当然このWebサーバも何らかのユーザ権限をもって動いています。

 Webサーバがどのユーザ権限を持って動くかは、一般的にはWebサーバソフトの設定ファイルで記述できます。もっとも有名な「Apache」の場合、httpd.conf という設定ファイルで記述します。標準では「nobody」(誰でもない)というユーザで操作を行います。「nobody」ユーザは通常「nobody」(誰もいない)グループに属します。(矛盾で悩まないように。)

 皆さんがページを更新するとき、FTPソフトを使ってファイルをWebサーバにアップロードしていると思います。FTPソフトの設定にユーザ名、パスワードを入力していると思いますが、これは最初の「何らかの操作を行う場合は必ずユーザがいなければならない」の原則にしたがっています。ログインすると、以後サーバに置いたファイルの所有権は全てログインしたユーザになっています。

 普段ページを更新するためにFTPを使用している方は、ファイルのアップロードはやってもパーミッションの設定まではしていないと思います。アップロードした直後のファイルのパーミッションは、サーバ側の設定(umask)によって定められます。通常は644(-rw-r--r--)になっていることが多いです。通常のHTML,画像等の場合、Webサーバはファイルを「読み込んで」それをブラウザに送るだけです。アップロードしたユーザと「nobody」ユーザは「その他(others)」の関係です。othersのパーミッションを見てみると、「r--」と最初から読み込み可能になっています。ですので、通常のファイルの場合は特にパーミッションを意識する必要はないのです。

 一方、CGIは「プログラム」です。「プログラム」は「実行」されて「結果」を返すものです。「CGIプログラム」を実行するのもWebサーバの役目です。つまり、Webサーバは「nobody」というユーザ権限でCGIプログラムの実行を試みます。ですので、「others」に実行権限がないとWebサーバはCGIプログラムを実行できません。「705(-rwx---r-x)」というのは、「othersに読み込みと実行の権限を与える」という意味なのです。「7」は、ユーザ自身が読んだり書いたりするための設定です。groupが「0」なのは、「必要のない権限は極力与えない」というセキュリティの原則に基づいています。othersに関して、実行だけなら「5(r-x)」じゃなくて「1(--x)」でいいじゃないか、と思うかもしれませんが、プログラムを実行するには、まずそのファイルをメモリ上に読み込む必要があります。そこで「r」も付けてやる必要があるのです。(この辺は深く考えるとハマります:p)CGIプログラムの「パーミッションは705にする」理由は、「othersに対して読み込み、実行権限を与えるため」なのです。パーミッションが間違っているCGIプログラムにアクセスすると、「403 Forbidden(アクセス禁止)」というエラーが出てきます。これは、WebサーバがCGIプログラムを実行しようとしたけど、othersに実行のパーミッションがないことが原因です。

 掲示板等のCGIプログラムの場合は、.cgiファイルと共に.txtファイルを設置することが多いです。掲示板のCGIプログラムは、.txtファイルを読み込んで整形して表示したり、フォームに書き込まれた発言を .txt ファイルに書き込んだりします。.txtファイルに「書き込む」には、othersに書き込みのパーミッションが必要です。また、「読み込む」には読み込みのパーミッションが必要です。ですので、.txtファイルは「606(-rw----rw-)」になっていることが多いのです。

 一方、CGIプログラムから読み込まれるけど書き込まれることはないファイル(テンプレート、設定ファイル、画像ファイル等)は、「604(-rw----r--)」にします。ユーザ(自分)が常に「6」なのは、書き込み禁止だと上書きFTP(同じファイルをアップロードすること)ができなくなるからです。

 ディレクトリのパーミッションは大抵「707(-rwx----rwx)」です。CGIプログラムにおいて、ディレクトリはその中に一時的(または恒久的)にファイルを作成したり消したりするのに利用します。上記の動作を全てCGIプログラムから可能にするには、そのディレクトリがothersにとって全てが可能である必要があります。ディレクトリはファイルロックをかける目的で良く使われます。(ファイルロックについては後述。)

 まとめると、

  • CGIプログラム(.cgi):705(-rwx---r-x)
  • データファイル(.txt):606(-rw----rw-)
  • テンプレート、画像ファイル等:604(-rw----r--)
  • ディレクトリ:707(-rwx---rwx)
ということになります。全て理由付けられるようになりましたか?

[index]

 

自分でCGIを作ってみたい 〜 (執筆中)

(執筆中)

[index]

 

Server Error とは何ぞや? 〜 (執筆中)

(執筆中)

[index]

 

自分のマシンでCGIの実験をしたい 〜 (執筆中)

(執筆中)

[index]

 

CGIに似た他の技術 〜 (執筆中)

(執筆中)

[index]