この記事は過去のエラー解決メモを整理したものです。
現在の推奨手順とは異なる可能性があります。
公式ドキュメントを確認して最新情報と差分がないかを確認してください。
事象
XserverにDjangoアプリをデプロイしたところ、ブラウザでアクセスした際に Internal Server Error 500 が発生した。
環境
- Xserver
- Django
- Python 3.12
- CGI
原因
原因は次の2つだった。
- Python環境に
PyMySQLがインストールされていなかった -
index.cgiにCGI実行時に必要な環境変数が設定されていなかった
対策
1. Xserverのエラーログを確認する
まず、Xserverの管理画面からエラーログを確認する。
- サーバー管理 > アクセス解析 > エラーログ
ログには次のように End of script output before headers: index.cgi が出ていた。
xsrv.jp.error_log
[Tue Oct 31 22:32:35.117072 2023] [cgid:error] [pid 3012133:tid 3012253] [client 106.154.147.88:55900] End of script output before headers: index.cgi
[Tue Oct 31 22:32:47.929607 2023] [cgid:error] [pid 3012133:tid 3012278] [client 106.154.147.88:42784] End of script output before headers: index.cgi
[Tue Oct 31 22:32:49.228605 2023] [cgid:error] [pid 3012135:tid 3012633] [client 106.154.147.88:42790] End of script output before headers: index.cgi
このログから、Django側の画面表示以前に index.cgi の実行で失敗していると判断した。
2. index.cgi を直接実行してエラー箇所を確認する
SSHでサーバーに入り、index.cgi を直接実行して詳細なエラーを確認する。
cd /home/xs797670/xs797670.xsrv.jp/public_html/project_dir/
./index.cgi
>File "/home/xs797670/xs797670.xsrv.jp/public_html/project_dir/.venv/lib/python3.12/site-packages/django/db/backends/mysql/base.py", line 17, in <module>
> raise ImproperlyConfigured(
>django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.
>Did you install mysqlclient?
Error loading MySQLdb module が出ているため、MySQL接続用のライブラリが不足している。
3. PyMySQL をインストールする
PyMySQL が入っていなかったので、Python 3.12 の環境にインストールする。
pip3 show PyMySQL
>WARNING: Package(s) not found: PyMySQL
pip3.12 install pymysql
pip3.12 show pymysql
>Name: PyMySQL
4. index.cgi を再実行して次のエラーを確認する
PyMySQL を入れた後にもう一度 index.cgi を実行すると、今度は REQUEST_METHOD がないというエラーになった。
cd /home/xs797670/xs797670.xsrv.jp/public_html/project_dir/
./index.cgi
>File "/home/xs797670/xs797670.xsrv.jp/public_html/project_dir/.venv/lib/python3.12/site-packages/django/core/handlers/wsgi.py", line 71, in __init__
>self.method = environ["REQUEST_METHOD"].upper()
> ~~~~~~~^^^^^^^^^^^^^^^^^^
>KeyError: 'REQUEST_METHOD'
>Status: 500 Internal Server Error
>Content-Type: text/plain
>Content-Length: 59
index.cgi をコマンドラインから直接実行した場合、CGIとして実行されるときに渡される環境変数が不足する。そのため、index.cgi 側で必要な値を設定する。
5. index.cgi に環境変数を追加する
index.cgi に SERVER_NAME、SERVER_PORT、REQUEST_METHOD などを追加する。
import sys, os
import pymysql
from wsgiref.handlers import CGIHandler
from django.core.wsgi import get_wsgi_application
sys.path.insert(0, "/home/xs797670/xs797670.xsrv.jp/public_html/project_dir/.venv/bin")
sys.path.append('/home/xs797670/xs797670.xsrv.jp/public_html/project_dir/neoseruko_djnago_projects/website_with_wix')
sys.path.append('/home/xs797670/xs797670.xsrv.jp/public_html/project_dir/neoseruko_djnago_projects/website_with_wix/config')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
os.environ['DJANGO_SETTINGS_MODULE'] = 'config.settings'
# ここを追加
os.environ["SERVER_NAME"] = "http://xs797670.xsrv.jp/"
os.environ["SERVER_PORT"] = "443"
os.environ["REQUEST_METHOD"] = "GET"
os.environ['OPENBLAS_NUM_THREADS'] = "1"
pymysql.install_as_MySQLdb()
application = get_wsgi_application()
CGIHandler().run(application)
6. 再度 index.cgi を実行して確認する
設定後に index.cgi を実行すると、500エラーではなく 400 Bad Request が返るようになった。
./index.cgi
>Status: 400 Bad Request
>Content-Type: text/html; charset=utf-8
>X-Content-Type-Options: nosniff
>Referrer-Policy: same-origin
>Cross-Origin-Opener-Policy: same-origin
>
>
><!doctype html>
><html lang="en">
><head>
><title>Bad Request (400)</title>
></head>
><body>
><h1>Bad Request (400)</h1><p></p>
></body>
></html>
index.cgi を直接実行した場合はリクエスト情報が完全ではないため 400 Bad Request になるが、Internal Server Error 500 の原因だったCGI実行エラーは解消できた。