Python3 CGIを使ったWebページのデバッグ環境構築 on Mac

MacローカルにWebサーバを用意し,Python3ベースのCGIが組み込まれたWebページを正しく表示させる方法をメモ.

なお,この中の説明ではSystem Integrity Protection(SIP)で保護されたファイルを編集する作業があるため,事前にTime Machine等を用いてシステムのバックアップを取ることを強くお勧めする.

Python3のインストール

Mac OSには,デフォルトではPython 2系しか環境がインストールされていない.Python 3系の環境をインストールする際にpyenvを用いてインストールすれば,Python2系と3系の切り替えを容易に行えて便利なのだが,ここではHomebrewからPython3をインストールする.具体的には以下のコマンドを実行する.

$ brew install python3

Apache環境の準備

MacにはApacheサーバがあらかじめインストールされている.設定ファイルは/private/etc/apache2/以下にある.

httpd.conf

まずは,httpd.confを以下のDiffを参考に編集する.

sh-3.2# diff httpd.conf.backup httpd.conf  
157c157  
< #LoadModule cgi_module libexec/apache2/mod_cgi.so  
---
> LoadModule cgi_module libexec/apache2/mod_cgi.so
419c419  
<     #AddHandler cgi-script .cgi  
---
>     AddHandler cgi-script .cgi
540a541  
> Include /private/etc/apache2/site-enabled/*.conf

編集できたら,Webサイトごとの設定ファイルを保存するsite-available/ディレクトリと,ここから有効にする設定ファイルをシンボリックリンクで保存するsite-enabled/ディレクトリを以下のコマンドで作成する.

# mkdir /private/etc/apache2/{site-available,site-enabled}

VirtualHost

各サイトごとの設定ファイルを,site-available/ディレクトリの下に作成する.設定ファイルのサンプル(sample.conf)を以下に載せる.

Listen 58001

<Directory /Users/USERNAME/sample/>  
  Options -Indexes +FollowSymlinks +ExecCGI
  AllowOverride All
  Require all granted
</Directory>

<VirtualHost *:58001>  
  ServerName localhost
  DocumentRoot "/Users/USERNAME/sample"
</VirtualHost>  

ポート番号をベースにしたバーチャルホストを活用することで,同時に複数サイトのローカルデバッグが行えるようにしている.

設定ファイルを作成できたら,以下のようなコマンドを実行してsite-enabled/にリンクを張り,Apacheが設定ファイルを読み込めるようにする.

# ln -s /private/etc/apache2/site-available/sample.conf /private/etc/apache2/site-enabled/sample.conf

PATH環境変数に値を追加

デフォルトのApacheでは,Shebangに/usr/bin/env python3という風な指定をしたCGIプログラムを動作させる際に参照されるPATH環境変数には/usr/bin:/bin:/usr/sbin:/sbinしか入っていない.先ほどインストールしたPython3本体へのリンクは/usr/local/bin/の下にあるため,ApacheがPATH環境変数を通して実行することができない(もちろん,Shebangに直接Python3のリンクへの絶対パスを記述すれば実行可能ではあるが…).

そこで,PATH環境変数の先頭に/usr/local/binを追加し,ApacheからPython3のリンクが見えるようにする.これを実現するためには/System/Library/LaunchDaemons/org.apache.httpd.plistを編集する必要があるのだが,このファイルが/System/以下にあることから最近のMac OSで実装されたSystem Integrity Protection(SIP)の影響で管理者権限でも編集できない.なので,まずはSIPの一時的な無効化を行う.

SIP無効化

SIPの無効化を行うために,まずは+Rを押しながら再起動してリカバリーモードに入る.リカバリーモードに入れたらターミナルを起動し,以下のコマンドを実行する.

# csrutil disable

これでSIPが無効化されたので,いつも通りの再起動を行う.

値の追加

前述の操作でSIPが無効化されたので,/System/Library/LaunchDaemons/org.apache.httpd.plistを編集できる.具体的には,以下のように編集する.

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">  
<plist version="1.0">  
<dict>  
    <key>Disabled</key>
    <true/>
    <key>Label</key>
    <string>org.apache.httpd</string>
    <key>EnvironmentVariables</key>
    <dict>
        <key>XPC_SERVICES_UNAVAILABLE</key>
        <string>1</string>
        <key>PATH</key>
        <string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
    </dict>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/sbin/httpd-wrapper</string>
        <string>-D</string>
        <string>FOREGROUND</string>
    </array>
    <key>OnDemand</key>
    <false/>
</dict>  
</plist>  

追加したのは<key>EnvironmentVariables</key><dict></dict>内にある<key>PATH</key><string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>の二つ./usr/local/binを先頭に記述することで,PATH環境変数を用いて実行ファイルを見つける際に/usr/local/binを優先して扱ってくれる.

SIPの有効化

ファイルの編集が終わったら,忘れずにSIPを再び有効にしておく.+Rを押しながら再起動してリカバリーモードに入り,ターミナルを起動して以下のコマンドを実行する.

# csrutil enable

これでSIPが有効化されたので,いつも通りの再起動を行う.

動作テスト

さて,以上の作業でデバッグ環境は構築できたので,動作テストを行う. VirtualHost設定の際に指定したドキュメントルートディレクトリを作成し,その下にHTMLファイルなどを置いていく.動作テストに用いるWebページだが,Gistで公開しているものを使えばいい.

なお,cgiファイルについてはApacheから実行可能なように権限を付与する必要がある.具体的には以下のコマンドを実行する.

$ chmod +x ~/sample/sample.cgi

Webページの準備ができたら,以下のコマンドを順に実行し,Apacheの起動と念のための設定リロードを行う.

# apachectl start
# apachectl graceful

起動と設定ファイルの読み込みができたらブラウザでhttp://localhost:58001/にアクセスしてほしい.It works!という表示とその下のCGI Output:の右に現在の日時が表示されていれば,正しく動作している.

なお,Apacheのログファイルは/private/var/log/apache2/以下にあるので,正しく表示されない場合はここを参照してほしい.