nginx and django

nginx (Engine X ) 是比 Apache 小巧快速的網頁伺服器,設定上相對沒有那麼強大與複雜。

Apache 是採用行程池運作比較消耗資源,而 nginx 則是 event based,不會依照 request 生成 process or thread。

下載網址:http://nginx.org/en/download.html

只是操作起來比較不熟悉,跟 apache 用 service 的方式比較不同,所以比較不親和一點…但是相對來說設定的細節都比較容易

設定檔在 /etc/nginx.conf

nginx 當初是為了 reverse porxy 所設計的,所以在 r-proxy 上理當應該比 apache 為更適當的選擇[1]


$ nginx # 啟動

$ nginx -t # 檢查設定檔格式是否正確

$ nginx -s [stop|reload|...] # 送訊號給正在執行的 nginx

可以用 fastcgi 搭配 django 運作,

可以額外 include 一個 django 的設定檔,內容如下:

server {
        listen  80;
        server_name server.com;
        location / {
            fastcgi_pass unix:/home/www/server.sock;
#           fastcgi_pass 127.0.0.1:8000;
            include     fastcgi.conf;
            access_log  /var/log/nginx_django.log;
        }
}

然後用 django 內建的 server 跑 fastcgi 模式,就能讓 django 跟 nginx 接起來囉。

$ kill `cat /home/www/server.pid`
$ python ./manage.py runfcgi method=threaded \
          socket=/home/www/server.sock pidfile=/home/www/server.pid

這邊指定用 thread 的方式跑,然後把 socket 建在該檔案位置,用在重開的時候要用,這個 socket 位置對應到上面的 nginx 設定的 socket 位置,
也可以跑在某個 port 上面去對應,只是用檔案的方式好像比較安全?!..我也不太懂=_=
另外 django 內的 fastcgi.conf 內要注意一點:

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

<strong>fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;</strong>
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

<strong>fastcgi_param  PATH_INFO          $fastcgi_script_name;</strong>

粗體的設定是 django url 在 route 會用來判斷的變數要設定對。
然後在專案內的 setting.py 的裡面加上 FORCE_SCRIPT_NAME=”/”
原因跟上面 route 路由規則有關,否則網址倒頁的時候會出問題。 參考資源:

pietty linux 鍵盤設定 home,end,keypad

好像有一天 linux 灌了 ncurses 這個處理文字的視窗 lib 以後, pietty 鍵盤事件的 mapping 就變的怪怪的,

按 home 跟 end 都會跑出 ~ 來,某些按鍵也變的怪怪的,剛開始是把 connection > data > Terminal-typ string 由 xtern 改成 linux 好像就好轉了,

只是顯示的顏色都不一樣了有點不習慣~

而且在 git 要 commit 的時候打中文也會變亂碼,後來發現[1]可以修改 ~/.inputrc 來解決 ,猜測是 ncurses 要監聽更多的鍵盤事件,所以把大部分的鍵盤對應的符號都調整過造成的。

</span>
<pre>"\e[3~": delete-char
# this is actually equivalent to "\C-?": delete-char
# VT
"\e[1~": beginning-of-line
"\e[4~": end-of-line
# kvt
"\e[H":beginning-of-line
"\e[F":end-of-line
# rxvt and konsole (i.e. the KDE-app...)
"\e[7~":beginning-of-line
"\e[8~":end-of-line

另外發現 小鍵盤數字鍵不能打的問題把 Terminal > Feature > Disable application keypad mode 改一下就 ok 了。

一度有改 Terminal > Keyboard > The Home and the End Key 看起來是這個,結果改了以後變成 home 可以 end 不行…而且在 vim 裡面會壞掉。

參考資源:

nowjs 伺服器(Server)建立函式,用戶端(Client)呼叫,即時系統

githubhttp://nowjs.com/

這個新的 module 做了一件有趣的事,由於 node.js 在伺服器寫 js 已經蠻酷的,進一步應該很多人都會聯想到,要怎麼在伺服器跟瀏覽器上共用已經寫過的 js 函式。

也有些人提出了一些方法來做,可以做一些簡單的判斷來做目前環境是瀏覽器或是伺服器來做不同的處理。

而這個 nowjs 主要主打的是在伺服器寫一個 function,你可以在瀏覽器端呼叫到,已經頗有趣的以外,呼叫到能幹麼呢?

主要就是傳訊息,你可以直接在 client 端呼叫伺服器的函式,並同時在伺服器呼叫一個函式,等同於呼叫 client 端的函式,達到廣播到所有使用者端的效果,其實基於web socket 就能達到這個效果,但能想出這個介面並設計出來也還頗有新意的。

跟之前有 lib 做到 php 在伺服器端建立 ajax 的概念有點類似,想要簡化 ajax 要寫 js 對某些人所帶來的[[困擾]],但這個實現我看起來覺得蠻失敗的..

但這概念搬到 nodejs 的世界來反而有不一樣的出發點,因為這邊沒有在想說這是件麻煩,而是達到用 js 做到跨前後端的假象…

但要小心要是做的太漂亮,反而容易讓新手搞不懂前後端的分別了…其實 nodejs 對 web 新手來講應該不是一個好玩具…

這部份未來倒是可以發展一下…讓開發變得更適合新手應該比較容易推廣

範例:

//server
var everyone = require("now").initialize(httpServer);
//建立一個函式 供 client 呼叫 , 並呼叫一個 client 的函式
everyone.now.distributeMessage = function(message){
  everyone.now.receiveMessage(this.now.name, message);
};
//client
<script type="text/javascript" src="http://localhost:8080/nowjs/now.js"></script>

<script type="text/javascript">
  $(document).ready(function() {
    now.name = 'mlwmlw';
    now.distributeMessage('hello');
  //設計一個函式讓 server 可以呼叫= =?
    now.receiveMessage = function(name, message) {
        alert(name + ':' + message);
    };
});

以下是官方教學影片…

參考資源:

apache rewrite and VirtualDocumentRoot

參考資源:http://phorum.study-area.org/index.php?topic=17120.0

設定讓每個使用者可以自動對應到某個虛擬伺服器的方式


UseCanonicalName On

VirtualDocumentRoot /home/%1/www/%2

例如

http://mlwmlw.blog.mlwmlw.org/ 對應至 /home/mlwmlw/www/blog

ohmygod.test.mlwmlw.org/ 對應至 /home/ohmygod/www/test

%1 %2 %3 則是按照 dns 名稱的順序對照到實體目錄上

.htaccess rewrite

透過 rewrite 設定將某個網址導到某個資料夾下的 index.php  ,常用於 codeIgniter 的設定,

官方教學的方式如下,感覺只能處理網址是虛擬伺服器的情況,

例如上述的 blog.mlwmlw.org/index.php,才能成功,


RewriteEngine On
RewriteCond %{REQUEST_URI} !^(/index\.php|/img|/js|/css|/robots\.txt|/favicon\.ico)
RewriteRule ^(.*)$ /index.php/$1 [L]

否則都會導頁到根目錄下,例如我用 http://mlwmlw.org/~user/test/index.php,

他則會幫我弄成 http://mlwmlw.org/index.php =__=。

如果想要將網址http://mlwmlw.org/~user/dir/index.php/xxx/yyy

導至 /home/user/www/dir/index.php/xxx/yyy 下,則可以用以下的 rewrite。

透過 REQUEST_FILENAME 會產生完整的要求目錄的原理,

將他與時紀要求的路徑對應去產生群組 %1 %2 變數來使用接在 RewriteRule 內。

感覺 rewrite 實在有點複雜…甚至還有專書在討論

Definitive-Guide-Apache-mod_rewrite

搞了三四個專案的失敗經驗才成功寫出這個規則…否則以往都要依照使用者設定 virtual host ~

但是最上面的那個設好也是可以不用一一指定啦~

其實有一大堆作法…可以用…博大精深的 httpd configuration…

RewriteEngine on
RewriteCond $1 !^(index.php|images|robots.txt|assets|temp)
RewriteCond %{REQUEST_FILENAME} ^/home/(.+)/www/(.+)/(.*)
RewriteRule ^(.*)$ /~%1/%2/index.php/$1 [L]

RewriteRule 對應的正規在比照的是 mlwmlw.org/index.php?abc=123 網址裡面的 /index.php?abc=123
所以如果寫 RewriteRule a http://a.com 則是 index.php?abc=123 裡面有出現 a 這個字就會轉頁,
如果要完整比對整個字串應該是要加上 ^a$ 來指定從開頭對照到結尾

%{REQUEST_FILENAME} 看到的是完整的要路徑 , 例如 /home/mlwmlw/www/project/index.php
%n 代表的是 RewriteCond 正規裡面符合條件的群組順序,例如上面的

RewriteCond %{REQUEST_FILENAME} ^/home/(.+)/www/(.+)/(.*)

對照到 /home/mlwmlw/www/project/index.php 的 /home/(%1)/www/(%2)/index.php 這樣 %1 , %2 就能在 Rule 裡面又拿來當規則,

$n 代表的是 RewriteRule 前半段的正規符合的群組,例如

http://mlwmlw.org/~mlwmlw/project/hello/world 會提取出 /hello/world 來比較,^(.*)$ 則是把整段都拿來 對應到 $1,

就是把參數都往 /~mlwmlw/project/index.php/$1 <- 這裡丟 變成 /~mlwmlw/project/index.php/hello/world

另外一提這裡比較特別與奇怪的用法是一開始的
RewriteCond $1 !^(index.php|images|robots.txt|assets|temp)
由於這裡根本還沒用到 RewriteRule 所以 $1 指的意思好像比較不明,
好像比較少這樣用,但是一樣是指 /hello/world 這一段,
如果有這段是採用 /index.php or /assets .. 等規則開始的話就直接跳掉了。
另外加上一個更完整的情境…與 RewriteCond and 的用法

RewriteEngine on
RewriteCond $1 !^(index.php|images|robots.txt|assets|temp)
RewriteCond %{HTTP_HOST} ^.+\.site\.com$
RewriteCond %{REQUEST_FILENAME} ^/home/(.+)/www/(.+)/(.*)
RewriteRule ^(.*)$ /%2/index.php/$1 [L]

RewriteCond $1 !^(index.php|images|robots.txt|assets|temp)
rewriteCond %{REQUEST_FILENAME} ^/home/(.+)/www/(.+)/(.*)
rewriteRule ^(.*)$ /~%1/%2/index.php/$1 [L]
  
if [^index.php,^images,^robots.txt,^temp] in url and host reg *.site.com :   
  (%1, %2, %3) = filename reg /home/(*)/www/(*)/(*) 
  $1 = url 
  redirect /%2/index.php/$1 
else if [^index.php,^images,^robots.txt,^temp] in url : 
  (%1, %2, %3) = filename reg /home/(*)/www/(*)/(*) 
  $1 = url   redirect /~%1/%2/index.php/$1

網站在 /home/mlwmlw/www/apple/ 設定好網址,
可以用 http://mlwmlw.site.com/apple 進去
也可以用 http://site.com/~mlwmlw/apple 進去