こんにちは、河野です。bashでCGIの2回目です。
今回は「おまじない」の部分についてです。
おまじないとは
僕がCGIを始めたのは2000年間近のころで、Y2K問題とか言われていたころです。当時はCGIの最初の数行を「おまじない」として教わっていました。「理由はともかくこう書かないといけないんだよ」という感じでした。
1 2 3 4 5 6 7 8 9 |
#!/bin/bash # helloworld.cgi # おまじない echo "Content-type:text/plain" echo # 内容 echo "Hello World" |
前回はechoの部分からを「おまじない」と表記していますが、この辺りは諸説あるようですので、ファイルの1行目から解説していきたいと思います。
1行目について
#!/bin/bash
の部分ですが、これはshebangですね。Unix/Linux上でスクリプトを実行させるために必要な記述です。
簡単に言えば、先頭2バイトが#!だった場合に、指定されたプログラムにファイル名が引数として渡され、実行されるというルールです。
ですので、以下のようなsample.cgiがあった場合、
1 2 |
#!/bin/bash # sample.cgi |
以下の2つの実行方法は同じことになります。
1 2 |
$ ./sample.cgi $ /bin/bash sample.cgi |
指定するプログラムは、bashやperlなど、スクリプトを実行させるためのコマンドでなくてもかまいません。
試しに、以下のようなスクリプトを作って実行してみると、
sample.tail
1 2 3 4 5 6 7 |
#!/bin/tail -3 tailで3行表示する 1 2 3 4 5 |
1 2 3 4 |
$ ./sample.tail 3 4 5 |
となります。最後の3行が表示されていますね。
shebangについては、以下のページに詳しく記載されています。
UNIXの部屋 コマンド検索:shebang (*BSD/Linux)
echoの出力内容について
1 2 3 |
# おまじない echo "Content-type:text/plain" echo |
このechoの部分ですが、これが無かったらどうなるのでしょうか?
試しに以下のようなスクリプトを実行すると、Internal Server Errorが起こります。
1 2 3 4 |
#!/bin/bash # omajinai-nai.cgi echo "No omajinai!!!" |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$ curl -s http://localhost/bash-cgi/omajinai-nai.cgi <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>500 Internal Server Error</title> </head><body> <h1>Internal Server Error</h1> <p>The server encountered an internal error or misconfiguration and was unable to complete your request.</p> <p>Please contact the server administrator, root@localhost and inform them of the time the error occurred, and anything you might have done that may have caused the error.</p> <p>More information about this error may be available in the server error log.</p> <hr> <address>Apache/2.2.15 (CentOS) Server at localhost Port 80</address> </body></html> |
Apacheのエラーログはこんな感じです。
1 |
[Fri Feb 08 12:58:10 2013] [error] [client 127.0.0.1] malformed header from script. Bad header=No omajinai!!!: omajinai-nai.cgi |
不正なヘッダーだよ!と怒られています。echoしている「No omajinai!!!」に対して、Bad headerだとも言われていますね。
プログラムとして実行はできているものの、その出力内容に問題があるという状態です。
CGIのレスポンスのルール
このレスポンスについても、RFCで定められています。
1 2 3 4 5 |
6.2. Response Types The response comprises a message-header and a message-body, separated by a blank line. The message-header contains one or more header fields. The body may be NULL. |
レスポンスは、メッセージヘッダーとメッセージボディで構成されて、空行(blank line)で区切る。
メッセージヘッダーは1つ以上のヘッダーフィールドからなり、メッセージボディはNULLでも良い。
ということです。
つまり、echo文の2行は、メッセージヘッダーと空行を出力している部分ということですね。
当然、ヘッダーの内容にも意味がありますが、これは後の回で説明していこうと思います。
1 2 3 4 5 6 7 8 9 10 |
#!/bin/bash # helloworld.cgi # CGIのヘッダー部分 echo "Content-type:text/plain" # ヘッダーとボディを分ける空行 echo # ボディ echo "Hello World" |
「おまじない」の意味がようやく理解できました!
改行コードについて
まだまだ気になることがあります。
ヘッダーとボディを区切るために空行が必要と言っても、改行コードはどうしたら良いんでしょう。OSに依存するような気がしますが、だとしたらLinuxだとLFで、WindowsだとCRLFで良いのでしょうか?
RFCを参照しますと、
1 2 3 4 5 6 7 8 9 |
6.3.4. Protocol-Specific Header Fields The script MAY return any other header fields that relate to the response message defined by the specification for the SERVER_PROTOCOL (HTTP/1.0 [1] or HTTP/1.1 [4]). The server MUST translate the header data from the CGI header syntax to the HTTP header syntax if these differ. For example, the character sequence for newline (such as UNIX's US-ASCII LF) used by CGI scripts may not be the same as that used by HTTP (US-ASCII CR followed by LF). |
空行は、LFかもしれないし、CRLFかもしんないよ!と書いてありますね。試してみました。
LF
1 2 3 4 5 |
#!/bin/bash # lf.cgi echo -ne "Content-Type:text/plain\n\n" echo "LF" |
1 2 |
$ curl -s http://localhost/bash-cgi/lf.cgi LF |
CRLF
1 2 3 4 5 |
#!/bin/bash # crlf.cgi echo -ne "Content-Type:text/plain\r\n\r\n" echo "CRLF" |
1 2 |
curl -s http://localhost/bash-cgi/crlf.cgi CRLF |
ちゃんと両方実行されています。ヘッダーとボディの区切りは、LFでもCRLFでも大丈夫ということですね。改行コードはLFじゃないとダメだと思っていました…。
ちなみにCRのみだとエラーになります。
1 2 3 4 5 |
#!/bin/bash # cr.cgi echo -ne "Content-Type:text/plain\r\r" echo "CR" |
1 2 3 4 5 |
curl -s http://localhost/bash-cgi/cr.cgi <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>500 Internal Server Error</title> (省略します) |
注意点
注意してもらいたいのは、あくまでもレスポンスの改行コードです。CGIのファイルそのものに使用している改行コードはLFでないと、bashでの実行エラーになります。
この連載記事においては、以降は以下のようにします。
- ファイルの改行コードはLF
- レスポンスのヘッダーとボディの区切りにはCRLF
次回はヘッダーについて掘り下げていこうと思います。