最准的是用 $uri 字段统计接口路径,它自动解码且剔除 query string;需自定义 log_format 使用 $uri,再配合 awk 按字段精准过滤统计。

直接看 $uri 字段最准,别用 $request 粗暴切分——它带参数、含空格、编码混乱,一统计就错。
先确保日志里有干净的接口路径
默认 `combined` 格式只记 `$request`(比如 "GET /api/users?id=123 HTTP/1.1"),没法直接当「页面」用。必须改 `log_format`,显式提取解码后、无参数的路径:
在 nginx.conf 的 http 或 server 块中添加:
log_format api_page '$remote_addr - $remote_user [$time_local] '
'"$request_method $uri $http_version" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" $request_time';
关键点:$uri 自动解码且丢弃 query string,/search?q=a 和 /search?q=b 都归为 /search;而 $request_uri 保留原始编码和参数,适合调试但不适合统计。
然后指定 access_log 使用它:
access_log /var/log/nginx/access.log api_page;
重载生效:nginx -s reload。注意:旧日志不会自动切换格式,新请求才写入新结构。
用 awk 精准统计 TOP 页面(排除噪音)
字段位置取决于你定义的 `log_format`。先确认一下:
使用tbot机器ID身份文件配合tsh CLI,通过Teleport访问控制SSH登录托管主机或执行远程命令。
head -1 /var/log/nginx/access.log
通常 `$7` 是 `$uri`,`$9` 是状态码。推荐命令(过滤掉健康检查、静态资源、错误响应):
awk '$9 >= 200 && $9- 管道接
| sort | uniq -c | sort -nr | head -20
这样能真实反映用户高频访问的业务页面,比如 /dashboard、/product/list,而不是被 /favicon.ico 或爬虫扫的 /admin/login 拉偏。
快速验证和临时分析(没改日志格式时)
如果暂时不能改配置,可用 `sed` 粗略剥离路径(仅限 GET/HEAD 请求):
sed -n 's/^.*"GET \(\/[^[:space:]"]*\).*/\1/p' /var/log/nginx/access.log
再配合去重统计:
sed -n 's/^.*"GET \(\/[^[:space:]"]*\).*/\1/p' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -15
⚠️ 注意:该方法对 POST 请求(如 "POST /upload HTTP/1.1" 后带 body)无效,也不处理编码字符(如 %20),仅作应急参考。
加个实时看板更直观
装个 GoAccess,一行命令生成带地域、浏览器、URL 排行的 HTML 报告:
goaccess /var/log/nginx/access.log \ --log-format=COMBINED \ --date-format='%d/%b/%Y' \ --time-format='%H:%M:%S' \ --ignore-crawlers \ -o /var/www/html/report.html
打开网页就能看到「Requested URLs」Tab,自动聚合、去参、排序,还支持点击钻取详情,比手敲 awk 快得多。










