0x01 前言
前几天我在配置ELK(安装配置Elastic Stack 5)的时候发现我的nginx日志并没有按照我设定的格式生成。
这并不是nginx的错,而是我没有仔细查看nginx的技术文档。我在这里做个记录。
0x02 错误
以下是我的日志格式:
log_format main '$remote_addr - $remote_user [$time_local] "$request" $http_host ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" ' '$upstream_addr $upstream_status $upstream_cache_status "$upstream_http_content_type" $upstream_response_time > $request_time';
它生成的日志是这样的:
10.1.1.66 - - [22/Nov/2016:12:26:14 +0800] "GET /bundles/src/ui/public/styles/fonts/open_sans/open_sans_v13_latin_700italic.woff2 HTTP/1.1" kibana.t.com 304 0 "http://kibana.t.com/bundles/commons.style.css?v=14458" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.87 Safari/537.36" "-" 127.0.0.1:5601 304 - "application/font-woff2" 0.004 > 0.004
然而我我实际收到的日志却是以下这样的:
113.87.241.226 - - [21/May/2016:02:44:16 +0600] "GET /s/oswald/v11/l1cOQ90roY9yC7voEhngDLO3LdcAZYWl9Si6vvxL-qU.woff HTTP/2.0" 200 16537 "https://terence.org.cn/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/601.5.17 (KHTML, like Gecko) Version/9.1 Safari/601.5.17"
上面这个日志的格式很明显和nginx默认的日志combined格式一致:
log_format combined '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"';
那么问题来了,为什么我定义了日志的格式却没有生成正确的日志,而是nginx默认的格式?
0x03 解决
在翻查nginx log module的说明文档后我找到了答案:
原因很简单,我的配置文件仅配置了日志存放的路径,但却少了指定的日志格式。我一直使用类似以下的配置信息:
access_log /var/log/nginx/access.log
在nginx log module的说明文档中有一句:
If the format is not specified then the predefined “combined” format is used.
如果未指定具体的格式,那么默认的combined将会被采用。那么问题来了,要怎样指定格式?
查看nginx log语法后发现:
Syntax: log_format name string ...; Default: log_format combined "..."; Context: http
log_format后面紧跟着的就是格式名称,那么要将这个名词放到哪里才能生成正确的日志?
再次翻查语法后发现:
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 path后面附上format,类似下面:
access_log /var/log/nginx/access.log main;
最后的main就是我定义的日志格式名称。如果没有为access_log定义日志格式名称,那么会使用默认的combined格式。
0x04 结语
以前完全没有查看日志的习惯,日志也越来越大。要不是ELK这个非常棒的开源软件,我也没有发现我在nginx日志的配置上出现了错误。