Nginx 日志管理
# 43.Nginx 日志管理
日志,是排查问题的基本手段。Nginx 对于日志也提供了很多的配置。
# 默认配置
在 Nginx 中,日志分为:访问日志 access.log ,错误日志 error.log。
日志路径默认是在 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