<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    Nginx 配置指令的執行順序(七)

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    來看一個 ngx_static 模塊服務磁盤文件的例子。我們使用下面這個配置片段:

        location / {
            root /var/www/;
        }

    同時在本機的 /var/www/ 目錄下創建兩個文件,一個文件叫做 index.html,內容是一行文本 this is my home;另一個文件叫做 hello.html,內容是一行文本 hello world. 同時注意這兩個文件的權限設置,確保它們都對運行 Nginx worker 進程的系統帳戶可讀。

     

        現在來通過 HTTP 協議請求一下這兩個文件所對應的 URI:

        $ curl 'http://localhost:8080/index.html'
        this is my home
     
        $ curl 'http://localhost:8080/hello.html'
        hello world

    我們看到,先前創建的那兩個磁盤文件的內容被分別輸出了。

     

        不妨來分析一下這里發生的事情:location / 中沒有使用運行在 content 階段的模塊指令,于是也就沒有模塊注冊這個 location 的“內容處理程序”,處理權便自動落到了在 content 階段“墊底”的那 3 個靜態資源服務模塊。首先運行的 ngx_index 和 ngx_autoindex 模塊先后看到當前請求的 URI,/index.html 和/hello.html,并不以 / 結尾,于是直接棄權,將處理權轉給了最后運行的 ngx_static 模塊。ngx_static 模塊根據 root 指令指定的“文檔根目錄”(document root),分別將請求 URI /index.html 和 /hello.html映射為文件系統路徑 /var/www/index.html 和 /var/www/hello.html,在確認這兩個文件存在后,將它們的內容分別作為響應體輸出,并自動設置 Content-TypeContent-Length 以及 Last-Modified 等響應頭。

     

        為了確認 ngx_static 模塊確實運行了,可以啟用 (一) 中介紹過的 Nginx “調試日志”,然后再次請求 /index.html 這個接口。此時,在 Nginx 錯誤日志文件中可以看到類似下面這一行的調試信息:

        [debug] 3033#0: *1 http static fd: 8

    這一行信息便是 ngx_static 模塊生成的,其含義是“正在輸出的靜態文件的描述符是數字 8”。當然,具體的文件描述符編號會經常發生變化,這里只是我機器的一次典型輸出。值得一提的是,能生成這一行調試信息的還有標準模塊 ngx_gzip_static ,但它默認是不啟用的,后面會專門介紹到這個模塊。

     

        注意上面這個例子中使用的 root 配置指令只起到了聲明“文檔根目錄”的作用,并不是它開啟了ngx_static 模塊。ngx_static 模塊總是處于開啟狀態,但是否輪得到它運行就要看 content 階段先于它運行的那些模塊是否“棄權”了。為了進一步確認這一點,來看下面這個空白 location 的定義:

        location / {
        }

    因為沒有配置 root 指令,所以在訪問這個接口時,Nginx 會自動計算出一個缺省的“文檔根目錄”。該缺省值是取所謂的“配置前綴”(configure prefix)路徑下的 html/ 子目錄。舉一個例子,假設“配置前綴”是/foo/bah/,則缺省的“文檔根目錄”便是 /foo/bar/html/.

     

        那么“配置前綴”是由什么來決定的呢?默認情況下,就是 Nginx 安裝時的根目錄(或者說 Nginx 構造時傳遞給 ./configure 腳本的 --prefix 選項的路徑值)。如果 Nginx 安裝到了 /usr/local/nginx/ 下,則“配置前綴”便是 /usr/local/nginx/,同時默認的“文檔根目錄”便是 /usr/local/nginx/html/. 不過,我們也可以在啟動 Nginx 的時候,通過 --prefix 命令行選項臨時指定自己的“配置前綴”路徑。假設我們啟動 Nginx 時使用的命令是

        nginx -p /home/agentzh/test/

    則對于該服務器實例,其“配置前綴”便是 /home/agentzh/test/,而默認的“文檔根目錄”便是/home/agentzh/test/html/. “配置前綴”不僅會決定默認的“文檔根目錄”,還決定著 Nginx 配置文件中許多相對路徑值如何解釋為絕對路徑,后面我們還會看到許多需要引用到“配置前綴”的例子。

     

        獲取當前“文檔根目錄”的路徑有一個非常簡便的方法,那就是請求一個肯定不存在的文件所對應的資源名,例如:

        $ curl 'http://localhost:8080/blah-blah.txt'
        <html>
        <head><title>404 Not Found</title></head>
        <body bgcolor="white">
        <center><h1>404 Not Found</h1></center>
        <hr><center>nginx</center>
        </body>
        </html>

    我們會很自然地得到 404 錯誤頁。此時再看 Nginx 錯誤日志文件,應該會看到類似下面這一行錯誤消息:

        [error] 9364#0: *1 open() "/home/agentzh/test/html/blah-blah.txt" failed (2: No such file or directory)

    這條錯誤消息是 ngx_static 模塊打印出來的,因為它并不能在文件系統的對應路徑上找到名為 blah-blah.txt的文件。因為這條錯誤信息中包含有 ngx_static 試圖打開的文件的絕對路徑,所以從這個路徑不難看出,當前的“文檔根目錄”是 /home/agentzh/test/html/.

     

        很多初學者會想當然地把 404 錯誤理解為某個 location 不存在,其實上面這個例子表明,即使 location存在并成功匹配,也是可能返回 404 錯誤頁的。因為決定著 404 錯誤頁的是抽象的“資源”是否存在,而非某個具體的 location 是否存在。

     

        初學者常犯的一個錯誤是忘記配置 content 階段的模塊指令,而他們自己其實并不期望使用 content 階段缺省運行的靜態資源服務,例如:

        location /auth {
            access_by_lua '
                -- a lot of Lua code omitted here...
            ';
        }

    顯然,這個 /auth 接口只定義了 access 階段的配置指令,即 access_by_lua,并未定義任何 content 階段的配置指令。于是當我們請求 /auth 接口時,在 access 階段的 Lua 代碼會如期執行,然后 content 階段的那些靜態文件服務會緊接著自動發生作用,直至 ngx_static 模塊去文件系統上找名為 auth 的文件。而經常地,404 錯誤頁會拋出,除非運氣太好,在對應路徑上確實存在一個叫做 auth 的文件。所以,一條經驗是,當遇到意外的 404 錯誤并且又不涉及靜態文件服務時,應當首先檢查是否在對應的 location 配置塊中恰當地配置了 content 階段的模塊指令,例如 content_by_lua、 echo 以及 proxy_pass 之類。當然,Nginx 的error.log 文件一般總是會提供各種意外問題的答案,例如對于上面這個例子,我的 error.log 中有下面這條錯誤信息:

        [error] 9364#0: *1 open() "/home/agentzh/test/html/auth" failed (2: No such file or directory)
    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全