access_log
access_log用来记录客户端请求访问日志,可以出现在http,server,location,if块中。语法如下:
access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
-
path用来指定日志存放路径,这个是必须参数,其它剩下的是可选参数。
-
format:是日志格式,日志格式可以使用log_format来定义,默认使用combined,是nginx内置的一种日志格式。
-
buffer=size:定义缓冲区大小,用于一次性写入日志的数据量,默认为 64k。
-
gzip[=level]:可选参数,表示是否启用 gzip 压缩日志文件,level 表示压缩级别,0 表示不压缩,1-9 表示压缩级别,默认为 1。
如果开启gzip压缩,nginx构建时候必须with zlib库。
-
flush=time:定义日志写入磁盘的时间间隔,单位为秒,默认为 1s。
access_log /var/log/nginx/log.gz combined gzip flush=5s;
如上配置开启gzip压缩,日志以gzip压缩方式进行日志记录。
-
if=condition:可选参数,表示只有符合条件的请求才会被记录到日志中,condition 是一个表达式,可以使用 nginx 变量和运算符。
map $status $loggable {~^[23] 0;default 1; }access_log /path/to/access.log combined if=$loggable;
上面定义一个$status状态码的map映射。以2和3开头的状态码返回0不记录日志,默认其它状态码返回1 if条件成立记录日志。
if条件用起来看着比较麻烦,其实还不如直接使用if指令来判断
if ($request_method = POST){access_log off; } if ($request_method = GET) {access_log on;access_log /var/log/nginx/log.log; }if ($request_uri ~* "/private/") {access_log /var/log/nginx/private_access.log main; }
access_log默认格式是:
access_log logs/access.log combined;
如下配置一个access_log
location /log {access_log /var/log/nginx/log.log;return 200;
}
记录的日志格式如下:
192.168.1.111 - - [26/Mar/2024:09:09:09 +0800] "GET /log HTTP/1.1" 200 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
这个日志格式是nginx内置的combined格式。如果不想使用该格式,可以使用log_format来自定义日志格式。
log_format
log_format用来设置日志记录的内容格式,语法如下:
log_format name [escape=default|json|none] string ...;
-
name用来指定日志格式的名称,access_log指令使用的format就等于这里定义的名称。
-
escape用来设置特殊字符转义,默认值default特殊字符会被转义,
default:默认值,特殊字符会被转义
json:会对特殊字符进行JSON编码,以确保日志内容符合JSON格式要求。
none:不会对特殊字符进行转义。这样可以在日志中直接输出原始字符,不进行任何处理。
-
string:用来指定日志记录的内容,可以使用变量。变量有两部分,一部分是基本内置变量,在location和rewrite文章中有介绍。另一部分是只有在日志记录时可以使用的变量。
像nginx内置的combined日志格式定义如下:
log_format combined '$remote_addr - $remote_user [$time_local] ''"$request" $status $body_bytes_sent ''"$http_referer" "$http_user_agent"';
常用的内置变量:
$remote_addr:客户端的IP地址
$host:客户端请求中的主机头字段值,请求服务器端host,可以是域名或ip
$port:请求主机服务端口
$request_uri:请求的路径
$http_user_agent:客户端的 User-Agent 字符串。
$http_referer:referer头信息
日志记录特有的变量:
$bytes_sent:响应的字节数
$request_length:请求的长度
$request_time:请求处理时间,单位秒
$time_local:本地时间带时区
$status:返回的http状态码
$http_x_forwarded_for:客户端的原始IP,再有代理时候取客户端真实IP
$upstream_response_time:上游服务器响应时间,用于记录反向代理时的响应时间。反省代理时使用
$upstream_connect_time:与上游服务器建立连接消耗时间
upstream参数都是反向代理时与上游服务器连接参数。
如下自定义一个log format
log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for" "$request_time"';access_log /var/log/nginx/access.log main;
log_format只能出现在http块下,是一个全局定义。
error_log
error_log指令用来记录nginx的错误日志,语法
error_log file [level]
如果不显示设置,默认格式是
error_log logs/error.log error;
error_log可以出现在http,server和location块中。
日志级别从低到高有debug
, info
, notice
, warn
, error
, crit
, alert
, or emerg
这些级别可配置。
像一般的404,500错误都会记录在错误日志中,日志级别默认error就差不多了,没必要设置的太低,除非需要详细信息来进行调试。如果要使用debug级别,nginx在安装时候需要设置–with-debug。
日志切割归档
nginx没有官方的日志归档指令或策略。日志会一直往acces_log或error_log中一直追加。这样就会导致日志文件变的很大。
可以借助linux定时任务(crontab)来周期性的执行脚本进行日志切割。
如下脚本:
#!/bin/bash
#日志根目录
LOG_HOME=/usr/local/nginx/logs/
#备份日志后缀
LOG_PATH_BAK="$(date -d "last_minute" +%Y%m%d%H%M)"
#重命名日志文件
mv ${LOG_HOME}/host.access.log ${LOG_HOME}/access.${LOG_PATH_BAK}.log
mv ${LOG_HOME}/error.log ${LOG_HOME}/error.${LOG_PATH_BAK}.log
#Send a USR1 signal to the Nginx main process.The USR1 signal in Nginx is to reopen the log file
kill -USR1 `cat ${LOG_HOME}/nginx.pid`
最后使用kill -USR1向nginx发送信号量来告诉nginx重新打开日志文件。当然这里备份的文件还可以使用gzip来进行压缩。