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。