XREAで動かしていたPython製CGIを復活させただけ

昔立てたPythonCGIが知らん間にInternal Server Errorになって動かなくなっていたので、色々やって復活させた。

Internal Server Error

1年くらい前にXREAマイグレーションがあったらしく、これに巻き込まれたか…。
www.xrea.com



本当は「Internal Server Error」が出力される際のエラーそのもののエラーログが見たいのだが、それは見れないみたい。
考えられる原因を順番につぶしていくしかない。

中身をいじるのがN年ぶりくらいなので色々うろ覚えのところからスタートだが、概ね以下のような順番でアタックして無事解消。

.htaccessの書き方おかしい説

おかしいということは無かったが、後続の手順でテスト用に仕込んだスクリプトが動かなかったりしたのは.htaccessの設定のせいだった。

知らん間にpythonのパスが変わっていた説

www.xrea.com
よく見ると、以前使っていた「/usr/local/bin/python3」ではなくなっており、現在は「/usr/bin/python3.6」
cgiの行頭のshebangを「#!/usr/bin/python3.6」のように修正する必要がありそう。
しかし、あとの検証で前のパスでも特に問題なく動くことが分かったので、根本原因ではなかった。

知らん間にパーミッションがおかしくなっている説

実行属性が設定されていない場合はInternal Server Errorになる。残念ながら、今回の場合は根本原因ではなかった。

とりあえずpythonが動くかを試す

「Content-type: text/html\n\n」を出力しておかないとInternal Server Errorになる。以下のQ9でもあるとおり、ありがちなミスらしい。
www.xrea.com
逆に、以下が動かないなら他が怪しい。

#!/usr/local/bin/python3
print("Content-type: text/html\n\n")

今回はこれで動いたので、とりあえずpython製のcgiを動かすという関門は突破できている。

エラーが発生するcgiのコードを少しずつ移植してエラー発生個所を特定する

今回の場合はcgi本体に記載されたimport文でエラーが発生していることがわかった。
import文をtry-exceptで囲んでも普通に機能することを今更ながら知った。

print("Content-type: text/html\n\n")
try:
    import [module名]
except Exception as e:
    print(e)
No module named 'mysql'

仮想環境にライブラリをインストールする

マイグレーション前はあったモジュールがマイグレーションによって失われたものと思われる。
そのためライブラリを自分でインストールして解決しようとしたが…

まず以下の手順でssh接続を行う。
help.xrea.com

$ python -m pip install --user mysql-connector-python
Exception:
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/pip/basecommand.py", line 215, in main
    status = self.run(options, args)
  File "/usr/lib/python3.6/site-packages/pip/commands/install.py", line 294, in run
    with self._build_session(options) as session:
  File "/usr/lib/python3.6/site-packages/pip/basecommand.py", line 72, in _build_session
    insecure_hosts=options.trusted_hosts,
  File "/usr/lib/python3.6/site-packages/pip/download.py", line 330, in __init__
    self.headers["User-Agent"] = user_agent()
  File "/usr/lib/python3.6/site-packages/pip/download.py", line 94, in user_agent
    from pip._vendor import distro
  File "/usr/lib/python3.6/site-packages/pip/_vendor/distro.py", line 1050, in <module>
    _distro = LinuxDistribution()
  File "/usr/lib/python3.6/site-packages/pip/_vendor/distro.py", line 595, in __init__
    self._distro_release_info = self._get_distro_release_info()
  File "/usr/lib/python3.6/site-packages/pip/_vendor/distro.py", line 984, in _get_distro_release_info
    basenames = os.listdir(_UNIXCONFDIR)
PermissionError: [Errno 13] Permission denied: '/etc'


このように、残念ながらXREAではpipコマンドでのライブラリインストールはできないらしい。
--user オプションを付与してもダメだった。

仕方ないので、仮想環境を構築してそちらにライブラリをインストールする。
手順は以下に述べられているとおり。
nakagawach.tokyo
zenn.dev


以下、「bottle」は今回付けた仮想環境の名前で、実際はどんな名前でもよい。

$ cd ~
$ python3 -m venv --without-pip bottle
$ source ./bottle/bin/activate

pipを使えるようにした後で、欲しいライブラリをインストールする。
以下を実行する前に、get-pip.pyを適当に引っ張ってきてftpで置いておく。
https://bootstrap.pypa.io/pip/3.6/get-pip.py

(bottle) $ python get-pip.py
(bottle) $ pip install mysql-connector-python==8.0.25
(bottle) $ deactivate

なお、上記でライブラリのバージョンを指定したのはpythonのバージョンが若干古く、
現時点で最新バージョンのライブラリをそのままインストールすると実行できなかったため。

これで確かに「No module named 'mysql'」が解消されることを確認する。
shebangを以下のようにすれば、ここで構築した仮想環境で実行することができる。

#!/virtual/[username]/bottle/bin/python3

これで無事解決。