$server_name在泛域名配置下不可靠,因其固定返回配置字面值(如*.example.com)而非实际Host;应改用$host(解析后标准化主机名)或$http_host(原始Host头)记录真实请求域名。

Nginx 的 $server_name 变量在泛域名配置(如 server_name *.example.com;)下**不会自动展开为实际请求的 Host 值**,而是固定返回配置中写的字面值(例如 *.example.com),因此不能直接用于日志中区分真实访问的子域名。
为什么 $server_name 在泛域名中不可靠
该变量仅反映 server_name 指令的原始配置字符串,不参与运行时 Host 头匹配。即使请求是 api.example.com 或 blog.example.com,$server_name 仍输出 *.example.com,无法体现差异。
正确获取实际请求主机:用 $host 或 $http_host
应改用以下两个更合适的变量:
-
$host:Nginx 解析后的 Host 名,优先取请求行中的 Host 头,若缺失则取匹配的server_name;自动小写,自动去除端口;最常用、最安全。 -
$http_host:原始 Host 请求头(含端口,如shop.example.com:8080),未做标准化处理;若需保留端口或原始大小写可选,但需注意空值风险。
在 log_format 中替换使用
修改日志格式,将 $server_name 替换为 $host:
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$host'; # ← 关键:用 $host 代替 $server_name
重启 Nginx 后,日志中该字段即显示真实请求的子域名,如 admin.example.com、docs.example.com 等。
进阶:按子域名分类写入不同日志文件(可选)
若需进一步隔离日志,可用 map 指令将 $host 映射为日志路径:
map $host $log_path {
default /var/log/nginx/access.log;
~^api\. /var/log/nginx/api_access.log;
~^blog\. /var/log/nginx/blog_access.log;
~^docs\. /var/log/nginx/docs_access.log;
}
<p>access_log /var/log/nginx/$log_path main;
</p>
这样不同子域的请求会自动写入对应文件,便于运维分析。










