核心是确认“谁真正响应请求”,Nginx静默忽略后加载的重复server_name,需用nginx -T查生效配置、检查同一端口下是否重复定义、验证匹配优先级(精确>通配符>正则)及default_server设置。

排查多站点共用端口(如 80 或 443)时的 server_name 冲突,核心是搞清“谁真正响应了请求”,而不是只看配置文件里有没有写。Nginx 不报错、不中断,但会静默忽略后加载的重复项——你访问 app.example.com,结果打开的是默认站或测试站,问题就出在这里。
看最终生效的配置结构
用 nginx -T 输出完整合并后的配置(含所有 include),直接搜索你的域名:
-
nginx -T 2>/dev/null | grep -A 10 "server_name.*app\.example\.com"—— 查该域名是否被加载、在哪一个文件里、是否重复出现 -
nginx -T 2>/dev/null | grep "listen.*80" -A 5—— 列出所有监听 80 的server块,观察顺序和是否有default_server - 重点检查:同一端口下是否多个块都写了
server_name app.example.com;若有,后加载者会被静默忽略,并在重载时输出警告:conflicting server name "app.example.com" on 0.0.0.0:80, ignored
确认匹配优先级是否被绕过
Nginx 匹配不是“找到就停”,而是按固定顺序逐级筛选:
- 精确匹配(
server_name app.example.com)优先于通配符(*.example.com) - 通配符
*.example.com不匹配example.com,必须显式加上example.com - 如果用
www.app.example.com访问,但只配了app.example.com,则完全不匹配——应写成server_name app.example.com www.app.example.com - 正则匹配(如
~^app\..*)一旦命中立即终止,不再比较后续块
验证实际路由路径
别只信文件名或目录位置,用真实请求验证哪个块在响应:
- 临时把目标配置改名为
00-app.conf,重启 Nginx;如果原来 404 的域名突然正常,说明是加载顺序或兜底冲突 - 用
curl -H "Host: app.example.com" http://127.0.0.1绕过 DNS 直连本地,确认是否仍进错块 - 在疑似“抢流量”的兜底块里加
return 444;或写独立日志:access_log /var/log/nginx/catch-all.log;,看是否有意外请求打进来
检查 default_server 和隐式兜底
没设 default_server 并不等于安全:
- IP 直接访问(如
http://192.168.1.100)时,Host 头为空或非法,必然落入default_server或第一个定义的server块 - 查所有监听 80 的块:
nginx -T 2>/dev/null | awk '/^server {/,/^}/ {if (/listen.*80/) print FILENAME ":" NR; if (/server_name/) print " " $0}' - 确保兜底块(如
99-default.conf)明确带default_server,且不包含无关server_name,避免误响应











