Linux--nginx中geo信息分析
nginx geo信息分析
使用场景
在 Nginx 中启用 GeoIP2 模块,记录用户访问日志,并通过 Python 脚本进行二次分析。
模块安装
在 Ubuntu 20+ / 22+ 系统中,GeoIP2 模块可以直接通过 apt 安装:
1 | # 装模块(Ubuntu 20+/22+ 自带) |
文件配置
- 在 nginx.conf 中启用 geo 变量
在 http {} 段中加入如下配置:
1 | http { |
- 在 server 块中单独启用日志
1
2
3
4
5
6
7
8
9
10
11
12
13server {
listen 443 ssl http2;
...
....
...
# ⭐ 记录带有地理信息的日志
access_log /var/log/nginx/xxxx_geo.log geo_combined;
location / {
try_files $uri $uri/ =404;
}
}
3.启动与验证
1 | # 检查配置是否正确 |
可能端口已经被占用,可以先暂停端口监听:
1 | sudo lsof -ti:80 | xargs -r sudo kill -9 |
如果输出为空说明端口已释放
日志分析
- 自定义日志解析脚本安装与运行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54#!/usr/bin/env python3
import re, csv, os, glob, gzip
from user_agents import parse
from datetime import datetime, timedelta
LOG_DIR = '/var/log/nginx'
LOG_PAT = 'access_geo.log*' # 支持 *.gz
OUT_DIR = os.path.expanduser('~/nginx_geo_daily')
# 昨天的日期
day_str = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
out_csv = os.path.join(OUT_DIR, f'{day_str}.csv')
# 正则:IP、时间、UA、Country、Region、City
line_re = re.compile(
r'(?P<ip>\d+\.\d+\.\d+\.\d+) .*?\[(?P<dt>[^\]]+)\] '
r'".*?" \d+ \d+ ".*?" "(?P<ua>[^"]+)" '
r'Country=(?P<country>[^ ]+) Region=(?P<region>[^ ]+) City=(?P<city>[^ ]+)'
)
rows = []
for path in glob.glob(os.path.join(LOG_DIR, LOG_PAT)):
opener = gzip.open if path.endswith('.gz') else open
with opener(path, 'rt', encoding='utf-8', errors='ignore') as f:
for line in f:
m = line_re.search(line)
if not m:
continue
ua = parse(m.group('ua'))
rows.append({
'datetime' : m.group('dt'),
'ip' : m.group('ip'),
'device' : ua.device.family,
'os' : ua.os.family,
'browser' : ua.browser.family,
'country' : m.group('country'),
'region' : m.group('region'),
'city' : m.group('city'),
})
# 去重 & 排序
rows = sorted({(r['ip'], r['datetime']): r for r in rows}.values(),
key=lambda r: r['datetime'])
os.makedirs(OUT_DIR, exist_ok=True)
with open(out_csv, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f,
fieldnames=['datetime','ip','device','os','browser','country','region','city'])
writer.writeheader()
writer.writerows(rows)
print(f'{len(rows)} records written to {out_csv}')1
2
3
4
5
6
7sudo mkdir -p /usr/local/bin /var/log/nginx/geo_daily
sudo tee /usr/local/bin/nginx_geo_daily.py < nginx_geo_daily.py
sudo chmod +x /usr/local/bin/nginx_geo_daily.py
# 手动执行 在/home/xxx/nginx_geo_daily/ 生成文件
/usr/local/bin/nginx_geo_daily.py - 定时任务
每天23:05执行
1 | crontab -e |