升級 Nginx + 安裝 uWSGI + Python VirtualEnv + Bottle


先來安裝 easy_install 以配合安裝與建立 VirtualEnv
並且測試安裝 bottle 套件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 安裝 easy_install (如己經安裝可以省略)
wget http://peak.telecommunity.com/dist/ez_setup.py
python ez_setup.py

# 安裝 VirtualEnv 套件
/usr/local/bin/easy_install virtualenv

# 建立 VirtualEnv 環境 (為方便管理.則為每個專案建立各自的環境 {個人喜好})
mkdir /home/[用戶]/venv
/usr/local/bin/virtualenv --no-site-package /home/[用戶]/venv/[專案名]

# 激活 VirtualEnv (則安裝的 Python 套件都會裝到這環境下.不影響原有環境)
cd /home/[用戶]/venv/[專案名]
source bin/activate.csh

# 安裝例子 (以安裝 bottle 套件為例)
pip install bottle

* 因為環境中自身使用的是 csh .所以激活方法要由 activate 改為 activate.sh
* 成功轉為 virtualenv 後.前面會多了 "[專案名]" 而不是 bash/zsh 的 "(專案名)"

之後進入升級或者全新安裝 Nginx 和 uWSGI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 安裝 uWSGI
wget http://projects.unbit.it/downloads/uwsgi-0.9.6.8.tar.gz
tar zxvf uwsgi-0.9.6.8.tar.gz
cd uwsgi-0.9.6.8
make

# 複製 uwsgi 到新建的目錄 (方便管理)
mkdir /usr/local/uwsgi
cp uwsgi /usr/local/uwsgi/
cp uwsgi.xml /usr/local/uwsgi/[專案].xml

# 最後建立 logs 目錄給 uwsgi
mkdir /usr/local/uwsgi/logs
chown root:wheel /usr/local/uwsgi/logs

# 升級 Nginx 到 0.8.54 (其實就是安裝)
wget http://nginx.org/download/nginx-0.8.54.tar.gz
tar zxvf nginx-0.8.54.tar.gz
cd nginx-0.8.54
./configure --prefix=/usr/local/nginx --user=www --group=www --with-select_module --with-poll_module --with-http_ssl_module --with-http_gzip_static_module --with-http_flv_module --with-http_sub_module --with-http_stub_status_module --with-http_secure_link_module
make && make install

# 重啟 Nginx (因為執行中的 Nginx Process 不會被升級影響)
cd /usr/local/nginx
killall nginx
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

# 下面的指令可使執行中的 Nginx Process 重新讀取 Nginx.conf
# 不過請肯定你的進升已受升級影響.即已重啟 Nginx
# 過程為 stop, quit, reopen, reload. (version >= 0.7.53)
/usr/local/nginx/sbin/nginx -s reload

* 如果只是升級.將覆蓋原有的檔案.但是設定檔將不受覆蓋
* 如果不肯定是否已經安裝成功
可以嘗試將 nginx.conf 的 server_tokens 設為 off 或者 on.再查看 web header 是否有顯示或出現版本號

至於 Nginx 和 uWSGI 的設定有三種,目前我的測試暫時分別為 A. B. C

A. 應該是比較常見的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# nginx.conf
server {
listen 80;
charset utf-8;
root /home/[用戶]/[專案];
server_name domain.me www.domain.me;

location / {
include uwsgi_params;
uwsgi_param UWSGI_PYHOME /home/[用戶]/[專案];
uwsgi_param UWSGI_CHDIR /home/[用戶]/[專案];
uwsgi_param UWSGI_SCRIPT index; # 專案的 WSGI 入口檔案 (如 index.py, 但省略 .py 結尾)
uwsgi_pass 127.0.0.1:8888; # 對應的 WSGI 程式位置
}

location ^~ /static {
root /home/[用戶]/[專案];
access_log off;
}

location /status {
stub_status on;
access_log off;
}
}

# 刪掉 Nginx 再重啟 (可以用 reload)
killall nginx
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

# 啟動 uWSGI
# 格式 (/usr/local/uwsgi/uwsgi -s :8888 -H [VirtualEnv Path])
/usr/local/uwsgi/uwsgi --gid=[執行組] --uid=[執行用戶] -s :8888 -H /home/[用戶]/venv/[專案]

B. 的方法和 A. 其實是差不多.只是將參數放到了 uWSGI 中作為啟動參數

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# nginx.conf
server {
listen 80;
charset utf-8;
root /home/[用戶]/[專案];
server_name domain.me www.domain.me;

location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8888; # 對應的 WSGI 程式位置
}

location ^~ /static {
root /home/[用戶]/[專案];
access_log off;
}

location /status {
stub_status on;
access_log off;
}
}

# 刪掉 Nginx 再重啟 (可以用 reload)
killall nginx
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

# 啟動 uWSGI
# 格式 (/usr/local/uwsgi/uwsgi -s :8888 -H [VirtualEnv Path])
/usr/local/uwsgi/uwsgi -s :8888 -H /home/[用戶]/venv/[專案] --gid=[執行組] --uid=[執行用戶] --chdir=/home/[用戶]/[專案] --python-path=/home/[用戶]/[專案] --w=[WSGI Default Module (如: index.py)]

C. 的方法和 A. B. 也是同一想法.只是將參數都放到了一個 XML 檔案中.而 uWSGI 本身也支援 INI 檔案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# nginx.conf 的設定和 B. 的 nginx.config 

# 修改 [專案.xml]
<uwsgi>
<socket>127.0.0.1:8888</socket>
<home>/home/[用戶]/venv/[專案]</home>
<gid>[執行組]</gid>
<uid>[執行用戶]</uid>
<chdir>/home/[用戶]/[專案]</chdir>
<python -path>/home/[用戶]/[專案]</python>
<module>[WSGI Script (index)]</module>
</uwsgi>

# 刪掉 Nginx 再重啟 (可以用 reload)
killall nginx
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

# 啟動 uWSGI
/usr/local/uwsgi/uwsgi -x /usr/local/uwsgi/[專案].xml

最後將 uWSGI 加入開機時執行

1
2
3
# 如 C. 設定中的 XML 方法.加入到 /etc/rc.local
打開 vim /etc/rc.local
加入 /usr/local/uwsgi/uwsgi -x /usr/local/uwsgi/[專案].xml

其實補充

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# uWSGI 的啟動參數中可以加入以作運行記錄
參數: -d /usr/local/uwsgi/logs/專案].log
即如: /usr/local/uwsgi/uwsgi -x /usr/local/uwsgi/[專案].xml -d /usr/local/uwsgi/logs/專案].log

# 以下是我的設定檔
<uwsgi>
<socket>127.0.0.1:8888</socket>
<home>/home/[用戶]/venv/[專案]</home>
<gid>[執行組]</gid>
<uid>[執行用戶]</uid>
<chdir>/home/[用戶]/[專案]</chdir>
<python -path>/home/[用戶]/[專案]</python>
<module>[WSGI Script (index)]</module>
<limit -as>256MB</limit> <!-- 最大可用記憶體空間 -->
<harakiri>30</harakiri> <!-- 執行超過30秒則退出 -->
<processes>2</processes> <!-- 同時請求的最大進程 -->
<master /> <!-- 開啟主控制的進程 -->
<memory -report/> <!-- 開啟記憶體使用回報 -->
<logto>/usr/local/uwsgi/logs/[專案].log</logto>
</uwsgi>

最後就是測試的代碼(因為之前已經安裝了 bottle 所以以他作測試)
代碼如下,放到 /home/[用法]/[專案] 內就可以了 (如不行請重啟 nginx & uwsgi):

1
2
3
4
5
6
7
8
9
10
from bottle import route, run, default_app

@route('/')
def index():
return "hello world"

if __name__ == "__main__":
run(host="localhost", port=8888)
else:
application = default_app()