2025/04/23

さくらインターネットのレンタルサーバでindex.cgi経由でflaskを動かす

 こんにちは、Akira(Type-EDGE)です。

最近、flaskを使ってWEBアプリを使っていたのですが、ちょっとしたミスで全てのコードをrmして憤死しました。

ようやく立ち直って始めたのは良いですが、思うままにコードを書いていたせいで中身はあまり覚えておらず、立上げすらロクにできないことに気付きました。

せっかくの勉強の機会なので、今回は記録を付けていこうと思います。

さくらインターネットでindex.cgiを動かすには? 

apacheが阻む、さくらインターネットのサーバーエラー

index.cgiを動かそうとすると様々なおまじないが必要になりますが、凡そ以下のエラーになって躓くはず。

 suexec policy violation: see suexec log for more details
 End of script output before headers: index.cgi

 なんどもこのエラーに躓いていると「ハイハイ分かったよ、権限無いのは分かったから答え出せ」とキーボードをクラッシュしたくなっちゃうはず。

複合的に起きているので、1つずつ解決していきましょう

index.cgiの文字コード

正しいコードを書いている方は、以下の文字コードにして下さい。

文字コード: UFT-8
改行コード: LF

コードに問題が無い場合にはこれが答えです。

どこに書いてあるのか分からないけれど、こうしないと動きません。

index.cgiのパーミッション

chmod 755 index.cgi 

これでOKです。

.htaccessの記載事項

Options +ExecCGI
AddHandler cgi-script .cgi
DirectoryIndex index.cgi

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.cgi/$1 [QSA,L]

とりあえずこれ書いておいてください。

最低限の機能は備わっています。

最終的にはこんなコードになりました

import sys
import os
import traceback
from pathlib import Path
from datetime import datetime
import cgitb
cgitb.enable()

try:
  sys.path.insert(0, '/home/www/xxx')

  from wsgiref.handlers import CGIHandler
  from src.app import create_app

  class ProxyFix:
    def __init__(self, app):
      self.app = app
    def __call__(self, environ, start_response):
      environ['SCRIPT_NAME'] = ''
      return self.app(environ, start_response)

  app = create_app()
  app.wsgi_app = ProxyFix(app.wsgi_app)

  CGIHandler().run(app)

except Exception as e:
  # 明示的にヘッダー出力(Apacheの誤動作防止)
  print("Status: 500 Internal Server Error")
  print("Content-Type: text/plain\n")
  log_dir = Path("/home/www/xxx/log")
  log_dir.mkdir(parents=True, exist_ok=True)
  date_str = datetime.now().strftime("%Y-%m-%d")
  error_log_file = log_dir / f"{date_str}_cgi_error.log"
  current_time = datetime.now().strftime("%H:%M:%S")
  with error_log_file.open("a", encoding="utf-8") as f:
    f.write(f"[{current_time}] ERROR in index.cgi: CGI起動時エラー\n")
    f.write("例外クラス: " + e.__class__.__name__ + "\n")
    f.write("メッセージ: " + str(e) + "\n")
    f.write(traceback.format_exc())
    f.write("\n")
  sys.exit(1)

最後に

おまじないみたいに探し求めてたどり着いたコードだったのですが、やっぱりもう一度作り直すのはしんどいです。

私みたいに愚かなことをせずに、バックアップを取ったり、記録を取ったり、何かしらの形で残しておくのが賢い選択ですよね。

そういう風に過去の私に伝えてあげたいです。

0 件のコメント:

コメントを投稿

さくらインターネットのレンタルサーバでindex.cgi経由でflaskを動かす

 こんにちは、Akira(Type-EDGE)です。 最近、flaskを使ってWEBアプリを使っていたのですが、ちょっとしたミスで全てのコードをrmして憤死しました。 ようやく立ち直って始めたのは良いですが、思うままにコードを書いていたせいで中身はあまり覚えておらず、立上げすらロ...