CGI

メインページ > 工学 > 情報技術 > プログラミング > CGI
CGI(シージーアイ、Common Gateway Interface)とは、ウェブサーバが独立した外部プロセス(CGIプログラム)でウェブページを生成できるようにする仕組みです。CGIプログラムの記述にはPerlなどのスクリプト言語がよく用いられますが、基本的に標準入出力を備えているプログラミング言語であれば(たとえばC言語やシェルスクリプトでも)用いることができます。
ウェブサーバのApacheは、PHP・Perl・PythonやRubyのようなスクリプティング言語のコードだけでなく、C言語をコンパイルしたバイナリファイルも実行できます(ただし、バイナリなので、ホストアーキテクチャごとにコンパイルしなおす必要があり、取り回しが悪いので、例外的に処理速度が極端に必要な場合以外には、めったにC言語によるバイナリをCGIに使用することはありません)。
広い意味での『CGI』の「プログラミング言語の内容を実行する」との意味は、具体的にはウェブページでユーザからの入力に応答したり、動的な出力を行ったりするための機構などもCGIです。CGIの規格はhttp://hoohoo.ncsa.uiuc.edu/cgi/interface.html(インターネットアーカイブ: https://web.archive.org/web/20070809114039/hoohoo.ncsa.uiuc.edu/cgi/interface.html )で定められています。ここで動的とはたとえば、ブラウザからリクエストを受け付けた日時をページとして表示させるものも動的なページの一つです。ウィキやブログなども動的なページに含まれます。これに対して静的とはあらかじめ用意してあるHTML等で記述されたドキュメントをリクエストへの応答時に変更を行わずに配信することを指しています。
PerlやPHPなど用いている言語が何かかは別として、現在インターネット上で大規模、あるいは著名なウェブサイトのほとんどは何らかの動的な仕組みを有していると考えられます。CGIの仕組みを理解することは大規模なデータをインターネット上で出版する技術的な背景を学ぶのと強い関係があると言えます。
動的なウェブアプリケーションの実装技術は、CGI以外にも mod_perl のようなApache向けのモジュールや FastCGI のような外部の常駐プロセスとの連携技術があります。 これらのCGI以外の方法が用いられるのは、CGIには「外部プロセスをリクエストがあるごとに起動しなければいけない」という欠点があり、プロセスの起動は毎秒数百から数千が限度で、この数は比較的小規模のウェブサイトでも容易に達する数です。このことからCGIでリクエスト毎にプロセスを起動するのではなく、動的コンテンツをモジュールや常駐プロセスに生成するのが現在の主流です。 このウィキブックスをサービスしているMediaWikiもPHPの常駐プロセスで実装されています。
CGIが行う動的な作用は主に以下の4要素によって成り立っています。
ウェブサーバで動的にコンテンツを生成する仕組みには他に、ウェブサーバのモジュール(mod_perlなど)やFastCGIがあります。 これらのCGIと大きな違いは、CGIの「リクエストごとに新しくプロセスを生成する」という負荷の大きな処理を、ウェブサーバプロセス内で実行したり、常駐するプロセスとウェブサーバの間での通信を行うことで避けている点です。
ApacheはCGIを実行するためには htttpd.conf の書換えの必要があります。
XAMPPであれば、場所は、\xampp\apache\conf の中に設定ファイル
があるので、探して httpd.conf のファイルの中身の下記のような部分を、下記のように書換えます。
多くのGNU/Linuxのディストリビューションでは、 /etc/httpd/conf に httpd.conf があります。 /etc/httpd.conf の所有者は root もしくは www なので、sudo vi /etc/httpd.conf などとし書込み保護した状態を維持してください。
設定の方法は2種類あります。
書き換え前
書き換え後
ScriptAlias という行を、下記のようになるように、書き換えます。
どちらの方法で編集するにしても、もしApacheをすでに立ち上げていたら、いったんApacheを終了してから、再度、立ち上げ直して下さい。
Apacheの起動時に設定ファイルを読み込む方式のようなので、立ち上げ直さないと、設定が反映されない場合があります。
Apacheを終了させるには、コマンド
でApacheが終了します。
右上のXボタンを押してコマンドラインなどのウィンドウを閉じるだけでは、Apacheが終了しない場合が普通なので、終了させるためにはコマンド入力で確実に、いったんApacheを終了させてください。
Apacheを立ち上げるには、コマンド
で立ち上がります。
今後の作業の暗黙の前提として、Apacheサーバーを立ち上げるのを忘れないように(よく忘れてエラーになります)。さっさと先にApacheサーバを立ち上げましょう。
さて、たとえば、下記のようなC言語ファイルをテキストファイル(『メモ帳』で良い)に書いて、コンパイル(gccでも良い)して、実行ファイル(windowsならexeファイル)にしましょう。
コード例
Content-Type: text/html というのは、Apache側が解釈のために必要な情報であり、これから送られてくるprintf文の内容が、テキストファイルまたはHTMLファイルであることを宣言しているテキスト文です。「HTMLヘッダー」などと言われます、webでの情報のやりとりをする際の、送受信メッセージ文の一種です。
さて、Windows版ApacheであるXAMPPの場合、上記コード例をコンパイルして出来上がった実行ファイル(ファイル名を指定しなければWindows版gccなら「 a.exe 」という名前になります)を、 フォルダ \xampp\cgi-bin に入れればいいです。
GNU/Linux版の素のApacheの場合、フォルダ cgi-bin の場所は
ですので、そこにa.outなどの実行ファイルをいれればすみます。ですが、初期設定では、root所有になってますので、chownコマンドで所有者を変えてください。
とにかく、cgi-bin フォルダにバイナリファイルを入れたら、のあと単にウェブ・ブラウザーで
にアクセスすればいいです。
または実行ファイル名がa.exe以外の別のファイル名なら、
にアクセスすればいいです。
すると、
上記コードの場合
というふうに、webページでprintf文の内容が表示されます。(GNU/Linux版Apacheでも同様の結果です。Fedora 32 で2020年7月14日に確認。)
C言語バイナリだろうが、Apache側がHTMLファイルを解釈してくれるので、なので、下記のようにprintf文中にHTMLタグを書いてバイナリ化しておけば、自動的にApacheがうまく変換して、ブラウザにHTMLタグの指示通りに表示できるようにしてくれます。
コード例
上記コードをコンパイルしたバイナリファイルをフォルダ cgi-bin に入れたあと、ウェブ・ブラウザーでアクセスすると、大きな文字で、
と表示されます。 (GNU/Linuxでも同様の結果です。Fedora 32 で2020年7月14日に確認。)
もし、興味あるのがCGIを使ったサーバ公開ではなく、CGIそのものの機能を作りたい場合、そのためのCGIの原理の知識は色々と考えられますが、OSのコマンドラインに搭載されている
が、原理的と思われる方法です。(なお、理解のために方法を紹介しているだけであり、通常のサーバ構築ではCGI機能自体の新規の実装は不要な作業です。すでにApacheなどの既存のサーバソフトにCGI機能が搭載されているからです。)
また、コマンドプロンプトに実行させたいコマンド列をテキストファイルに記述して繰り返し使うことが出来ます。 Windowsならバッチファイル、UnixまたはUnixに類したOSならばシェルスクリプトと呼ばれます。
本科目では、リダイレクトについて説明します。バッチファイルの解説は別の科目にゆだねます(たとえば『DOS入門』などを参照してください)。
リダイレクトについては、Windowsの場合、コマンドプロンプトで
と入力すれば、標準出力に出される文字列がそのまま、リダイレクト先のファイルに書き込まれて保存されます。
たとえば実行ファイル名「hello.exe」で、リダイレクト先ファイル名「ridtest.txt」なら
というコマンドになります。
間の演算子の機能は
になります。
CGI用のウェブサーバーにおいて、CGIプログラムの出力を処理する方法は複数あります。一般的には、指定されたCGI用のフォルダ内にある実行ファイルをリダイレクトして実行することで、その出力をテキストファイルとして扱うことができます。ただし、この方法は現代の実装ではあまり使用されていません。
実際の現場では、より効率的な方法が一般的に採用されています。例えば、Apacheや他のウェブサーバーでは、CGIプログラムの出力を直接パイプラインに渡し、他のプログラムや処理と連携させることができます。この場合、リダイレクトや一時ファイルの作成を回避し、データの処理を効率的に行うことができます。
パイプラインを使用することで、CGIプログラムの出力を別のプログラムや処理に直接渡すことができます。これにより、リアルタイムのデータ処理や複雑なデータフローを実現することができます。また、パイプラインを使用することで、複数のプログラムを連鎖させてデータを処理することも可能です。
実行ファイルがカレント・ディレクトリにある場合、
ストリームを指定したリダイレクトのためのコマンドの書式は、
です。これで、リダイレクト先ファイルに、書き込まれます。 この書式は、sh ksh bash zsh に共通ですが csh とは異なります。
たとえば実行ファイル名 hello で、リダイレクト先ファイル名が text.txt なら
というコマンドになります。
なお、ストリーム番号の意味は
になります。
Perl/CGI のページも見てください。 Perl/ライブラリ・モジュールとオブジェクト指向 のページもご覧ください。
テキストエディタ TeraPad(テラパッド)等のテキスト(拡張子 *.txt)を *.cgi に変えた物です。書かれている内容はtextなのでコード指定はテキストエディタのファイルオープンでUTF-8に変えてから日本語が使えます。変えないと文字化けします。
動作が確認され ミスがないのが確認されたら、契約サーバーにアップロードをFFFTP等でおこないます。皆さんに楽しんでもらいましょう。属性(パーミッション)の変更もお忘れなく。
Perl/制御構造・Perl/リファレンス・Perl/はじめに もご覧ください。
w:とほほのWWW入門は、良い情報源になるかもしれません。
本書ではApache HTTP Serverを用いた例を示しますが、ほかにも多くのウェブサーバでCGIが利用可能です。
PHPやPerlとは関係なく、一般に Apache の起動の方法は、GNU/Linux(Fedora32)の場合、ターミナル画面で、コマンド
です。(CentOS 7 以降はこうのようです。)
httpd とはlinuxの場合、Apache のことです。
なお、昔は
というコマンドのようでした。
Apache が正常に動いているか確かめるには、ブラウザを開き、アドレスバーに
http://localhost
と入力します。
バージョンにもよりますが、Apacheのロゴマークの羽の絵のあるwebページが表示されていれば、たぶんインストール成功しているでしょう。

Apache を終了するには、GNU/Linuxならターミナル端末で
で終了します。
昔は
で終了でした。
終了後に先程の localhost のリンク先に移動しても、何も読み込みできないハズです。(Apacheを終了したので、読み込みできないのが成功。) そもそもアパッチをどうインストールすればいいかについては、たとえば『PHP/確実に動作させるまで』などに解説があります。(2020年4月21日の時点では、まだ Apache 専用のページはWikibooks日本語版にはありません)。
GNU/Linux の CentOS系の場合、フォルダ階層 var/www/html に、目的のhtmlファイルを入れます。(なお、このようなフォルダ(そこにhtmlなどを入れるとサーバーが公開してくれる場所)のことをドキュメントルート DocumentRoot という。)
あらかじめ、目的のhtmlファイルを作っておく。
たとえば、serverTest.html というファイルが作ってあり、このhtmlファイルを公開したい場合、
まず、
というコマンドになります。
SE Linux がオンだと設定が面倒なので、
でSE Linuxをオフできます。
ウェブ・ブラウザーで http://localhost/serverTest.html にアクセスして、作成したhtmlどおりの内容が表示されれば、ここまでは成功。(外部公開するには、まだ作業が続く。)
ファイル名の部分(例では末尾の serverTest.html )は、作成したhtmlファイルのファイル名にします。
ウェブ・ブラウザーで確認し終わったら
でSElinuxの設定をオンに戻す。
PerlでCGIプログラムをする場合、
perlだけでなく perl-CGI もインストールする必要があります。
GNU/Linux の Fedoraの場合、
で両方とも入ります。sudo dnf install perl だけでは、perl-CGI がインストールされません。
Fedoraにインストールする場合、dnf コマンドでの perl-CGIの末尾3文字の「CGI」は大文字でなければなりません(でないとパッケージマネージャーが認識しません)。
下記のコードは、Perlによる単純なCGIプログラムの例です。CGIプログラムは、後述の設定をしたあとにウェブ・ブラウザーで閲覧して確認できます。(コマンド端末では確認できないか、著しく確認が困難。)
text/htmlのあとのエスケープシーケンスは必ず2つ \n\n としてください。もし1つだけだと、ブラウザで見てもエラーになり、「Hello World!」が表示されません。(もし \n が 1つだけだと「500 Internal Server Error」になります。)

というのは何かというと、これはshebangというOSの機能で、インタプリタに何を使うかを指定します。
書式はコメント文と同様に「#」から始まり形式的にはコメントですが、コメントではないので消さないでください。消すと動作しなくなります(例えば、bash のプロンプトから実行すると bash スクリプトとして perl スクリプトを実行してしまいます。おそらく bash の構文ではないのでエラーになります)。
PerlだけでなくUnix系のシェルスクリプトなど他のプログラム言語でも同様にshebangを記述する事があります。
は、HTTPレスポンス・ヘッダーの一部で、ウェブ・ブラウザーなどユーザー・エージェントは、HTML本体とは別に、受信しようとする情報の種類などの打合わせのために HTTPヘッダーを送受信しあってます(Perlの場合は「CGIヘッダー」ともいい「HTTPレスポンス・ヘッダー」と区別していますが、Webサーバがヘッダー要素を追加する可能性がある為です)。
そのHTTPレスポンス・ヘッダーで送受信しあう情報のひとつに「Content-Type: 」ヘッダーがあります。「Content-Type: text/html」というヘッダーによって「これからテキストの1つであるHTMLを送る」と相手先に伝えています。
HTMLのソースコードを送りたい場合は、下記のように書きます。
しかし実用的には、下記のようにプログラムを書いたほうがラクでしょう。
use warnings; とは何かというと、これはプログラム中にエラーがあったら警告を出すという意味です。Perlはプログラム言語ですので、エラーも起こりえます。そのエラーの際に警告を出すという意味です。
ですが、これはコマンド端末で実行している場合のハナシです。
ウェブ・ブラウザーで見ている場合、そのような気のきいた警告はしてくれません。
また、use warnings; は警告をするだけですので、そのままプログラムを実行します。けっして、気をきかしてプログラム停止したりはしません。
use strict; は、プログラムの停止なども含めて、より厳格に判定および処置をします。
なので、上記プログラムから use warnings; および use strict; を除去しても、ウェブ・ブラウザー上で表示する事は可能です。
このファイルは、拡張子をかならず「.cgi」にしてください。(拡張子「.cgi」または「.pl」にしないと、今後の設定が面倒になります。)
このファイルを、フォルダ階層
の中に配置します。
もし cgi-bin フォルダがまだ作れていない場合、perl-CGIがまだインストールされてないと思われるので、まずperl-CGIをインストールしてください。
所有者がrootになってるなどで、配置できないなら
で所有者を変更できます。
冒頭の
の部分は、環境によっては
の場合もあります。
この部分 #!/usr/local/bin/perl は、perlのインタプリタを呼出してスクリプトを渡すための指示です。
これらperlインタプリタのバイナリの存在場所をさがすには、コマンド
で探せます。
そして、制作したサンプルファイルは、アクセス権の設定で「プログラムとして実行可能」にチェックボックスを入れてください。右クリックで現れるダイアログから設定できると思います。
インタープリターへのパスがわからない場合は、あるいは色々な環境で動かすことが想定される場合(本書もそのケースです)
の様に POSIX でパスが決まっている env(1) を呼出し、(絶対パスでなく)コマンド名でインタープリターを指定します。 こうすると、env は環境変数PATHの中から順に インタープリター を探し、見つかったインタープリターにスクリプトを渡し起動します。
しかし、サーバがApacheの場合、まです、これだけでは動きません。
Apacheは初期設定では、cgiスクリプトを動かさない設定になっています。なので、まず、この初期設定を書き換える必要があります。
cgiスクリプトを動かせるように設定を変更するために、設定ファイルの httpd.conf というファイルを書き換えて、
という文章を追加する必要があります。
なお、通常のapacheでは、すでにコメントアウトされた状態で
とあるので、単に冒頭のコメントアウト記号#をはずせばいいだけです。
この書き換えにより、拡張子 .cgi のあるファイルを、cgiスクリプトとして処理できるようになります。
なお、perlなどで使われる拡張子 「.pl」のファイルもCGIスクリプトとして実行したいなら、上記の AddHandler に
と「.pl」を追加するだけで済みます。
ただし、管理者が通常では root になっているので、そのままでは、書き換えできません。なのでGNU/Linuxの場合、コマンドで
で、管理者を変えてから、管理者設定を書き換えることになります。

書き換えが終わったら、apache を立ち上げ直します。
そして、ウェブ・ブラウザーで
にアクセスしてください。
ブラウザ画面上に
と表示されています。また、そのページのタイトルとして、タブ欄などに「Example Web Page」と書いてあります。

では、より実用的なプログラムを見ていきましょう。
下記のプログラムは、入力した文字列を、htmlのフォーム機能を使って別ファイル(例では catchtest.cgi ) に送るプログラムです。
※ 『PHP/HTMLフォームからのデータ受け取り』と動作内容は同じです。
このように、パターンとして
というような書式で、単に <!DOCTYPE html> と EOT のあいだに、お決まりのパターンのコードを書くだけで、入出力機能のあるファームも簡単に作れます。

上記のコードの遷移先のページは、下記のようにつくります
たとえば ggggggg とブラウザに表示された入力ボックスにしてボタン「登録」を押すと、
と表示されます。
まず、遷移先のページにも、shebangやHTTPレスポンス・ヘッダーを忘れないようにしましょう(無いとエラーになります(Internal Server Error など) )。
上記コードの if文 と else文 は、決まり文句です。 $msg以外はすべて、Perlでの決まり文句です。STDINは標準入力のことです。
Perlでは、formタグからのPOSTの受け取りは、標準入力 STDIN を通して受け取りが行われる仕様です。
環境変数として REQUEST_METHOD や CONTENT_LENGTH や QUERY_STRING という環境変数があらかじめ用意されています。なので上記コードでは、この変数はこのまま使う必要があります(勝手に名前を変えてはイケナイ)。
なお、環境変数を英語で environmental variable と言います。
というのは、おおむね「もし環境変数 REQUEST_METHOD が POST なら」 のような意味です。
環境変数 REQUEST_METHOD には、フォームを呼び出した時のリクエストの結果がPOSTまたはGETのどちらかとして入っています。

eq 演算子は、「eqの左右の両辺をもし文字列とした場合に、両辺が等しいか?」を調べる演算子です。
いっぽう、== 演算子は、両辺を数値とした場合に等しいかを調べる演算子です。(C言語と違って、Perlでは変数の宣言時に型指定が無いので、条件分岐if文では、こういった演算子の区別が必要になります。)
なので、けっして eq演算子の部分を == 演算子に変えてはダメです。

なお、両辺が等しくない場合については、文字として評価する場合には ne 演算子、数値として評価する場合には != 演算子 です。

さて、表示結果の username というのは単に、勝手につけたオブジェクト名であり、呼び出し元のファイルのHTMLタグで勝手に命名したオブジェクト名ですので、もしそのオブジェクト名が変われば、表示結果の左辺のこの部分は名前になります。
結局
のように、オブジェクト名と一緒に、Perlでは POST で受け取った内容を管理する仕組みです。
より高度なCGIプログラムは次のようになります。
上記の書き方は「信じられない植物 ダウンロード」で検索して、参考に見てください。CGIのゲームです。
ちょっと古い見なれた構文 オリジナルです。printは一般的に使われています。