nginx的日誌包括錯誤日誌和訪問日誌,分別使用不一樣的指令來定義其輸出位置和相應的級別。 下面介紹其各自的用途。html
nginx提供了error_log
指令來指定錯誤日誌的輸出文件和級別。 指令定義以下:linux
Syntax: error_log file [level]; Default: error_log logs/error.log error; Context: main, http, mail, stream, server, location
error_log的第一個參數,定義了輸出的文件名。另外還可使用一些特殊的文件,可選值有:nginx
error_log syslog:server=192.168.1.1 debug;
error_log memory:32m debug;
使用gdb的指令來查看內存中日誌的方法,以下web
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
error_log指令的第二個參數,定義了輸出日誌的級別,默認值爲error
。官方文檔對級別的定義比較簡單,以下說明來自於文章Configuring the Nginx Error Log and Access Log算法
debug – Useful debugging information to help determine where the problem lies. info – Informational messages that aren’t necessary to read but may be good to know. notice – Something normal happened that is worth noting. warn – Something unexpected happened, however is not a cause for concern. error – Something was unsuccessful. crit – There are problems that need to be critically addressed. alert – Prompt action is required. emerg – The system is in an unusable state and requires immediate attention.
從上到下,嚴重程度逐漸變高。好比使用以下指令指定級別爲error
時,json
error_log logs/error.log error;
級別爲error、crit、alert、emerg的日誌將輸出到文件logs/error.log中。須要注意的是,在構建nginx時須要指定選項--with-debug,不然沒法使用error_log來使debug生效,參見A debugging log。
訪問日誌
nginx提供了access_log指令來實現訪問日誌的輸出文件和級別。官方文檔中給出的配置樣例
瀏覽器
log_format compression '$remote_addr - $remote_user [$time_local] ' '"$request" $status $bytes_sent ' '"$http_referer" "$http_user_agent" "$gzip_ratio"'; access_log /spool/logs/nginx-access.log compression buffer=32k;
關鍵指令有log_format
和access_log
。緩存
指令定義以下:服務器
Syntax: log_format name [escape=default|json] string ...; Default: log_format combined "..."; Context: http
使用log_format
能夠在配置文件中定義多個輸出格式,知足不一樣場景下的access_log
指令輸出日誌的需求。以下是log_format
指令提供的日誌字段和說明,來自nginx日誌配置app
$remote_addr和$http_x_forwarded_for,記錄客戶端IP地址。 $remote_user,記錄客戶端用戶名稱。 $request,記錄請求的URL和HTTP協議。 $status,記錄響應的狀態碼 $body_bytes_sent,發送給客戶端的字節數,不包括響應頭的大小;該變量與Apache模塊mod_log_config裏的「%B」參數兼容。 $bytes_sent,發送給客戶端的總字節數。 $connection,鏈接的序列號。 $connection_requests,當前經過一個鏈接得到的請求數量。 $msec,日誌寫入時間。單位爲秒,精度是毫秒。 $pipe,若是請求是經過HTTP流水線(pipelined)發送,pipe值爲「p」,不然爲「.」。 $http_referer,記錄從哪一個頁面連接訪問過來的。 $http_user_agent,記錄客戶端瀏覽器相關信息。 $request_length,請求的長度(包括請求行,請求頭和請求正文)。 $request_time,請求處理時間,單位爲秒,精度毫秒。從讀入客戶端的第一個字節開始,直到把最後一個字符發送給客戶端後進行日誌寫入爲止。 $time_iso8601,ISO8601標準格式下的本地時間。 $time_local,通用日誌格式下的本地時間。
定位性能問題時比較有用的幾個字段,以下
access_log
指令定義以下
Syntax: access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]]; access_log off; Default: access_log logs/access.log combined; Context: http, server, location, if in location, limit_except
指令的參數說明:
配置樣例
# 關閉日誌。 access_log off; # 日誌記錄至logs/access.log中,格式爲combined。 access_log logs/access.log combined; # 日誌記錄至logs/access.log,內存中緩存至多64k日誌,每隔10s將日誌刷新到文件中。 access_log logs/access.log buffer=64k flush=10s;
指令定義以下
Syntax: open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time]; open_log_file_cache off; Default: open_log_file_cache off; Context: http, server, location
指令的參數說明:
配置樣例
open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;
指令定義以下
Syntax: log_not_found on | off; Default: log_not_found on; Context: http, server, location
是否在error_log中記錄被訪問URL不存在的錯誤。默認值爲on
,表示記錄相關信息。
指令定義以下
Syntax: log_subrequest on | off; Default: log_subrequest off; Context: http, server, location
是否在access_log中記錄子請求的訪問日誌。默認值爲off
,表示不記錄相關信息。
指令定義以下
Syntax: rewrite_log on | off; Default: rewrite_log off; Context: http, server, location, if
用來控制nginx執行URL重寫操做的處理日誌是否寫出到文件中;在調試重寫規則時,建議開啓日誌。當啓用後,將以notice級別來記錄URL重寫操做相關的日誌。
如何管理nginx輸出的日誌
爲避免應用輸出的日誌過多、過大,致使硬盤滿而影響應用、硬件的穩定性,須要對日誌文件進行管理。而一般狀況下采起的策略有:
文件繞接,控制文件的數量,避免文件無限制生成。
按天切換,控制文件的生成規則,避免單個文件中記錄的數量過多,同時便於管理。
按大小切換,控制文件的大小,避免單個文件中記錄的數量過多,同時便於管理。
。。。
從官方文檔以及衆網友的分享看,nginx並無對日誌文件的管理提供原生的支持。但仍然能夠找到一些方法來解決nginx日誌管理的問題。
原生方法
nginx的開發者提供了一種簡單、粗暴的方式來實現日誌文件的切換。來自官網的一篇文章Log Rotation介紹了這種方法,核心腳本以下:
mv access.log access.log.0 kill -USR1 `cat master.nginx.pid` sleep 1 # do something with access.log.0 gzip access.log.0
nginx開發人員對上述方法的解釋:
The rotator should send the -USR1 signal to the master process. The master process reopens files, does chown() and chmod() to enable the worker processes to write to files, and send a notification to the worker procesess. They reopen files instantly. If the rotator sends the -HUP signal, then them master does a reconfiguration and starts a new worker processes those write to the new log files, but the old shuting down worker processes still uses the old log files.
When master process receives -USR1 it repopens all logs, does chown() and chmod() (to allow unpriviliged worker processes to reopen them), and notifies workers about reopening. Then the workers reopens its logs too. So the old logs are available to gzip right away - you will not lose any line.
在網上簡單搜索,發現使用logrotate也是一個不錯的選擇,網上能夠找到至關數量的介紹文章。此處再也不贅述使用方法和原理。
以下是截取自純手工玩轉 Nginx 日誌的一些例子。給定access_log
日誌的格式以下
log_format myformat '$remote_addr^A$http_x_forwarded_for^A$host^A$time_local^A$status^A' '$request_time^A$request_length^A$bytes_sent^A$http_referer^A$request^A$http_user_agent';
利用awk命令,能夠快速獲得以下的數據。
cat access.log | awk -F '^A' '{print $10}' | sort | uniq -c
cat access.log | awk -F '^A' '{if($5 == 500) print $0}'
cat access.log | awk -F '^A' '{if($5 == 500) print $0}' | wc -l
cat access.log | awk -F '^A' '{if($5 == 500) print $0}' | grep '09:00' | wc-l
tail -f access.log | awk -F '^A' '{if($6>1) print $0}'
tail -f access.log | awk -F '^A' '{if($6>1) print $3"|"$4}'
cat access.log | awk -F '^A' '{if($5==502) print $11}' | sort | uniq -c
cat access.log | awk -F '^A' '{if($5==200 && $8 < 100) print $3"|"$4"|"$11"|"$6}'
tail -f access.log | cat -e 或者 tail -f access.log | tr '^A' '|'
AWK的深刻使用方法,請參考The GNU Awk User’s Guide。