Nginx 日志记录post数据,并使用goaccess进行日志分析

时间:2023-12-22 22:39:26

nginx日志默认不会记录post数据

在nginx配置文件的http节

log_format 日志格式标识 [escape=json] 日志格式

比如:日志格式标识设置为main,添加escape=json以便中文正确显示(注意,escape=json 需要 nginx 1.11.8 以上版本才支持),记录post和cookie的请求的相信信息

log_format main escape=json '$remote_addr [$time_local] "$request" $status $bytes_sent "$http_referer" "$http_user_agent" "$http_cookie" "$request_body"';

其中:

$time_local 格式化的时间
$request 请求地址
$status 响应码
$body_bytes_sent 传送页面的字节数
$http_referer 来源地址
$http_user_agent 客户端UA
$document_root 当前文件的目录绝对地址,比如:/var/www/html
$fastcgi_script_name 当前url的绝对地址,比如:/info.php
$request_filename 当前请求文件的绝对物理地址,基于root和alias指令,比如:/var/www/html/info.php
$http_cookie cookie信息,这个也很重要,如果在cookie中带上了用户的标识,比较方便调试

然后在每个虚拟站点的server节

access_log  日志报错路径 日志格式标识;

比如日志保存到/data/logs/web.log,日志格式用刚才设置的main那个格式,如果要其他格式可以在刚才的http节添加多个log_format,并使用不同的日志格式标识

access_log  /data/logs/web.log main;

GoAccess日志分析

安装

yum install glib2 glib2-devel GeoIP-devel  ncurses-devel zlib zlib-develyum install gcc -y
yum -y install GeoIP-update
yum install goaccess

查看nginx的日志格式配置,用 nginx2goaccess.sh 将 nginx日志格式配置转换为goaccess可以识别的格式配置

https://raw.githubusercontent.com/stockrt/nginx2goaccess/master/nginx2goaccess.sh

sh nginx2goaccess.sh '<log_format>'       #log_format为你nginx.conf中配置的日志格式

比如:

sh nginx2goaccess.sh '$remote_addr [$time_local] "$request" $status $bytes_sent "$http_referer" "$http_user_agent" "$http_cookie" "$request_body"'

转换的结果是

- Generated goaccess config:
time-format %T
date-format %d/%b/%Y
log_format %h [%d:%t %^] "%r" %s %b "%R" "%u" "%^" "%r_body"

把结果保存为go.conf文件

然后就可以对nginx日志进行分析了

./goaccess -f nginx_access.log -p go.conf -o report.html

发现报错

Token already set for '%r' specifier.,那个因为%r_body不被支持,替换为

log_format %h [%d:%t %^] "%r" %s %b "%R" "%u" "%^" "%^"

如果要对日志进行实时分析

nohup goaccess -f nginx_access.log -p go.conf -o report.html --real-time-html --daemonize --ws-url=xxx.xxx.com &

需要注意的时,如果你的域名使用了ssl链接,那么指定ws-url也必须用wss://开头,并且指定证书,否则浏览器会拦截未加密的请求,正常情况使用http协议会比较方便,也不会出问题

如果想让报表用中文显示,必须1.3版本以上才支持

LANG="zh_CN.UTF-8" bash -c "nohup goaccess -f nginx_access.log -p go.conf -o report.html --real-time-html --daemonize --ws-url=xxx.xxx.com &"

goaccess命令参数:

-a --agent-list 启用由主机用户代理的列表。为了更快的解析,不启用该项
-d --with-output-resolver 在HTML/JSON输出中开启IP解析,会使用GeoIP来进行IP解析
-f --log-file 需要分析的日志文件路径
-p --config-file 配置文件路径
-o --output 输出格式,支持html、json、csv
-m --with-mouse 控制面板支持鼠标点击
-q --no-query-string 忽略请求的参数部分
--real-time-html 实时生成HTML报告
--daemonize 守护进程模式,--real-time-html时使用
--ws-url 指定实时报告模式下生成的html页面发起websocket通讯执行的服务器地址。报表页面与GoAccess服务端通过HTTP建立连接后,后续就是WebSocket数据传输了,GoAccess默认使用了7890端口发起socket通讯,需要注意的时,老版本的goaccess报表页面在重新执行goaccess命令时并不会重新生成,所以如果修改了ws-url,需要上传原有的html页面再重新生成

goaccess日期时间格式:

%a 星期几的简写
%A 星期几的全称
%b 月份的简写
%B 月份的全称
%c 标准的日期的时间串
%C 年份的前两位数字
%d 十进制表示的每月的第几天
%D 月/天/年
%e 在两字符域中,十进制表示的每月的第几天
%F 年-月-日
%g 年份的后两位数字,使用基于周的年
%G 年份,使用基于周的年
%h 简写的月份名
%H 24小时制的小时
%I 12小时制的小时
%j 十进制表示的每年的第几天
%m 十进制表示的月份
%M 十时制表示的分钟数
%n 新行符
%p 本地的AM或PM的等价显示
%r 12小时的时间
%R 显示小时和分钟:hh:mm
%S 十进制的秒数
%t 水平制表符
%T 显示时分秒:hh:mm:ss
%u 每周的第几天,星期一为第一天 (值从1到7,星期一为1)
%U 第年的第几周,把星期日作为第一天(值从0到53)
%V 每年的第几周,使用基于周的年
%w 十进制表示的星期几(值从0到6,星期天为0)
%W 每年的第几周,把星期一做为第一天(值从0到53)
%x 标准的日期串
%X 标准的时间串
%y 不带世纪的十进制年份(值从0到99)
%Y 带世纪部分的十制年份
%z,%Z 时区名称,如果不能得到时区名称则返回空字符。
%% 百分号

goaccess 格式标识:

%t  匹配time-format格式的时间字段
%d  匹配date-format格式的日期字段
%h  host(客户端ip地址,包括ipv4和ipv6)
%r  来自客户端的请求行
%m  请求的方法
%U  URL路径
%H  请求协议
%s  服务器响应的状态码
%b  服务器返回的内容大小
%R  HTTP请求头的referer字段
%u  用户代理的HTTP请求报头
%D  请求所花费的时间,单位微秒
%T  请求所花费的时间,单位秒
%^  忽略这一字段

如果nginx2goaccess转换的格式使用时会报错,请自行按以上格式标识编写

为了设置正确的log format,踩了不少坑,先列出来避免大家重复碰到。
(1) log format默认是按照空格分隔日志信息的,所以,对于包含了特殊字符如空格等信息的字段,必须包含在“”里面。如字段request http_user_agent等
(2) nginx日志格式里面,采用空格分隔,但是此处一定注意,只能用一个空格。当时我有个地方用了两个空格,直接导致goaccess结果出错。
(3) nginx日志中的每一个字段都要和log format中的对应,如果log format中不需要nginx中的某一个信息,则用%^跳过该信息。
(4) 对于nginx日志中的每一个 -(中划线), log format都需要一个%^来跳过, 如果是“-”, 则用“%^”
(5) 如果nginx日志信息中有:(冒号), 则需要在log format中也显示出来。例如nginx日志中$time_local就包含了:(冒号),所以在log format的相应位置也是 [%d:%t %^]