2019年3月29日 星期五

如何在樹莓派 Apache 伺服器執行 Python 程式

今天看到 "樹哥的樹莓派(PI)" 分享了如何在樹莓派的 Apache 伺服器順利執行 Python 程式的秘訣 :

在Apache 以Python 視為 CGI 來源來執行

這篇主要是講為何照網路上說明去設定 Apache 的預設網頁設定檔 /etc/apache2/sites-available/000-default.conf 後, 網頁卻顯示程式原始碼, 根本沒執行的原因是, 在重啟 Apache 伺服器前應先下 sudo a2enmod cgi  指令以便在 /etc/apache2/mods-enabled/ 下產生一個 SymLink : cgid.load. 但沒提到如何修改 000-default.conf 設定檔.

這個 000-default.conf 設定檔原始內容如下, 有作用的部分只有兩行 :

pi@raspberrypi:~ $ sudo cat /etc/apache2/sites-available/000-default.conf 
<VirtualHost *:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        #ServerName www.example.com

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html

        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
</VirtualHost>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

我照樹哥文中圖片內容修改 000-default.conf, 加入如下內容 (藍色部分) :

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html
        ScriptAlias /cgi-bin/ /var/www/cgi-bin/
        <Directory "/var/www/cgi-bin">
            Options +ExecCGI
            AddHandler cgi-script .cgi .py
            Options FollowSymLinks
            Require all granted
        </Directory>

我使用 nano 編輯設定檔 :

pi@raspberrypi:~ $ sudo nano /etc/apache2/sites-available/000-default.conf
pi@raspberrypi:~ $ sudo cat /etc/apache2/sites-available/000-default.conf 
<VirtualHost *:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        #ServerName www.example.com

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html
        ScriptAlias /cgi-bin/ /var/www/cgi-bin/
        <Directory "/var/www/cgi-bin">
            Options +ExecCGI
            AddHandler cgi-script .cgi .py
            Options FollowSymLinks
            Require all granted
        </Directory>


        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
</VirtualHost>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

接著到 /www/var/ 底下新增 cgi-bin 子目錄, 然後在 cgi-bin 下編輯測試程式 test.py :

pi@raspberrypi:~ $ cd /var/www  
pi@raspberrypi:/var/www $ sudo mkdir cgi-bin  
pi@raspberrypi:/var/www $ ls  
cgi-bin  html
pi@raspberrypi:/var/www $ cd cgi-bin  
pi@raspberrypi:/var/www/cgi-bin $ nano test.py    

測試程式 test.py 內容如下 :

pi@raspberrypi:/var/www/cgi-bin $ cat test.py
#!/usr/bin/python 
print('Content-type: text/html\n\n')
print('<b>Hello World</b>')

就是簡單輸出 Hello World 而已. 注意, 第一行的 #!/usr/bin/python 不可少, 否則會因無法呼叫 Python 解譯器來執行檔案而造成 Internal Error. 

接著要用 chmod 將此 Python 程式之權限改為可執行 : 

pi@raspberrypi:/var/www/cgi-bin $ sudo chmod +x test.py  

最後, 重點來了, 要先下 sudo a2enmod cgi 建立連接, 再重啟伺服器 : 

pi@raspberrypi:/var/www/cgi-bin $ sudo a2enmod cgi   
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
Enabling module cgi.
To activate the new configuration, you need to run:
  service apache2 restart 
pi@raspberrypi:/var/www/cgi-bin $ sudo service apache2 restart 

開啟樹莓派瀏覽器, 網址輸入 localhost/cgi-bin/test.py 即可看到網頁輸出 Hello World :



如果沒有先下 sudo a2enmod cgi 就重啟伺服器的話, 將看到程式原始碼 :




雖然計畫使用 Nginx + Python, 沒有打算用 Apache, 但還是測試看看 Apache+Python 是否可行. 但前提是樹莓派要先安裝 Apache, 指令如下 :

$ sudo apt-get install apache2
參考 :

在樹莓派上架設 PHP+MySQL 網站伺服器
在 Windows 下安裝 Apache + Python
安裝 Apache2 + Python + MySQL
Run python script as cgi under apache2 server
Apache Web Server with cgi for python scripts

沒有留言 :