前言 大家好,我是老馬。很高興遇到你。 我們為 java 開發者實現了 java 版本的 nginx https://github.com/houbb/nginx4j 如果你想知道 servlet 如何處理的,可以參考我的另一個項目: 手寫從零實現簡易版 tomcat minicat 手寫 ngin ...
前言
大家好,我是老馬。很高興遇到你。
我們為 java 開發者實現了 java 版本的 nginx
如果你想知道 servlet 如何處理的,可以參考我的另一個項目:
手寫從零實現簡易版 tomcat minicat
手寫 nginx 系列
如果你對 nginx 原理感興趣,可以閱讀:
從零手寫實現 nginx-01-為什麼不能有 java 版本的 nginx?
從零手寫實現 nginx-03-nginx 基於 Netty 實現
從零手寫實現 nginx-04-基於 netty http 出入參優化處理
從零手寫實現 nginx-05-MIME類型(Multipurpose Internet Mail Extensions,多用途互聯網郵件擴展類型)
從零手寫實現 nginx-12-keep-alive 連接復用
NGINX 調試
通過調試二進位文件、調試日誌和核心轉儲來排除 NGINX 或 NGINX Plus 部署中的問題並追蹤錯誤。
介紹
調試幫助您在程式代碼出現問題時識別錯誤。它通常用於開發或測試第三方或實驗性模塊。
NGINX 調試功能包括調試日誌和創建核心轉儲文件以及進一步的回溯。
配置 NGINX 二進位文件進行調試
首先,您需要在 NGINX 二進位文件中啟用調試。NGINX Plus 已經為您提供了 nginx-debug 二進位文件,而 NGINX Open Source 需要重新編譯。
配置 NGINX Plus 二進位文件
從版本 8 開始,NGINX Plus 與標準二進位文件一起提供 nginx-debug 二進位文件。要在 NGINX Plus 中啟用調試,您需要從 nginx 切換到 nginx-debug 二進位文件。打開終端並運行以下命令:
service nginx stop && service nginx-debug start
完成後,在配置文件中啟用調試日誌。
編譯 NGINX Open Source 二進位文件
要在 NGINX Open Source 中啟用調試,您需要使用 configure 腳本中指定的 --with-debug 標誌重新編譯它。
要編譯支持調試的 NGINX Open Source:
- 下載並解壓 NGINX 源文件,轉到源文件所在的目錄。參見下載源代碼。
- 獲取 NGINX 配置參數列表。運行命令:
nginx -V 2>&1 | grep arguments
- 將 --with-debug 選項添加到 configure 命令列表中並運行 configure 腳本:
./configure --with-debug <其他 configure 參數>
- 編譯和安裝 NGINX:
sudo make
sudo make install
- 重新啟動 NGINX。
NGINX 和調試符號
調試符號有助於獲取用於調試的附加信息,例如函數、變數、數據結構、源文件和行號信息。
NGINX 預設使用“-g”標誌編譯,其中包含調試符號。
但是,如果在運行回溯時出現“沒有可用的符號表信息”錯誤,則表示缺少調試符號,您需要重新編譯 NGINX 並支持調試符號。
確切的編譯器標誌取決於編譯器。例如,對於 GCC 編譯器系統:
- 使用“-g”標誌包含調試符號
- 使用“-O0”標誌禁用編譯器優化,使調試器輸出更易於理解:
./configure --with-debug --with-cc-opt='-O0 -g' ...
在 NGINX 配置中啟用調試日誌
調試日誌記錄錯誤和與調試相關的任何信息,預設情況下是禁用的。要啟用它,請確保 NGINX 已編譯支持調試(參見“為調試配置 NGINX 二進位文件”),然後在 NGINX 配置文件中使用 error_log 指令的 debug 參數啟用它。調試日誌可以寫入文件、記憶體中的分配緩衝區、標準錯誤輸出或 syslog。
建議在 NGINX 配置的“main”級別上啟用調試日誌,以獲得正在進行的完整情況。
將調試日誌寫入文件
將調試日誌寫入文件可能會在高負載下降低性能。還要註意,文件可能會變得非常大,快速消耗磁碟空間。為減少負面影響,您可以配置調試日誌寫入記憶體緩衝區,或為特定 IP 地址設置調試日誌。有關詳細信息,請參閱“將調試日誌寫入記憶體”和“選定 IP 的調試日誌”。
要啟用將調試日誌寫入文件:
-
確保您的 NGINX 配置了 --with-debug 配置選項。運行命令並檢查輸出是否包含 --with-debug 行:
nginx -V 2>&1 | grep -- '--with-debug'
-
打開 NGINX 配置文件:
sudo vi /etc/nginx/nginx.conf
-
查找 error_log 指令,預設情況下位於 main 上下文中,並將日誌級別更改為 debug。如果需要,更改日誌文件的路徑:
error_log /var/log/nginx/error.log debug;
-
保存配置並退出配置文件。
將調試日誌寫入記憶體
調試日誌可以使用迴圈緩衝區寫入記憶體。優點是,在高負載下,調試級別的日誌記錄對性能影響不大。
要啟用將調試日誌寫入記憶體:
-
確保您的 NGINX 配置了 --with-debug 配置選項。運行命令並檢查輸出是否包含 --with-debug 行:
nginx -V 2>&1 | grep -- '--with-debug'
-
在 NGINX 配置文件中,使用在 main 上下文中指定的 error_log 指令啟用調試日誌的記憶體緩衝區:
error_log memory:32m debug; ... http { ... }
從記憶體中提取調試日誌
可以使用在 GDB 調試器中執行的腳本從記憶體緩衝區中提取日誌。
要從記憶體中提取調試日誌:
-
獲取 NGINX 工作進程的 PID:
ps axu |grep nginx
-
啟動 GDB 調試器:
sudo gdb -p <在上一步中獲得的 nginx PID>
-
複製腳本,將其粘貼到 GDB 中並按“Enter”。該腳本將在當前目錄中的 debug_log.txt 文件中保存日誌:
set $log = ngx_cycle->log while $log->writer != ngx_log_memory_writer set $log = $log->next end set $buf = (ngx_log_memory_buf_t *) $log->wdata dump binary memory debug_log.txt $buf->start $buf->end
-
通過按下 CTRL+D 退出 GDB。
-
打開位於當前目錄中的“debug_log.txt”文件:
sudo less debug_log.txt
選定 IP 的調試日誌
可以為特定 IP 地址或 IP 地址範圍啟用調試日誌。在生產環境中,記錄特定 IP 可能很有用,因為它不會對性能產生負面影響。IP 地址在事件塊中的 debug_connection 指令中指定;該指令可以定義多次:
error_log /path/to/log;
...
events {
debug_connection 192.168.1.1;
debug_connection 192.168.10.0/24;
}
每個虛擬主機的調試日誌
通常,error_log 指令在主上下文中指定,因此適用於所有其他上下文,包括伺服器和位置。
但是,如果在特定伺服器或位置塊內指定了另一個 error_log 指令,則會覆蓋全局設置,並且這樣的 error_log 指令將設置自己的日誌文件路徑和調試日誌級別。
要為特定虛擬主機設置調試日誌,請在特定伺服器塊內添加 error_log 指令,並設置新的日誌文件路徑和調試日誌級別:
error_log /path1/to/log debug;
...
http {
...
server {
error_log /path2/to/log debug;
...
}
}
要禁用特定虛擬主機的調試日誌,請在特定伺服器塊內指定 error_log 指令,並僅指定日誌文件路徑:
error_log /path/to/log debug;
...
http {
...
server {
error_log /path/to/log;
...
}
}
啟用核心轉儲
核心轉儲文件可以幫助識別和修複導致 NGINX 崩潰的問題。核心轉儲文件可能包含諸如密碼和私鑰之類的敏感信息,因此請確保對它們進行安全處理。
為了創建核心轉儲文件,必須在操作系統和 NGINX 配置文件中都啟用它們。
在操作系統中啟用核心轉儲
在操作系統中執行以下步驟:
-
指定一個工作目錄,用於保存核心轉儲文件,例如“/tmp/cores”:
mkdir /tmp/cores
-
確保該目錄可由 NGINX 工作進程寫入:
sudo chown root:root /tmp/cores sudo chmod 1777 /tmp/cores
-
禁用核心轉儲文件的最大大小限制:
ulimit -c unlimited
如果操作以“Cannot modify limit: operation not permitted”結束,請運行以下命令:
sudo sh -c "ulimit -c unlimited && exec su $LOGNAME"
-
為 setuid 和 setgid 進程啟用核心轉儲。
- 對於 CentOS 7.0、Debian 8.2、Ubuntu 14.04,請運行以下命令:
echo "/tmp/cores/core.%e.%p" | sudo tee /proc/sys/kernel/core_pattern sudo sysctl -w fs.suid_dumpable=2 sysctl -p
- 對於 FreeBSD,請運行以下命令:
sudo sysctl kern.sugid_coredump=1 sudo sysctl kern.corefile=/tmp/cores/%N.core.%P
在 NGINX 配置中啟用核心轉儲
要在 NGINX 配置文件中啟用核心轉儲:
-
打開 NGINX 配置文件:
sudo vi /usr/local/etc/nginx/nginx.conf
-
使用 working_directory 指令定義一個目錄,該目錄將保存核心轉儲文件。該指令在主配置級別上指定:
working_directory /tmp/cores/;
-
確保該目錄存在,並由 NGINX 工作進程寫入。在終端中運行以下命令:
sudo chown root:root /tmp/cores sudo chmod 1777 /tmp/cores
-
使用 worker_rlimit_core 指令指定核心轉儲文件的最大可能大小。該指令也在主配置級別上指定。如果核心轉儲文件大小超過該值,將不會創建核心轉儲文件。
worker_rlimit_core 500M;
示例:
worker_processes auto; error_log /var/log/nginx/error.log debug; working_directory /tmp/cores/; worker_rlimit_core 500M; events { ... } http { ... }
通過這些設置,核心轉儲文件將在“/tmp/cores/”目錄中創建,只有當其大小不超過 500 兆位元組時才會創建。
從核心轉儲文件中獲取回溯信息
回溯提供了關於程式崩潰時出錯的信息。
要從核心轉儲文件中獲取回溯信息:
-
使用 GDB 調試器打開核心轉儲文件,命令格式為:
sudo gdb <nginx_executable_path> <coredump_file_path>
-
輸入“backtrace”命令以從崩潰時的堆棧中獲取堆棧跟蹤信息:
(gdb) backtrace
如果“backtrace”命令返回“沒有可用的符號表信息”消息,則需要重新編譯 NGINX 二進位文件以包含調試符號。請參閱NGINX和調試符號。
從運行中的進程中轉儲NGINX配置
您可以從主進程記憶體中提取當前的NGINX配置。當您需要:
- 驗證已載入的配置
- 如果磁碟上的版本被意外刪除或覆蓋,恢復以前的配置
配置轉儲可以通過提供一個GDB腳本來獲得,只要您的NGINX具有調試支持。
確保您的NGINX已經構建了調試支持(在configure參數列表中使用--with-debug選項)。運行命令並檢查輸出是否包含--with-debug行:
nginx -V 2>&1 | grep -- '--with-debug'
獲取NGINX工作進程的PID:
ps axu | grep nginx
啟動GDB調試器:
sudo gdb -p <在上一步中獲取的NGINX PID>
複製並粘貼腳本到GDB中,然後按“Enter”鍵。該腳本將配置保存在當前目錄中的nginx_conf.txt文件中:
set $cd = ngx_cycle->config_dump
set $nelts = $cd.nelts
set $elts = (ngx_conf_dump_t*)($cd.elts)
while ($nelts-- > 0)
set $name = $elts[$nelts]->name.data
printf "Dumping %s to nginx_conf.txt\n", $name
append memory nginx_conf.txt \
$elts[$nelts]->buffer.start $elts[$nelts]->buffer.end
end
按下CTRL+D退出GDB。
打開位於當前目錄中的nginx_conf.txt文件:
sudo vi nginx_conf.txt
在請求幫助時
在請求調試幫助時,請提供以下信息:
- NGINX版本、編譯器版本和配置參數。運行命令:
nginx -V
-
當前完整的NGINX配置。請參閱從運行進程中轉儲NGINX配置
-
調試日誌。請參閱在NGINX配置中啟用調試日誌
-
獲取的回溯。請參閱啟用核心轉儲,獲取回溯信息。
參考資料
https://docs.nginx.com/nginx/admin-guide/monitoring/debugging/