前提:
- localhostへアクセスしてCGIを動作させる
- homebrewがインストールされている(here)
- nginxがhomebrewを利用して既にインストールされている
brew install nginx
最初の時点でnginxが起動している必要はありません。
初学者につき、sudoやchmod 777を多用しますが、ご容赦ください。
個人的な試作のみで利用するのが良いと思います。
ステップ1: CGI実行に必要なパッケージのインストール
以下2つのツールをインストールします。
- fcgiwrap
- spawn-fcgi
以下のコマンドを利用してください。
brew install fcgiwrap spawn-fcgi
[fcgiwrap]
CGIを高速安全に実行する外部ツール。NginxとCGIスクリプトの間の接続を提供する。wiki
[spawn-fcgi]
fcgiwrapを起動する。これによってNginxからfcgiwrapにアクセスできるようになる。
ステップ2: ディレクトリの作成と権限の変更
以下2つのディレクトリを作成します。
①cgiの実行ファイルを保存するディレクトリ
②cgiとnginxをつなげるソケットを保存するディレクトリ
ではまず①から。ディレクトリの権限が動作に影響を及ぼすので、ガイドに沿って行ってください。
cd /opt/homebrew/Cellar/nginx/1.25.4/
mkdir cgi-bin
chmod 777 cgi-bin
次に②です
cd /opt/homebrew/Cellar/nginx/1.25.4/
mkdir sock
chmod 777 sock
これでディレクトリ作成と権限の変更は完了。
ステップ3: cgiの実行ファイルを作成
以下の2つのファイルを、指定する名称と場所で作成してください。
ファイル名称「form.py」
/opt/homebrew/Cellar/nginx/1.25.4/cgi-bin/
にファイルを作成し、以下の内容を記載してください。
#!/opt/homebrew/bin/python
import cgi
import sys
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
print("[Python CGI]",file=sys.stderr)
print('Content-Type: text/html; charset=UTF-8\n')
html_body = """
<h1>[Python3 CGI]</h1>
<h2>area01 = "%s"</h2>
<h2>area02 = "%s"</h2>
"""
form = cgi.FieldStorage()
area01 = form.getvalue('area01', '')
area02 = form.getvalue('area02', '')
print(html_body % (area01, area02))
ファイル名称「form_py.html」
/opt/homebrew/Cellar/nginx/1.25.4/html
にファイルを作成し、以下の内容を記載してください。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Python CGI Form</title>
<head>
<body>
<form action="http://localhost:8100/form.py" method="post">
<input type="text" name="area01"> <BR />
<input type="text" name="area02"> <BR />
<input type="submit" name="submit">
</form>
</body>
</html>
ステップ4: fcgiwrapの設定
spawn-fcgiとfcgiwrapを連携させてバックグラウンドで実行します。
コマンドは以下です。
sudo -u _www spawn-fcgi -f /opt/homebrew/Cellar/fcgiwrap/1.1.0/sbin/fcgiwrap -d /opt/homebrew/Cellar/nginx/1.25.4/cgi-bin/ -s /opt/homebrew/Cellar/nginx/1.25.4/sock/cgi.sock
コマンドの説明
sudo -u _www
ユーザー:"_www"としてこの操作を実行します、という宣言です。
nginxのworkerprocessの起動ユーザーと同じユーザー名に設定します。(nginxの設定は後で説明)
オプション-fに続く引数
brewでインストールしたfcgiwrapの実行ファイルの場所を示しています。
brew info fcgiwrap
とコマンドを打つと、どのディレクトリにfcgiwrap用のスペースが確保されたかわかります。例:/opt/homebrew/Cellar/fcgiwrap/1.1.0
このディレクトリのさらに深いところ、./sbin/
にfcgiwrapの実行ファイルがあると思います。
オプション-dに続く引数
cgiのスクリプトファイル(form.pyなど)を保存するルートディレクトリです。
nginxのconfigure Fileでいう[root]のような意味ですね。
任意の場所を選ぶことができます。
オプション-sに続く引数
cgi.sock(名称は任意)は、fcgiwrapとnginxが通信するためのソケットです。
このコマンドを実行すると、ファイルは自動的に作成されます。
nginxがcgiスクリプトを実行する時には、このファイル(ソケット)を通して、fcgiwrapにデータを送出します。そしてcgiスクリプトの実行結果はこのソケットを通して、nginxに返送されます。
ソケットファイルはグラフィカル表示しても見えませんが、ls
コマンドをうてば見えます。
ステップ5: Nginxの設定
Nginxの設定ファイル(/opt/homebrew/etc/nginx/nginx.conf)を編集して、CGIスクリプトを処理するための設定を追加します。
nginx.confを以下に書き換えてください。
user _www;
error_log logs/error.log;
error_log logs/error.log notice;
error_log logs/error.log info;
error_log logs/error.log debug;
events {
worker_connections 1024;
}
http {
keepalive_timeout 65;
server {
listen 8100;
server_name localhost;
location / {
root html;
index index.html index.htm;
limit_except GET POST{
deny all;
}
}
location = /form.py{
root /opt/homebrew/Cellar/nginx/1.25.4/cgi-bin;
fastcgi_pass unix:/opt/homebrew/Cellar/nginx/1.25.4/sock/cgi.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
設定ファイルの記述の説明
ポイントを絞って設定ファイルの記述を説明します。
user _www
ユーザー名:_wwwがworkerプロセスの実行者です、という意味です。
fcigwrapの設定でも出てきましたね。この2つのユーザーは同じにしてください。異なると、権限エラーになる可能性があります。
error_log xxx
fcgiwrapとの接続に問題があった場合に、logへエラーを出力させるようにします。
デバック用ですね。
error_logの場所はこちら
location = /form.py
URIが~/form.pyと完全一致した場合に、このlocationの情報が利用されます。
root /opt/~~
サーバー側のリソースの場所です。
~/form.pyへアクセスがあったときに、このデータ(先に作ったcgiスクリプト)を実行します。
fastcgi_pass unix:/opt/~~
nginxとfcgiwrapが情報をやり取りする、ソケットファイルの保存場所です。
先ほど作成したソケットへのフルパスを記載します。
unix:~と書き出しているのは、同じホストのunixのソケットを利用した通信であることを示しています。
ステップ6: Nginxの再起動
変更を適用するためにNginxを(再)起動します。
//起動の場合
sudo nginx
//再起動の場合
sudo nginx -s reload
これで、Nginxを介してCGIスクリプトを実行する設定が完了しました。
ブラウザからhttp://localhost:8100/form_py.htmlにアクセスして、空欄を埋め、スクリプトが正しく実行されるかを確認してください。
ステップ7: エラーになる場合
error_logを確認する
error_logには、nginxがどのように処理をしようとしているのかが細かく出力されます。
ファイルが見つからない、実行の権限がない、などがわかるのでかなり参考になります。
fcgiwrapの実行ユーザーを確認する
ps aux | grep fcgiwrap
で実行ユーザーが「_www」になっているか確認してください。
もし違う場合は、最後に説明するクリーンアップを行い、ステップ3からやり直してください。
nginxのworkerプロセスの実行ユーザーを確認する
ps aux | grep nginx
で実行ユーザーが「_www」になっているか確認してください。
もし違う場合は、最後に説明するクリーンアップを行い、ステップ3からやり直してください。
503エラーの場合(もう一息の状態です)
form.pyの1行目を書き換えてみてください。
#!/opt/homebrew/bin/python
の場合、あなたのPCのpythonのパスと異なるかもしれません。
which python
とコマンドラインに入力して、出力されたパスに書き換えてみましょう。 #!出力されたパス
ステップ8: クリーンアップ
テストが終わったら、あなたのパソコンのリソースを開放しておきましょう。
ソケットファイルの削除
rm path_to_socket_file/cgi.sock
プロセスの停止
ps aux | grep fcgiwrap
上記のコマンドが成功すると、プロセスid(pid)が表示されます。
おそらく2つ表示されるので、fcgiwrap
の実行ファイルへのパスが表示されている方をkillします。
kill pid
表示されたpidに置き換えてください。