nginx + fcgiwrap でcgiを動かす
nginxで小物のperlやpythonプログラムを動かすために、
Simple CGI support for Nginx (fcgiwrap)
を設定したときの作業内容です。
fcgiwrapをmakeするとき、
fcgi_stdio.h: そのようなファイルやディレクトリはありません
というエラーメッセージと共にビルドに失敗しました。
まずは、fastcgiのソースを取得し展開します。
#cd /usr/local/src
#wget http://www.fastcgi.com/dist/fcgi.tar.gz
#tar zxvf fcgi-2.4.0.tar.gz
#cd fcgi-2.4.0
#./configure
#make
#make install
次に、fcgiwrapのインストールを行います。
#wget http://github.com/gnosek/fcgiwrap/tarball/master
#tar zxvf gnosek-fcgiwrap-86921709962b95d4c7bf65c1c409c9809bf2e357.tar.gz
#cd gnosek-fcgiwrap-86921709962b95d4c7bf65c1c409c9809bf2e357
#make
#make install
[ -f /usr/local/bin/fcgiwrap ] && mv /usr/local/bin/fcgiwrap /usr/local/bin/fcgiwrap~
make: *** [install] エラー 1
こんな感じで、エラーが発生します。
注意点として、
・./configureはありません。
・make install はバイナリの移動に失敗します。
コンパイルは完了しているので手動でコピーしました。
#cp fcgiwrap /usr/local/bin/
※ここの作業は環境により異なります。
私はたまたまPythonをインストールしており、/usr/local/binのライブラリを
ロードするようにしていました。
#vi /etc/ld.so.conf.d/python-2.5.4.conf
/usr/local/bin
そのため、設定読み直しだけでfcgiのライブラリを読み込めましたが、
#vi /etc/ld.so.conf.d/fcgi.conf
/usr/local/bin
というファイルを作成した後に
#ldconfig
としてやる必要がありそうです。
次に、nginxの設定ファイルにcgiを起動する設定を行います。
###cgiに渡すパラメータファイルの保管先を作成
#mkdir /usr/local/nginx/conf
###設定ファイルをコピー
#cp /usr/local/nginx/fastcgi_params /usr/local/nginx/conf/
###nginxの設定ファイルを編集
#vi /usr/local/nginx/nginx.conf
location ~ ^/cgi-bin/.*\.cgi$
{
fastcgi_pass unix:/tmp/cgi.sock;
fastcgi_read_timeout 5m;
fastcgi_index index.cgi;
include conf/fastcgi_params;
}
cgi-bin/*.cgiへのアクセスを/tmp/cgi.sockに渡すようにしてやります。
cgi.sockを作成し、fcgiwrapへの仲介役を行うperlスクリプトを作成します。
#vi /usr/local/nginx/fcgi.pl
#!/usr/bin/perl
use strict;
use warnings FATAL => qw( all );
use IO::Socket::UNIX;
my $bin_path = '/usr/local/bin/fcgiwrap';
my $socket_path = $ARGV[0] || '/tmp/cgi.sock';
my $num_children = $ARGV[1] || 1;
close STDIN;
unlink $socket_path;
my $socket = IO::Socket::UNIX->new(
Local => $socket_path,
Listen => 100,
);
die "Cannot create socket at $socket_path: $!\n" unless $socket;
for (1 .. $num_children) {
my $pid = fork;
die "Cannot fork: $!" unless defined $pid;
next if $pid;
exec $bin_path;
die "Failed to exec $bin_path: $!\n";
}
###作成したファイルに実行権限付与
#chmod +x fcgi.pl
###実行
#./fcgi.pl
これで、/tmp/cgi.sockが作成されているはずです。
※これが正しいのか不明ですが、このままだとnginxのログに
connect() to unix:/tmp/cgi.sock failed (13: Permission denied) while connecting to upstream
と出力され、動いてくれませんでした。
とりあえずの対策として、
#chmod 777 /tmp/cgi.sock
を実行して逃げています。
次に、テスト用のプログラムを作成します。
#mkdir /usr/local/nginx/html/cgi-bin
#vi /usr/local/nginx/html/cgi-bin/test.cgi
#!/usr/bin/env perl
print "Content-type: text/html\n\n";
print "<html><head><title>Hello World</title></head>\n";
print "<body>\n";
print "<h2>Hello, world!</h2>\n";
print "</body></html>\n";
#chmod +x /usr/local/nginx/html/cgi-bin/test.cgi
/sbin/nginxを実行して、
http://www.example.com/cgi-bin/test.cgiにアクセスすると、
Hello, world!とPerlのプログラムが答えてくれます。
完全に理解できてはいないのですが、
・nginxはcgiのリクエストを/tmp/cgi.sockにリダイレクト
・fcgc.plが/tmp/cgi.sockへの処理要求をfcgiwrapにリダイレクト
・fcgiwrapでtest.cgiの処理を実行する。
という流れになるかと思います。
【参考URL】
Simple CGI support for Nginx (fcgiwrap)
NginxFcgiExample
nginx-fcgi
FastCGIのインストール(CentOS+Apache2)
もどる