網頁服務器開發:CGI(2)

開發好的web CGI程序部署到linux主機上出現問題。

環境與條件

  • linux版本:ubuntu 12.04 server
  • Apache版本:2.4.18

產生問題

  1. 直接輸出CGI程序源文件(Python script source code)
  2. permision denied
  3. 元數據錯誤
  4. UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 11-12: ordinal not in range(128): /home/MyWebsite/cgi-bin/GetCustomNavigateContent.py

解決方案

輸出源文件的問題。

應該是Apache沒有設置好。查看apachectl -M 命令(查看Apache加載的所有模塊)。發現果然沒有cgi模塊。查看apachectl -l命令,發現有mod_so.c,這個模塊負責動態加載其它模塊,如果沒有這個模塊,動靜就大了,不再本文討論範圍之內。
發現mod_so.c之後,便知道可以更新配置文件動態加載Apache模塊。
在本機中Apache的配置文件在 /etc/apache2中的apache2.conf。裏面有這樣一句描述

# Include module configuration:
IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf

說明相關的配置文件在mods-enabled中生效。Apache自身攜帶了很多模塊,很多配置文件,位置在mods-available中,使用的時候只需要將其中的配置文件利用ln -s連接到enabled文件夾中即可。

/etc/apache2# tree -F 
.
├── apache2.conf
├── apache2.conf.bak
├── conf-available/
│   ├── apache2-doc.conf
│   ├── charset.conf
│   ├── localized-error-pages.conf
│   ├── other-vhosts-access-log.conf
│   ├── security.conf
│   └── serve-cgi-bin.conf
├── conf-enabled/
│   ├── apache2-doc.conf -> ../conf-available/apache2-doc.conf
│   ├── charset.conf -> ../conf-available/charset.conf
│   ├── localized-error-pages.conf -> ../conf-available/localized-error-pages.conf
│   ├── other-vhosts-access-log.conf -> ../conf-available/other-vhosts-access-log.conf
│   ├── security.conf -> ../conf-available/security.conf
│   └── serve-cgi-bin.conf -> ../conf-available/serve-cgi-bin.conf
├── envvars
├── magic
├── mods-available/
│   ├── access_compat.load
│   ├── actions.conf
│   ├── actions.load
│   ├── alias.conf
│   ├── alias.load
│   ├── allowmethods.load
│   ├── asis.load
│   ├── auth_basic.load
│   ├── auth_digest.load
│   ├── auth_form.load
│   ├── authn_anon.load
│   ├── authn_core.load
│   ├── authn_dbd.load
│   ├── authn_dbm.load
│   ├── authn_file.load
│   ├── authn_socache.load
│   ├── authnz_fcgi.load
│   ├── authnz_ldap.load
│   ├── authz_core.load
│   ├── authz_dbd.load
│   ├── authz_dbm.load
│   ├── authz_groupfile.load
│   ├── authz_host.load
│   ├── authz_owner.load
│   ├── authz_user.load
│   ├── autoindex.conf
│   ├── autoindex.load
│   ├── buffer.load
│   ├── cache_disk.conf
│   ├── cache_disk.load
│   ├── cache.load
│   ├── cache_socache.load
│   ├── cgid.conf
│   ├── cgid.load
│   ├── cgi.load
│   ├── charset_lite.load
│   ├── data.load
│   ├── dav_fs.conf
│   ├── dav_fs.load
│   ├── dav.load
│   ├── dav_lock.load
│   ├── dbd.load
│   ├── deflate.conf
│   ├── deflate.load
│   ├── dialup.load
│   ├── dir.conf
│   ├── dir.load
│   ├── dump_io.load
│   ├── echo.load
│   ├── env.load
│   ├── expires.load
│   ├── ext_filter.load
│   ├── file_cache.load
│   ├── filter.load
│   ├── headers.load
│   ├── heartbeat.load
│   ├── heartmonitor.load
│   ├── ident.load
│   ├── include.load
│   ├── info.conf
│   ├── info.load
│   ├── lbmethod_bybusyness.load
│   ├── lbmethod_byrequests.load
│   ├── lbmethod_bytraffic.load
│   ├── lbmethod_heartbeat.load
│   ├── ldap.conf
│   ├── ldap.load
│   ├── log_debug.load
│   ├── log_forensic.load
│   ├── lua.load
│   ├── macro.load
│   ├── mime.conf
│   ├── mime.load
│   ├── mime_magic.conf
│   ├── mime_magic.load
│   ├── mpm_event.conf
│   ├── mpm_event.load
│   ├── mpm_prefork.conf
│   ├── mpm_prefork.load
│   ├── mpm_worker.conf
│   ├── mpm_worker.load
│   ├── negotiation.conf
│   ├── negotiation.load
│   ├── proxy_ajp.load
│   ├── proxy_balancer.conf
│   ├── proxy_balancer.load
│   ├── proxy.conf
│   ├── proxy_connect.load
│   ├── proxy_express.load
│   ├── proxy_fcgi.load
│   ├── proxy_fdpass.load
│   ├── proxy_ftp.conf
│   ├── proxy_ftp.load
│   ├── proxy_html.conf
│   ├── proxy_html.load
│   ├── proxy_http.load
│   ├── proxy.load
│   ├── proxy_scgi.load
│   ├── proxy_wstunnel.load
│   ├── ratelimit.load
│   ├── reflector.load
│   ├── remoteip.load
│   ├── reqtimeout.conf
│   ├── reqtimeout.load
│   ├── request.load
│   ├── rewrite.load
│   ├── sed.load
│   ├── session_cookie.load
│   ├── session_crypto.load
│   ├── session_dbd.load
│   ├── session.load
│   ├── setenvif.conf
│   ├── setenvif.load
│   ├── slotmem_plain.load
│   ├── slotmem_shm.load
│   ├── socache_dbm.load
│   ├── socache_memcache.load
│   ├── socache_shmcb.load
│   ├── speling.load
│   ├── ssl.conf
│   ├── ssl.load
│   ├── status.conf
│   ├── status.load
│   ├── substitute.load
│   ├── suexec.load
│   ├── unique_id.load
│   ├── userdir.conf
│   ├── userdir.load
│   ├── usertrack.load
│   ├── vhost_alias.load
│   └── xml2enc.load
├── mods-enabled/
│   ├── access_compat.load -> ../mods-available/access_compat.load
│   ├── alias.conf -> ../mods-available/alias.conf
│   ├── alias.load -> ../mods-available/alias.load
│   ├── auth_basic.load -> ../mods-available/auth_basic.load
│   ├── authn_core.load -> ../mods-available/authn_core.load
│   ├── authn_file.load -> ../mods-available/authn_file.load
│   ├── authz_core.load -> ../mods-available/authz_core.load
│   ├── authz_host.load -> ../mods-available/authz_host.load
│   ├── authz_user.load -> ../mods-available/authz_user.load
│   ├── autoindex.conf -> ../mods-available/autoindex.conf
│   ├── autoindex.load -> ../mods-available/autoindex.load
│   ├── cgi.load -> ../mods-available/cgi.load
│   ├── deflate.conf -> ../mods-available/deflate.conf
│   ├── deflate.load -> ../mods-available/deflate.load
│   ├── dir.conf -> ../mods-available/dir.conf
│   ├── dir.load -> ../mods-available/dir.load
│   ├── env.load -> ../mods-available/env.load
│   ├── filter.load -> ../mods-available/filter.load
│   ├── mime.conf -> ../mods-available/mime.conf
│   ├── mime.load -> ../mods-available/mime.load
│   ├── mpm_event.conf -> ../mods-available/mpm_event.conf
│   ├── mpm_event.load -> ../mods-available/mpm_event.load
│   ├── negotiation.conf -> ../mods-available/negotiation.conf
│   ├── negotiation.load -> ../mods-available/negotiation.load
│   ├── setenvif.conf -> ../mods-available/setenvif.conf
│   ├── setenvif.load -> ../mods-available/setenvif.load
│   ├── status.conf -> ../mods-available/status.conf
│   └── status.load -> ../mods-available/status.load
├── ports.conf
├── sites-available/
│   ├── 000-default.conf
│   └── default-ssl.conf
└── sites-enabled/
    └── 000-default.conf -> ../sites-available/000-default.conf

本例中只需要一個cgi.load即可。如果是多線程的需要連接cgid.load與cgid.conf。

permision denied

出現此種問題說明權限不匹配,需要設置權限,爲Apache設置好CGI目錄執行權限之後,在CGI目錄所在和所操作的內容所在的位置利用chmod 777 -R path 修改權限去吧。

元數據錯誤

這個問題是將MacOS 上開發的Python部署到linux上發現的。原因在於兩個版本的python3.5採用的dbm存儲方式不同,解決方法,將初始化dbm數據過程轉化爲Python script腳本,傳到服務器之後,刪除所有數據,重新初始化。

UnicodeEncodeError

這個錯誤比較詭異。他出現的原因不明,解決的方案簡單,讓我瞠目結舌。
代碼中是這樣寫的。

customxml = open('CustomNavigate.xml', 'w')
customxml.write(r'''<?xml version="1.0" encoding="utf-8"?><root id="rootNode"><li>
        <a href="http://www.jd.com" target="_blank" collectnum="0" style="animation-delay: 6s;">
            <img src="http://img.9553.com/uploadfile/2016/1027/20161027053122646.jpg"/>
        </a>
        <p>中文字符</p>
    </li></root>''')
customxml.close()

xmlContent = open('CustomNavigate.xml')

for line in xmlContent.readlines():
    print(line)
    pass

重寫pythonscript之後一步步來執行發現完全不能輸出中文,無論是單獨輸出還是在文件中輸出。排故,一天找到如下方案。在文件頭部添加以下兩行。

import codecs, sys
sys.stdout = codecs.getwriter('utf8')(sys.stdout.buffer)

customxml='''<?xml version="1.0" encoding="utf-8"?><root id="rootNode"><li>
        <a href="http://www.jd.com" target="_blank" collectnum="0" style="animation-delay: 6s;">
            <img src="http://img.9553.com/uploadfile/2016/1027/20161027053122646.jpg"/>
        </a>
        <p>中文字符</p>
    </li></root>'''

file = open("CustomNavigate.xml",'w')
file.write(customxml)
file.close()

xmlfile = open('CustomNavigate.xml')
content = xmlfile.readlines()
for line in content:
    print(line)

以上代碼省略了許多過程,大家意會即可。經過測試,似乎是python3設置的問題。這個問題在shell執行環境下是無法發現的,必須放到CGI執行環境中才會出現,不知道爲什麼。
Mac OS + Python3 (服務器使用了Python內置的HTTPServer(srvraddr, CGIHTTPRequestHandler))搭建本地測試環境顯示正常,沒有linux主機的問題。很是奇怪。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章