Nginx日志管理
# 43.Nginx日志管理
日志,是排查问题的基本手段。Nginx对于日志也提供了很多的配置。
# 默认配置
在Nginx中,日志分为:访问日志access.log ,错误日志error.log,日志路径默认是在Nginx安装路径的logs目录下。例如我的Nginx安装位置为/opt/nginx/,则日志路径为/opt/nginx/logs
ll /opt/nginx/logs
-rw-r--r--. 1 root root 13658 3月 29 08:07 access.log
-rw-r--r--. 1 root root 4428 3月 29 07:12 error.log
2
3
# access.log
在Nginx中,可以配置访问日志的路径,日志的级别和日志的格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
2
3
4
5
第1~3行配置了日志的格式,并将该格式命名为main,然后是日志的格式:$remote_addr
表示请求IP地址,$remote_user
表示请求的用户,$time_local
表示时间戳..... 需要注意,log_format配置必须放在http内
然后第5行配置了访问日志的路径,这里是相对路径(相对Nginx的安装位置),然后指定了日志格式为main。
因此,我们的日志看起来是这样的:
192.168.2.245 - - [29/Mar/2023:08:07:44 +0800] "GET / HTTP/1.1" 200 626 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"
第一个字段是请求的IP地址,然后是用户(为空,因此是空),然后是请求的时间戳(2023年8点7分),然后是请求的类型(Get)..
就不一一解读了,format有很多可选项如下表:
参数 | 说明 | 示例 |
---|---|---|
$remote_addr | 客户端地址 | 211.28.65.253 |
$remote_user | 客户端用户名称,用于记录浏览者进行身份验证时提供的名字,如登录百度的用户名peterjxl,如果没有登录就是空白 | |
$time_local | 访问时间和时区 | 18/Jul/2012:17:00:01 +0800 |
$request | 请求的URI和HTTP协议,这是整个PV日志记录中最有用的信息,记录服务器收到一个什么样的请求,请求的是什么 | "GET /article-10000.html HTTP/1.1" |
$http_host | 请求地址,即浏览器中你输入的地址(IP或域名) | 192.168.100.100 |
$status | HTTP请求返回的状态码 | 200 |
$upstream_status | upstream状态 | 200 |
$body_bytes_sent | 发送给客户端文件内容大小,可以将日志每条记录中的这个值累加起来以粗略估计服务器吞吐量 | 1547 |
$http_referer | url跳转来源 | https://www.baidu.com/ (opens new window) |
$http_user_agent | 用户终端浏览器等信息 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SV1; GTB7.0; .NET4.0C; |
$ssl_protocol | SSL协议版本 | TLSv1 |
$ssl_cipher | 交换数据中的算法 | RC4-SHA |
$upstream_addr | 后台upstream的地址,即真正提供服务的主机地址 | 10.10.10.100:80 |
$request_time | 整个请求的总时间 | 0.205 |
$upstream_response_time | 请求过程中,upstream响应时间 | 0.002 |
# error.log
nginx的错误日志配置
- 错误日志级别分为: debug,info,notice,warn,error,crit。crit 记录的日志最少,debug记录的日志最多。请根据实际情况选择配置日志级别, 配置级别低了,太多信息没用;级别太高不容易排查问题;建议保持默认crit。
- 错误日志路径:直接在error_log 后面写上日志路径即可
- 错误日志可以配置在:main、http、 server、location
- 格式不支持自定义
因此,一个错误日志可以这样配的:
error_log /opt/nginx/logs/error.log crit;
常见的错误日志如下:
错误信息 | 错误说明 |
---|---|
“upstream prematurely(过早的) closed connection” | 请求uri的时候出现的异常,是由于upstream还未返回应答给用户时用户断掉连接造成的,对系统没有影响,可以忽略 |
“recv() failed (104: Connection reset by peer)” | (1)服务器的并发连接数超过了其承载量,服务器会将其中一些连接Down掉; (2)客户关掉了浏览器,而服务器还在给客户端发送数据; (3)浏览器端按了Stop |
“(111: Connection refused) while connecting to upstream” | 用户在连接时,若遇到后端upstream挂掉或者不通,会收到该错误 |
“(111: Connection refused) while reading response header from upstream” | 用户在连接成功后读取数据时,若遇到后端upstream挂掉或者不通,会收到该错误 |
“(111: Connection refused) while sending request to upstream” | Nginx和upstream连接成功后发送数据时,若遇到后端upstream挂掉或者不通,会收到该错误 |
“(110: Connection timed out) while connecting to upstream” | nginx连接后面的upstream时超时 |
“(110: Connection timed out) while reading upstream” | nginx读取来自upstream的响应时超时 |
“(110: Connection timed out) while reading response header from upstream” | nginx读取来自upstream的响应头时超时 |
“(110: Connection timed out) while reading upstream” | nginx读取来自upstream的响应时超时 |
“(104: Connection reset by peer) while connecting to upstream” | upstream发送了RST,将连接重置 |
“upstream sent invalid header while reading response header from upstream” | upstream发送的响应头无效 |
“upstream sent no valid HTTP/1.0 header while reading response header from upstream” | upstream发送的响应头无效 |
“client intended to send too large body” | 用于设置允许接受的客户端请求内容的最大值,默认值是1M,client发送的body超过了设置值 |
“reopening logs” | 用户发送kill -USR1命令 |
“gracefully shutting down”, | 用户发送kill -WINCH命令 |
“no servers are inside upstream” | upstream下未配置server |
“no live upstreams while connecting to upstream” | upstream下的server全都挂了 |
“SSL_do_handshake() failed” | SSL握手失败 |
“SSL_write() failed (SSL:) while sending to client” | |
“(13: Permission denied) while reading upstream” | |
“(98: Address already in use) while connecting to upstream” | |
“(99: Cannot assign requested address) while connecting to upstream” | |
“ngx_slab_alloc() failed: no memory in SSL session shared cache” | ssl_session_cache大小不够等原因造成 |
“could not add new SSL session to the session cache while SSL handshaking” | ssl_session_cache大小不够等原因造成 |
“send() failed (111: Connection refused)” |
# 关闭错误日志
使用error_log off 或者将注释掉错误日志的配置,错误日志依旧还是会被记录的。如果需要彻底关闭,需要扔到黑洞当中才可以:
error_log /dev/null;
当然,一般情况下不建议关闭错误日志
# 日志分割
新版本Nginx支持自动切割并压缩日志,日志文件名如下:
access.log
access.log.1
access.log.2.gz
access.log.3.gz
error.log
error.log.1
error.log.2.gz
error.log.3.gz
2
3
4
5
6
7
8
默认是每天都会产生一个.gz文件。如果还不能满足需求,可以用shell脚本+crontab处理日志。
例如,压缩2天前的日志,并删除压缩后的文件,假设脚本名字为autoTarNginxLogs.sh:
nowdate_2="`date +%Y%m%d -d -2day`"
tar -czvf /opt/nginx/access.log${nowdate_2}.tar.gz /opt/nginx/access.log
tar -czvf /opt/nginx/error.log${nowdate_2}.tar.gz /opt/nginx/error.log
echo '' > /opt/nginx/access.log
echo '' > /opt/nginx/error.log
2
3
4
5
删除日志,假设脚本名字为autoClearNginxLogs.sh:
find /opt/nginx/ -type f -mtime +90 -name "*.tar.gz" -exec rm -f {} \;
配置crontab:例如每天凌晨执行一次清理,并将清理的过程追加到日志里(2表示错误输出,2>&1 表示将错误输出重定向到和标准输出一样)
0 1 * * * sh sh /opt/nginx/autoTarNginxLogs.sh 1>>/opt/nginx/autoTarNginxLogs.log 2>&1
0 1 * * * sh sh /opt/nginx/autoClearNginxLogs.sh 1>>/opt/nginx/autoClearNginxLogs.log 2>&1
2