天天看點

mac安裝apache的mod_wsgi子產品錯誤總結以及hello world測試

mac系統版本為OS X EI Capitan 10.11.4

(其實系統已經安裝好了管理者權限的apache,在/etc/apache2下,但是我們還是要安裝使用者權限的apache,友善更改檔案不需要權限)

預設已經在mac上面安裝好了使用者權限的apache。(如果沒有安裝好的話,傳送門:Apache Installing

apache安裝的一些小問題

我簡單說說在安裝apache過程中遇到的問題:

  • 如果遇到OSError或者寫入錯誤的話,一般是沒有root目錄下的寫入權限,使用sudo指令獲得權限就好。
  • configure: error: C compiler cannot create executables 解決方法傳送門
  • 通常在安裝的過程中會遇到各種各樣的工具缺失,比如apr,pcre等,去官網下載下傳源碼下來解壓,然後運作configure檔案後編譯就好了。指令如下:
./configure --prefix=安裝位址
make
make install
#如果想清除之前的.o檔案可以使用make distclean
           

安裝好apache之後指令行進入bin目錄下運作./apachectl start啟動apache服務。

  • 啟動過程中最常見的就是80端口被占用,展現為套接字無法綁定位址,為了省事,我直接将apache中conf目錄下的httpd.conf檔案中監聽的端口改成了8000。
  • 以及還遇到了這個錯誤:httpd: Could not reliably determine the server’s fully qualified domain name, using 127.0.0.1 for ServerName

    這裡需要改一下/etc/hosts檔案以及ServerName屬性,詳細解決方法看以上連結。

開啟浏覽器輸入localhost後傳回it works之後apache則安裝成功。

apache安裝擴充子產品mod_wsgi

安裝方法傳送門:mod_wsgi installation

第一種方法是傳統的apache安裝擴充子產品的方法,先下載下傳mod_wsgi源碼,configure然後再編譯安裝,然而因為在make intall的時候出現了root權限問題(用sudo也無法解決,詳細的情況讨論請參見這裡),是以我選擇了用第二種方法安裝mod_wsgi子產品。

第二種方法就是直接用pip安裝mod_wsgi,安裝好之後将mod_wsgi-py27.so的路徑配置在httpd.conf檔案中。指令如下:

[sudo] pip install mod_wsgi
mod_wsgi-express module-location
#将輸出的路徑複制到httpd.conf中,假設輸出的路徑為/user/local/mod_wsgi-py27.so
#在http.conf中寫入以下指令:
LoadModule wsgi_module /user/local/mod_wsgi-py27.so
           

重新啟動apache伺服器,mod_wsgi子產品就應該安裝好了。

hello world example 與 mod_wsgi子產品互動

接下來可以試一下用一個簡單的hello world application來測試一下mod_wsgi子產品的正常工作。

定義一個符合WSGI标準的application并儲存該檔案為hello.wsgi。(如果不太清楚WSGI标準的可以參看我的一篇部落格: WSGI初探及wsgiref簡單實作)

#hello.wsgi
def application(environ, start_response):
    status = "200 OK"
    response_headers = [('Content-type', 'text/plain')]
    output = "hello world!"
    start_response(status, response_headers)
    return [output]
           

我嘗試用了兩種方法來配置apache使其調用hello.wsgi傳回hello world。

  1. 第一種方法就是直接将hello.wsgi放在apache的根目錄下通路,比較簡單。
  2. 第二種方法就是在apache上配置一個虛拟主機,通過自己設定的域名來通路hello.wsgi。

我們先來看第一種方法:

  1. 首先打開conf目錄下的httpd.conf檔案(就是apache的主伺服器的配置檔案),找到DocumentRoot變量,它的值就是apache伺服器的根目錄,把你的hello.wsgi檔案拖到該目錄下。(注意,在mac下應該已經确認在Finder中打開所有的檔案字尾名,hello.wsgi的字尾名為.wsgi,當然,不一定要使用字尾名.wsgi,也可以使用.py字尾)
  2. 然後在DocumentRoot變量(假設為/Users/Apache/WWW)下設定WSGI腳本的别名:

在打開apache服務後,我們在浏覽器中輸入localhost :8000/hello.wsgi (監聽的端口為8000),即可看到“hello world!”。

值得注意的是,如果WSGIScriptAlias設定成了:

WSGIScriptAlias / /Users/Apache/WWW/hello.wsgi
           

那麼在WWW目錄下的所有靜态檔案都會被屏蔽,對localhost:8000/*(*表示任意字元)的任意通路都會轉換成對hello.wsgi的通路。如果我們還想要通路在WWW目錄下的靜态檔案,則需要用到Alias指令。

第二種方法:

1.首先 在http.conf檔案中設定可以引入包含虛拟主機的檔案:

# Virtual hosts
# Include conf/extra/httpd-vhosts.conf
将上面的#去掉就可以引入虛拟主機的配置檔案了
           

2.在extra目錄下找到http-ghosts.conf配置virtual host,基本跟配置主伺服器一樣:

(假設虛拟主機的根目錄為/Users/Apache/VirtualHost,監聽的端口為8001)

<VirtualHost *:8001>
    DocumentRoot "/Users/Apache/VirtualHost"
    ServerName www.virtualhost.com
    ServerAlias virtualhost.com
    WSGIScriptAlias /hello.wsgi /Users/Apache/VirtualHost/hello.wsgi
    DirectoryIndex index.html
    <Directory "/Users/Apache/VirtualHost">
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>
           

3.在設定完虛拟主機的配置檔案之後,我們還不能在浏覽器中立即測試我們的新域名,我們還要将新域名和127.0.0.1綁定起來。是以打開/etc/hosts檔案,綁定域名和位址(修改檔案需要權限):

那麼/etc/hosts為什麼要這樣設定呢?

一般來說,當浏覽器得到域名的時候,浏覽器首先通過/etc/hosts檔案查詢它的ip位址,得不到ip的時候再向DNS伺服器查詢。是以,如果我們在mac上設定了shadowsocks的全局代理,所有的請求直接走代理,那麼我們就擷取不到這個我們自己創立的域名的ip位址了。(是以記得關閉你的翻牆工具)

此時,我們打開浏覽器就可以輸入virtualhost.com:8000/hello.wsgi就能看到“hello world!”了。

關于mod_wsgi子產品的embedded mode(嵌入模式)與Daemon Process(守護程序)

mod_wsgi子產品在加載WSGI應用程式的時候有兩種不同的模式,預設使用的是嵌入模式,而另一種模式是守護程序,等會我們會講述如何開啟守護程序。

這兩種模式有什麼不同呢?嵌入模式将會直接在apache的子程序中加載WSGI Application,而守護程序則會在與apache程序的不同程序中加載,需要進行程序間的通信機制。是以,如果對WSGI Application的代碼進行了修改,那麼在嵌入模式下需要重新開機apache伺服器,而在守護程序下則不需要重新開機伺服器(這對于如果沒有重新開機伺服器的權限卻又需要修改應用程式的情況下是很有用的)。

以及,如果多個django的項目布置在同一台apache伺服器上,也是推薦用守護程序,否則程序中的django_settings_module會互相錯亂,具體參考這裡:How to use Django with Apache and mod_wsgi。

接下來是Daemon process的virtual host配置代碼(在第二種方法的代碼基礎上加上以下代碼):

#在VirtualHost标簽内加上以下代碼
WSGIDaemonProcess virtualhost.com processes= threads= display-name=%{GROUP}
WSGIProcessGroup virtualhost.com

#在VirtualHost标簽以外加上以下代碼
WSGISocketPrefix /Users/Apache/run/wsgi
           

關于前兩行代碼的詳細作用請參考官方文檔。

重點說一下最後一行的作用,首先假設我們沒有在VirtualHost标簽以外加上WSGISocketPrefix,或者,WSGISocketPrefix指定的目錄沒有讀寫權限,我們通路hello.wsgi都會傳回:

Service Unavailable

The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.
           

為什麼會這樣呢?首先我們知道Daemon模式下是不同程序間的通信,而其中使用了本地的socket,是以,伺服器端需要對一個檔案目錄擁有寫的權限來儲存socket檔案,用戶端需要知道這養的一個檔案目錄并且具有讀的權限來擷取socket檔案。是以,WSGISocketPrefix變量值隻要設定一個具有讀寫權限的任意目錄就可以了。

詳細的英文解釋:mod_wsgi ConfigurationIssues

mod_wsgi子產品部署django應用

官方文檔說的非常清楚,别忘了WSGIPythonPath變量即可(嵌入模式與守護程序配置不一樣)。

官方文檔傳送門