サーバサイドプログラム
WWW のさらなる仕組み
動的WEBページ
WWWとは
で説明したように、 WWW サーバは基本的にはあらかじめ用意されたペー
ジを返すのですが、もっと自分のページを動的にしたい、例えば、「来訪
者カウンタ(自分のページに何人来たか)を表示させたい」とか「メッセー
ジを何か書きこんでもらう」などという要求があるのは当然のことです。
これを実現しようと思えばやはり「プログラム」が必要です。ただ一言
で「プログラム作ってWEBページで動かす」といっても、大きく次の2つ
にわかれます。
- クライアントサイド(クライアント側のブラウザ上)で動かす
- サーバサイド(WWWサーバマシン上[プロバイダのサーバ等])で動かす
です。これらのうち前者のクライアント側(ブラウザ)で動くものとして
は、 JavaScript, Java applet や
VBScriptなどがあります。これらのものは基本的に 状態が保存でき
ない ため、ユーザの使い勝手をよくするとか、見た目を修飾すると
かにもっぱら用いられます(とりあえずここでは説明を省略します)。
後者は、最近では「Webアプリケーション」と呼ばれることが多
いものですが、「サーバ側で動かす」ことにより、サーバー上のデー
タ(情報)を変化・保存することが可能となりますので、多彩な応
用ができます。ネット通販に代表されるように、現在のインターネットビ
ジネスは、この技術無しでは考えられません。サーバー側でプログラムを
動かす方法としては、Java Servletや ASP.NET 、SSI (Server Side
Include) 等がありますが、まずは最も基本的で一般的な CGI
(Common Gateway Interface) をとりあげます。
CGIとは?
CGI とは、サーバーホスト上で、WWW サーバプログラムが自分以外のプログラ
ムを呼び出し、目的とする処理を依頼し、(HTML形式で記述されている)処理
結果をWWW ブラウザに送りかえす仕組みです。ここで、呼び出した外部プログ
ラムのことをゲートウェイと呼ぶことがあり、CGI という言葉ができました。
以下の図のように、サーバーが外部プログラムの助けを借りて処理をおこなっ
ています。(上の普通の WWW の場合と見比べながら仕組みを理解するのが良
いかもしれません。)

この外部プログラムはそのサーバー上で動くプログラムであればどのよう
な言語・開発環境でも良いです。とはいえ、多くの場合 perl が最も一般
的でした。それは、perl の特徴が CGI の要求によくマッチしていたから
なのです(が、それは後述しています)。
最近のトレンドとしては、perl でごりごり書くのははやらなくて、
PHP/Python/Ruby で書き、さらに言うと、スクラッチから書くのではなく
アプリケーションフレームワーク使って開発、というものが大規模サイト
でも主流となっているようです(別途解説)。
(以下、興味のある人は独習してみてください)
CGIを含めた Web ページの設置方法
ここでは、一般的な(?UNIX系のサーバで、設定次第でなんとでもなるけど、
大抵のデフォルト設定では、の意)CGIを含めた Web ページの設置の方法を説
明します。 付録:学内でのWWWページの設置
も参考にしてください。
- その前に、当然CGIが許可されているサーバにページを設置する権限(ア
カウント)がある、という前提があります。一般には各自のホームディレクト
リの直下の public_html/ というディレクトリの下が、個人のページを設置す
るディレクトリです。もし無い場合はサーバに login して
mkdir ~/public_html
chmod 755 ~/public_html
として、ディレクトリを作って、 パーミッション(読み/書き/
実行の許可)
を与えておきましょう。"~" は、ホームディレクトリを表す特殊記号です。
755 の意味ですが、これは実は8進数で、左から「自分」「同じグループ」
「それ以外のユーザ」についての属性を表しています。そして、
それぞれの8進数=3ビットについて
- 頭のビット(4の位):読み込み可能
- 中のビット(2の位):書き込み可能
- 最後のビット(1の位):実行可能
という意味です。すると、755 とは、自分自身は読むのも書き込むのも実行も
可能、それ以外は読むのと実行は可能で、書き込みは不可、という意味になり
ます。慣れるまではピンとこないかもしれませんが、おいおい分かってくると
思います。chmod では、上のような8進数で直接パーミッションを指定するほ
か、
chmod +x ~/public_html
とすることで実行可能 (eXecutable) にする、という操作も可能です。詳細は
略します。
-
そして、以前に作ったページがある人はそのファイルを、無ければ以下のよう
な内容のファイルを、その public_html の下に index.html というファイル
名で置きます。
<html>
<body>
This is a test page.
</body>
</html>
Windows PC (以下、PC)がメインな人の場合、サーバである別マシンにファイルを「置く」
方法ですが、いくつかあります:
- un*x 上でエディタ(テキスト編集プログラム、「メモ帳」み
たいなもの)を使ってファイルを作成する;telnet で liweb ログインして作
業するということです。cat だけではあまりに非効率というわけで liweb に
は、標準的 エディタの vi
がもちろんありますが、そのほか、もう少し単純な nano というものが
あるので、利用するのも可です。emacs は残念ながらインストー
ルされてない模様です。
nano 「ファイル名」
とうつだけでエディタが使えるようになります。一通り編集が終ったら ESC
(エスケープキー)をおすとメニューが出て来ますので、エンターを2回うっ
てもらえれば書きこんで終了します。
- 但し、学内にかぎっていえば telnet は必要なくって、liweb 上のディ
レクトリ・ファイルは、Windows での「ホームディレクトリ」の下の
I:\unix\
以下にある、すなわち Windows ドメインの各自のディスク領域は unix 環境
でも共有されていますので、ここ(の public_html 以下)にコピーするか、
最初から
I:\unix\public_html\
の下に「メモ帳」や「TeraPad」等の Windows 上でのエディタで作成すればい
いわけです。とはいえ後述するように TeraPad がお勧めです。
- TeraPad では、改行コードの指定ができます。un*x では後で述べるように ^J = LF (Line Feed) だけで改
行を意味しますので、このように設定すれば、nkf 等で変換するような必要は
なくなります。ファイルをおいてアクセスした時 "Internal Server Error"
となった場合は、まずこの改行コードを確認してください。
-
さらに、さらに、どうも Widnows 側から liweb にファイルを作ると、デフォ
ルトのファイル属性は
-rwx--xr-x 1 maechan Doctor 251 Nov 13 09:39 sample.cgi
と(ちょっと変だけど…普通は644 か 755 なのに何故 715?) なるような設
定みたいです。そうすると、普段はCGI の設定のために TeraTerm でログイン
する、という作業は不要となります。
パーミッションの設
定だけでも自分でするなら、ログインしたあと($ はプロンプトのつ
もり);
$ cd public_html
$ chmod 755 foobar.cgi
$ logout
(foobar.cgi はファイル名)だけ覚えていればOKということになります。
それはそれとして、サーバー内で実際にどのようなことが行われているかを知っ
ておくことは必要ですし、学外の環境では un*x の知識は必須だと思いますの
で、出来るだけ telnet での操作も覚えておいてください。
…とはいえ、ここでつまずいて先に進むことが出来ないのも困るので、簡
単なシェルスクリプトを作りました。
html やCGIを作ったら、そのたびに liweb にログインして
/home/doctor/maechan/unix/bin/setperm
と打ちこんでもらうと、パーミッションの設定が適切に出来ると思います。い
ちいち面倒な場合は、 上で述べているように設定ファイル .cshrc
を自分のホームにおいておけば、単に setperm と打つだけで
設定できます。
-
前に何人かの学生さんから「TeraTerm での入力ミス等の修正方法がわからな
い」という問いをうけました。実は、アルファベットや数字や記号以外の特殊
キーの動作については stty というコマンドで再設定が可能なのですが、とり
あえずbackspace で1文字削除をしたい場合(デフォルトでは
shift+backspace だとうまくいくみたいです)は;
stty erace ^H
(^H はほんとは1文字でbackspace を打ったときに出る文字)とコマンドで打
つと、それ以降は backspace で1文字消去できます。これをログインするた
びに打ち込むのは面倒、という場合は、(csh 使いの場合は)ホームディレク
トリの .login というファイルに書いておけば、ログインした時に自動的に読
み込んで処理してくれますので、そのようにしてください。上述の dot-files
の中にサンプルを置いてありますので、コピーしてログインしなおせば問題は
無くなっているはずです。
-
public_html 内におくだけでは駄目な場合があり、上述のようにパーミッショ
ンのチェックが必要になります。index.html の場合だと liweb にログインして
ls -l index.html
として
-rwxr-xr-x 1 maechan maechan 1508 Nov 9 07:21 index.html
のように、誰でも読めるようになっていればOKです。
なっていなければ
chmod +r index.html
として読み出し許可してやります。
CGI も同様に、事前に作っておいてもいいですし、その場で (un*x 上で)編
集してもいいですし、とにかく foobar.cgi というファイルを作ります。そし
て、実行可能にしておけば動くはず、です(コードの問題は後
述)
perl 超入門
特徴
perl とは、WWW サーバ上で動く CGI プログラムとして使用できるプログ
ラミング言語のうち、最もよく利用されるものの1つです。その特徴は
以下の通りです。
- インタプリタ、つまりコンパイルの必要のないプログラムを書けばすぐ
動かせる言語です。C言語などで開発する場合はサーバーでコンパイル・リン
クしてやらないと動かせない、つまり大抵の場合シェルアカウントが必要です
が、perl ならそんな手間は不要です。
- 上に関連して、サーバのアーキテクチャに依存してないので、サーバプ
ログラムが (apache など)同じものであれば、ほとんどそのままでどこ
にもっていっても同じように動きます。コンパイルされたバイナリプロ
グラムは、一般に機種(CPU、OSの種類)に依存するので、別の機種に持って
いっても普通は動かないです。ちょっと思いつくだけでも、サーバーには
Pentium/II/III (Intel)、Sparc (SunMicrosystems), Alpha (HP(旧Compaq(元
DEC)))など、いろんな可能性があるでしょう。インタープリタで動く perl な
らその機種の心配は無用です。
CGI のさわり
本来はここでさらに perl の仕様を詳細に説明すべきですが、興味ある人は 最低限の説明 を参照してみ
てください。
ここでは、とりあえずまずは最初ということで、perl で CGI を構成すること
にします。最終的には HTML を出力するわけですので、その場合、もっとも普
通にかつ頻繁に使うのは「print」すなわち引数で与えられた文字列
をそのまま標準出力に書き出す命令になります。
print 命令の書き方は以下の通りです。
print "ブラウザに送りたい文字列\n";
ダブルコーテーション「″」で囲まれた文字列がブラウザに返されます。最後
にある「\n」は改行コードなのですが、これはあくまでこの perl プログラム
が生み出すHTML 文書の改行であってブラウザ上での改行ではありません。ブ
ラウザ上で改行させたければ <BR>タグを使って
print "あいうえお<BR>\n";
と記述します。
まずは、一番簡単な例を書いてみましょう。以下のような perl プログラムファ
イルを「test.cgi」などと名前で作成しサーバ上のデイレクトリに置きます。
#!/usr/bin/perl
#
print "Content-Type: text/html; charset=Shift_JIS\n\n";
print "\n";
print "perl test \n";
print "\n";
print "ここ本文1行目
\n";
print "ここ本文2行目
\n";
print "\n";
print "\n";
このファイルを実行するのには、ブラウザのURL(アドレス)に
http://puffin.hannan-u.ac.jp/lect/libs/nets/test.cgi
と入力します。
まず、このファイルの先頭行の
#!/usr/bin/perl
ですが、これはこのファイルが perl で書かれており、そのインタープリタ
(処理するプログラム)が /usr/bin に存在する、ということを指示していま
す。これは、unix系OS でスクリプトを動かす時のお約束なので、そういうも
のだと思って、当面はおまじないと思っていて従ってください。
とはいえ、たまに、「ちゃんとファイルを置いたのに動いてくれない!」と、は
まる人がいるのですが…
テキストファイルは基本的に文字(コード)の羅列なわけです。でも、我々は
適当な長さの行で折り返して編集したり表示したりしています。じゃぁ行の終
わりはどうなっているのかというと、ファイル内に 改行を表す特殊文字
(制御コード)がはいっていて、それを印として行をかえている、という
わけです。
そして、やっかいなことに、OSによって、改行を表すコードが違うのです。伝
統的に、unix 系 (Linux 含む)では ^J (0x0A) 1 文字、
DOS/Windows では ^M^J (0x0D0A) の2 文字、さらに MacOS (ver.9
以前)では ^M (0x0D) 1 文字(MacOS X は unix 系なので改行
は ^J のみ)で表しています。なので、何も考えないで Windows で
作ったテキストファイルを Linux に持っていくと、行の終わりに ^M が残った
ままになっていて、「/usr/bin/perl^M というプログラムなんて無い!」となっ
てしまうわけです。
TeraPad で作成する場合、「コードを指定して保存」で、
改行が LF だけになっているのを確認してください。
1行目をこうしておいて、あとはそのファイルの実行属性をON にしておくと、
あとは普通のプログラムのように(いちいちインタープリタを指定しなくても)
動いてくれます。属性を変更するには、そのファイルが test.cgi だとすると、
シェルから
chmod +x test.cgi
とコマンドを打ち込んでやればOKです。
プログラムの中身はというと単純で、基本的にはHTMLをそのまま出力している
わけですが、最初のprint 文だけは特別です。実は、HTTP のブラウザへの出
力は、メールと同様ヘッダ (header) と本文 (body) が必
ずあって、ヘッダの部分でいまからブラウザへ送信するデータの種類などを示
すきまりです。ヘッダと本文の間は空行であるのもメールの場合と同様です。
ここでは
Content-Type: text/html; charset=Shift_JIS
と出力してるので、「今から送信するデータは HTML のテキストであって、文
字セット(ここではコードとほぼ同義)が Shift_JIS ですよ」とサーバがブ
ラウザに教えている、というわけです。Windows で作ったテキストファイルは
デフォルトで SJIS なので SJISで送信するなら Shift_JIS (ハイフンではな
くアンダーバーであることに注意)とします。もし unix 上で euc で作成し
たのなら、Shift_JIS ではなくEUC-JP等と適切なコード名を書いておかないと
文字化けしてしまいます。
この場合はどうするかというと、FTPの時にバイナリモードではなくテキスト
モードで転送する(と、ソフトで自動変換してくれる)とか、あるいはシェル
で(元のが win-edit.html とすると)
nkf --unix win-edit.html > unixfile.html
とすることで、改行コードが変換されたものが unixfile.html として保存さ
れます。ついでに文字コードを例えば SJIS から JIS (ISO-2022-JP) に変換
するなら
nkf --unix --jis win-edit.html > unixfile.html
で一度にできます。あとは
rm win-edit.html
mv unixfile.html win-edit.html
と元のを消して名前をつけかえればOKです。
いずれにせよ、今自分が編集しているファイルのコード(文字セットと
改行コード)が何であるかを意識しないと、HTML/CGIはうまく動いてくれない
ことがあるということは是非覚えておいてください。
フォームで値を渡す
前のように print で出力するだけなら、最初からHTML 書いてるのとかわらな
いのであまりCGI を使う意義はなくって、クライアント(ブラウザ)からの入
力を活用できないとプログラムを動かしている意味がないです。そこで、ブラ
ウザからCGIへの値の渡し方について簡単に例を示します。
多く使われるのは、form というタグをつかって入力データを渡すことで
す。方法には GET, POST がありますがここでは詳細ははぶき当面 GET
method のみを使うものとします。その場合、以下のようなHTML をまず書
くことになります。
こうすると、cgi のパラメータとして入力したデータが例えば「まえだ」
だとしますと、
test2.cgi?IN=%1B%24B%24%5E%24%28%24%40%1B%28B
のような形で渡されます。これは実は文字列のコードの16進数表示になって
いることに注意してください。そして、test2.cgi として、
#! /usr/local/bin/perl
#
require 'jcode.pl';
$value = $ENV{'QUERY_STRING'} ;
$value =~ s/^IN=//;
$value =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg;
print "Content-Type: text/html; charset=Shift_JIS\n\n";
print "\n";
print "perl test \n";
print "\n";
print "入力された文字列は、
\n";
print "「".&jcode'sjis($value)."」です。
\n";
print " 目次にもどる\n";
print "\n";
print "\n";
のように作っておくと、
入力された文字列は、
「まえだ」です。
目次にもどる
のようにブラウザに帰ってきます。以下のフォームに入力してみてくださ
い。
ここで perl のサンプルを(場当たり的で申し訳ないですが)少しずつ解説し
ていきます。
- #!/usr/bin/perl
これは 上と同様です。
- #
これはコメント行です。
- require 'jcode.pl';
これはVB.NET でいう import 文に相当するもので、ライブラリを使うときに
指定します。ここで指定しているものは漢字コード変換用ライブラリです。
liweb では既に/usr/lib/perl5/site_perl/jcode.pl としてインストールされ
てるのですぐ使えますが、無い場合は自分でインストールする必要があります。
といってもこの jcode.pl というファイルをネットから落として cgi と同じ
場所に置くだけです。
- $value = $ENV{'QUERY_STRING'} ;
これは、先に指定されたパラメータを環境変数という形でとりこみ、それ
を変数 $value に格納してます。perl では変数の頭は(配列や連想記憶
の全体の参照を除き)かならず$ではじめます。環境変数についてはちょっ
とややこしいので、ここではおまじないとして「こうしたら取り込める」
と覚えておいてください。
- $value =~ s/^IN=//;
ここで、form で指定した input の名前"IN" をとりのぞいています。
- $value =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg;
実はパラメータの %1B%24B%24%5E%24%28%24%40%1B%28B は、「まえだ」を
変換した文字列だったのですが、それをもとの漢字コードにもどすおまじ
ないです。
- print "Content-Type: text/html; charset=Shift_JIS\n\n";
- print "<HTML>\n";
- print "<HEAD><TITLE>perl test </TITLE></HEAD>\n";
- print "<BODY>\n";
- print "入力された文字列は、<BR>\n";
ここまでは test.cgi とほぼ同じです。
- print "「".&jcode'sjis($value)."」です。<BR>\n";
ここで、上でもとめた $value 、すなわち入力文字列を SJIS コードに変
換して、それをプリントしています。
- print "<a href=\"cgi-intro.html\"> 元にもどる </a>\n";
test.cgi ではつけませんでしたが、このように「元にもどる」リンクを
つけておくと親切かもしれません。"\”" は、"" の中で文字として ″ を
使いたいときに \ を添えてあるもの(エスケープ)です。
- print "</BODY>\n";
- print "</HTML>\n";
これらは前と同じです。
ちなみに次の CGI だと、式をいれるとその結果を返してきます。これだと
ちゃんと「プログラムが動いている」ということが実感できるかもしれません。
呼び出しはこんな感じです。
test3.cgi の中身はこちらです。下のままなら、保存する時の漢字コードをEUC
に、改行コードをLFだけにするのを忘れないようにしてください。
#! /usr/bin/perl
#
require 'jcode.pl';
$value = $ENV{'QUERY_STRING'} ;
$value =~ s/^IN=//;
$value =~ s/\+//g;
$value =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg;
print "Content-Type: text/html; charset=EUC-JP\n\n";
print "\n";
print "perl test \n";
print "\n";
print "入力された文字列は「".&jcode'euc($value)."」で
\n";
print "結果は「".eval($value)."」です。
\n";
print " 元にもどる\n";
print "\n";
print "\n";
eval($value) という関数呼び出しで、$value という変数内の
式を、EVALuate (評価)して、すなわち計算して、
その結果を print で表示してるというわけです。
以上のようにして、ブラウザとサーバー上のCGIとのデータ連係ができる
ようになります。
前田としゆき maechan@hannan-u.ac.jp
講義用スタイル
印刷用スタイル
(開いてから、ページを再度更新してください)