梦想博客

Nginx日志解析和自动切割

calendar 2023/09/04
refresh-cw 2023/11/25
1556字,4分钟

天下苦IIS久矣

作为高度依赖IIS的.neter,一直想摆脱IIS的束缚(以下是对IIS的吐槽

  • 什么垃圾玩意啊,换证书还要手动一个一个网站来设定
  • 什么垃圾玩意啊,居然不支持反向代理??
  • 什么垃圾玩意啊,居然不支持正向代理??
  • 什么垃圾玩意啊,不能在linux中(跨平台)用??
  • 什么垃圾玩意啊,资源消耗那么大??
  • 什么垃圾玩意啊,开启TLS1.3居然要升级到windows server 2022??
  • 什么垃圾玩意啊,居然不支持负载均衡??
  • 什么垃圾玩意啊,自动回收导致web缓存丢失??
  • 日志和监控方案相比于nginx的es不够详细和灵活
  • 发布.net core(>=.net5)的应用时还要单独安装runtime,甚至不支持单一文件发布,托管方式无,巨他妈坑,那我为什么不用asp.net core自带的Kestrel?只是少了个日志,我完全可以写一个中间件来实现啊
  • 遇到问题时,解决方案(stackoverflow)上的iis回答比nginx少的实在是太多

鉴于以上诸多的问题,加上asp.net core的兴起,使我彻底放弃了对iis的幻想

Nginx日志的自动切割 🔗

在nginx下日志会自动存储到/var/log/nginx下的access.log和error.log中(ubuntu22.04TLS)

如果网站访问量大的话,则会导致一个文件太大,而且也不太好解析,针对于此问题可以自行编写shell脚本或使用logrotate来实现,这里没有使用压缩

 1#!/bin/bash
 2
 3#Auto cut nginx log script.
 4#create by dreamslave
 5#create date:2023-09-01
 6
 7# nginx日志路径
 8logs_path=/var/log/nginx
 9# 当前日期
10currentDate=$(date -d 'yesterday' +%Y/%m/%d)
11
12# 使用 IFS(内部字段分隔符)将日期分解为年、月和日
13IFS='/' read -ra DATE_PARTS <<< "$currentDate"
14
15# 批量移动所有.log文件
16for log_file in ${logs_path}/*.log; do
17    # 取文件的基本名(不包括后缀),用于创建子目录
18    base_name=$(basename ${log_file} .log)
19
20    # 定义备份的日志文件夹路径
21    dir="${logs_path}/logs/${base_name}/${DATE_PARTS[0]}/${DATE_PARTS[1]}"
22
23    # 创建日志目录
24    mkdir -p ${dir} || { echo "Failed to create directory: ${dir}"; exit 1; }
25
26    if [ -f ${log_file} ]; then
27        # 移动并重命名日志文件到新目录中
28        mv ${log_file} ${dir}/${DATE_PARTS[2]}.log || { echo "Failed to move ${log_file}"; exit 1; }
29    else
30        echo "Log file ${log_file} does not exist."
31    fi
32done
33
34# 向nginx主进程发送信号,重新生成日志文件
35nginx -s reopen || { echo "Failed to reopen Nginx logs"; exit 1; }
36
37echo "Log backup successful for date: ${currentDate}"

以上脚本可以使用crontab -e来设定每日0点自动执行一次

如此便完成了如何在nginx中切割日志的操作

使用GoAccess来实现nginx日志的解析 🔗

GoAccess项目地址

安装GoAccess(ubuntu)

1wget -O - https://deb.goaccess.io/gnugpg.key | gpg --dearmor | sudo tee /usr/share/keyrings/goaccess.gpg >/dev/null
2echo "deb [signed-by=/usr/share/keyrings/goaccess.gpg arch=$(dpkg --print-architecture)] https://deb.goaccess.io/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/goaccess.list
3sudo apt-get update
4sudo apt-get install goaccess

由于goaccess的日志配置相对比较麻烦,所以推荐使用nginx2goaccess来实现日志的自动化生成

我的日志格式为

1log_format  main  '$remote_addr - $remote_user [$time_local] "$request" $status  $body_bytes_sent $request_time $upstream_response_time $upstream_addr "$http_referer" "$http_user_agent" "$http_x_forwarded_for"';

对应的goaccess的日志格式为

1find /var/log/nginx/logs/ -name '*.log' -print0 | xargs -0 goaccess --log-format='%h - %^ [%d:%t %^] "%r" %s  %b %T %^ %^ "%R" "%u" "%^"' --date-format='%d/%b/%Y' --time-format='%T' -o /var/www/html/report.html --real-time-html
2
3# 这里是压缩版的
4find /var/log/nginx/logs/ -name '*.log.gz' -print0 | xargs -0 zcat | goaccess --log-format='%h - %^ [%d:%t %^] "%r" %s  %b %T %^ %^ "%R" "%u" "%^"' --date-format='%d/%b/%Y' --time-format='%T' -c

请注意,默认的goaccess是不支持中文输出的,需要将LANG=zh_CN

goaccess的日志解析分为cli和webui 2种方式

  • cli版


  • WebUI版


webui版使用websocket来实时更新数据,所以整体来说webui更加方便

同时goaccess还提供了导出csv和json的多种功能,可以更可观的看到网站各项访问指标

2023/11/25追加更新 🔗

使用goaccess自带的ws进行实时日志刷新 🔗

进入goaccess的配置项,进行编辑

1vi /etc/goaccess/goaccess.conf

修改ws-url为 wss://record.dreamogi.com:443/logs (自己设置节点)

然后在nginx配置中反代ws(默认端口是7890,可在goaccess.conf编辑)

1location /logs {
2    proxy_pass http://localhost:7890;
3    proxy_http_version 1.1;
4    proxy_set_header Upgrade $http_upgrade;
5    proxy_set_header Connection "Upgrade";
6}

如此便完成了网站日志实时刷新的功能,为了安全起见请设置

1    auth_basic           "Private Property";
2    auth_basic_user_file /etc/nginx/.htpasswd;

这里补个坑,如何nginx授权访问(输入账号密码)

1apt install apache2-utils
2sudo htpasswd -c /etc/nginx/.htpasswd [账号]
3//这里在nginx里编辑auth_basic
4systemctl restart nginx

分类