Nginx 日誌系統由 error_log (錯誤/診斷) 與 access_log (訪問/審計) 兩大核心指令構建,底層涉及多模組協作、文件描述符緩存、紅黑樹管理等機制。本文從源碼視角剖析兩指令註冊差異、作用域繼承、變量路徑處理、緩存策略,助力運維與二次開發。
| 模組 | 指令上下文 | 回調函數 | 存儲位置 | 記錄範圍 |
|---|---|---|---|---|
| ngx_errlog_module (core) | main | ngx_error_log | cycle->new_log | 進程啟動、事件、核心錯誤、非 HTTP 階段 |
| ngx_http_core_module | http, server, location | ngx_http_core_error_log | clcf->error_log (ngx_http_core_loc_conf_t) | HTTP 請求處理階段錯誤 |
設計意圖: Core 模組優先註冊,捕獲 HTTP 模組載入前的早期錯誤;HTTP 模組提供分級配置 (server/location 覆蓋),實現精細化錯誤路由。兩者互不耦合,各司其職。
// ngx_http_core_merge_loc_conf 片段
if (conf->error_log == NULL) {
if (prev->error_log) {
conf->error_log = prev->error_log; // 繼承父級
} else {
conf->error_log = &cf->cycle->new_log; // 回退 core error_log
}
}
若 http {} 未顯式設定 error_log,所有 server/location 自動繼承 main 級 core error_log,保證無遺漏。
屬於 NGX_HTTP_LOG_PHASE (最後階段),請求處理完畢前執行,記錄完整訪問資訊。
# 常量路徑 → 緩存 fd 於 cycle->open_files
access_log logs/access.log main;
# 變量路徑 → 動態解析,走 script 機制
access_log logs/'$remote_addr'-access.log main;
cycle->open_files 鏈表 (去重),寫入調用 ngx_write_fd,極高效。ngx_http_log_script_write,需管理 fd 緩存,避免海量 fd 耗盡系統上限。
open_log_file_cache max=1000 inactive=60s min_uses=2 valid=10s;
rbtree) + 隊列 (queue) 管理緩存項 (ngx_cached_open_file_t)。inactive 內未達 min_uses → 淘汰;達標 → 進入活躍隊列。valid 間隔檢查是否超時。cleanup 機制自動關閉未緩存 fd。| 指令 | 模組 | 管理範圍 | 適用場景 |
|---|---|---|---|
| open_log_file_cache | ngx_http_log_module | access_log 變量路徑 fd | 按 IP/域名/參數切分日誌 |
| open_file_cache | ngx_http_core_module | 靜態文件、索引、try_files、gzip、mp4/flv 等 | 靜態資源加速、元數據緩存 |
兩者底層均調用 ngx_open_file_cache_init 初始化紅黑樹,但管理對象完全隔離。
warn,server 覆蓋 error,location 關鍵業務設 debug (臨時)。open_log_file_cache,max=5000 inactive=30s,避免單進程 fd 爆滿。logrotate + nginx -s reopen (發送 NGX_REOPEN_SIGNAL),Nginx 重新打開 fd,舊檔交由 logrotate 壓縮備份。rm access.log 不會生成新檔,fd 指向已刪除 inode,日誌丟失。正確做法:mv access.log access.log.old && nginx -s reopen。access_log off; 減少 I/O。深入理解 Nginx 日誌模組架構,能精準排查「日誌不寫入、fd 洩漏、磁碟爆滿」等疑難雜症,亦為高性能日誌管道設計奠基。