排查server_name冲突的核心是确认实际响应请求的server块,而非仅检查配置是否存在;nginx静默按精确匹配>通配符>正则优先级选块,未匹配时由default_server或首个server块兜底,重复定义会导致后加载者被忽略。

排查 server_name 冲突导致的路由错乱,核心是确认“哪个 server 块真正响应了请求”,而不是只看配置写了没写。Nginx 不报错、不警告(除非有明确冲突日志),而是静默按规则选块——结果就是访问 app.example.com 却打开默认页或另一个测试站。
查最终生效的配置结构
用 nginx -T 输出完整合并后的配置(含所有 include),直接定位目标域名:
- 搜索是否加载:`nginx -T 2>/dev/null | grep -A 10 "server_name.*app\.example\.com"` —— 看它出现在哪个文件、是否被重复定义
- 列出所有 80 端口 server 块:`nginx -T 2>/dev/null | grep "listen.*80" -A 5` —— 观察顺序、default_server 标记、以及是否有多个块都写了相同的 server_name
- 注意警告信息:如 conflicting server name "app.example.com" on 0.0.0.0:80, ignored,说明后加载的那个块已被丢弃
验匹配逻辑是否被绕过
server_name 匹配不是“模糊包含”,而是严格按优先级逐级比对:
- 精确匹配(
server_name app.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并重启,如果原来 404 的域名突然正常,说明是加载顺序或兜底冲突 - 绕过 DNS 直连测试:
curl -H "Host: app.example.com" http://127.0.0.1,确认是否仍进错块 - 在疑似“抢流量”的兜底块里加
return 444;或单独日志:access_log /var/log/nginx/catch-all.log;,观察是否有意外 Host 头打进来
查 default_server 和隐式兜底
没设 default_server ≠ 安全。Nginx 会把同一端口下第一个定义的 server 块当作隐式兜底:
- IP 直接访问(如
http://192.168.1.100)时 Host 头为空或非法,必然落入 default_server 或第一个块 - 用这条命令快速扫描所有监听 80 的块及其 server_name:
`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











