最稳妥做法是在 log_format 中使用 $host 变量标识请求域名,而非 $server_name;$host 真实反映客户端 host 头,支持多域名共用 server 块的精准区分,便于按域名聚合分析与统计。

要在 Nginx 中用访问日志区分多站点流量,关键不是“记录虚拟主机名”这个动作本身,而是让每条日志明确标识请求归属的域名,并支持后续按域名聚合分析。最实用、最稳妥的做法是:**在 log_format 中包含 $host 变量,再统一写入一个日志文件(或按需分流),而非依赖 server 块隔离来“记录主机名”**。
为什么优先用 $host 而不是 $server_name
$host 来自 HTTP 请求头的 Host 字段,真实反映用户访问的是哪个域名(比如 www.example.com 或 api.example.com),即使多个域名共用同一个 server 块也能准确区分;$server_name 是配置里写的静态值,泛域名(如 *.example.com)下所有子域都显示相同名称,无法分辨具体来源。
- 客户端发
curl -H "Host: test.example.com" http://127.0.0.1→ 日志中 $host 就是 test.example.com - 若 server_name 设为
server_name *.example.com;→ $server_name 始终是 *.example.com,失去区分意义 - 对运维排查、流量统计、安全审计来说,$host 更贴近实际业务场景
配置带 host 的日志格式(推荐做法)
在 nginx.conf 的 http 块顶部定义一个通用日志格式,把 $host 放在开头或显眼位置:
log_format host_log '$host $remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
然后在 server 块或全局 access_log 中启用它:
access_log /var/log/nginx/access.log host_log;
这样所有请求都会在日志首字段留下域名,无需为每个站点单独建日志文件,也避免了路径权限、目录创建、logrotate 等额外维护成本。
快速按域名统计流量(命令行实操)
日志有了 $host,统计就变得极简单。例如查看各域名请求数 Top 10:
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
查看每个域名的 4xx/5xx 错误分布:
awk '$9 ~ /^(4|5)[0-9][0-9]$/ {print $1, $9}' /var/log/nginx/access.log | sort | uniq -c | sort -nr
注意:字段序号(如 $1、$9)需根据你实际 log_format 中的空格分隔结果确认,可用 head -1 /var/log/nginx/access.log 查看对齐方式。
需要独立日志文件时的安全写法
如果因合规、归档或日志系统接入要求必须物理分离文件,不建议直接用 access_log /var/log/nginx/$host.log;——Nginx 不会自动创建子目录,且原始 $host 可能含非法字符或路径遍历风险。
更稳妥的方式是配合 map 模块做白名单映射:
map $host $log_key {
default "unknown";
example.com "example";
api.example.com "api";
admin.example.org "admin";
}
<p>access_log /var/log/nginx/$log_key-access.log host_log;
</p>
这样既实现文件分离,又规避了变量直写带来的安全隐患,目录只需提前建好 /var/log/nginx/example-access.log 等几个固定路径即可。











