Skip to content

nginx 配置不生效?搞懂 sites-available 和 sites-enabled ​

一句话总结:nginx 配置改了不生效,99% 是因为没搞清楚 sites-available 和 sites-enabled 之间的符号链接机制,改错了文件或没做软链接。

字段内容
标签#nginx #配置排故 #symlink #sites-enabled #DevOps
踩坑日期2026-07-19
严重程度🔴 中

事故经过 ​

时间线 ​

那天风哥让我给一个新站点配 nginx,子域名 xxx.sirenzhuli.cn 要指向后端 8898 端口。

操作过程(错误的):

  1. 我信心满满地 vim /etc/nginx/sites-available/xxx,写了一个漂亮的配置文件
  2. nginx -t 检测通过,语法没问题
  3. systemctl reload nginx,重启服务
  4. 浏览器访问 xxx.sirenzhuli.cn → 404 Not Found
  5. 我盯着配置反复看,哪里写错了?
  6. nginx -t 再跑一次,还是 OK
  7. 抓狂了半小时……

最终发现:

bash
ls -la /etc/nginx/sites-enabled/

——里面根本没有我新建的那个配置文件!


还有一次更坑的: 我之前改过 DNS,把某个子域名从旧 IP 指向了新 IP,结果旧 APP 还在用域名请求,直接全军覆没。教训在下面一起讲。

根因分析 ​

第一层:出错了文件,改了个寂寞 ​

nginx 在启动/重载时真正读取的是 /etc/nginx/sites-enabled/ 目录下的文件,而不是 /etc/nginx/sites-available/。

主配置文件 /etc/nginx/nginx.conf 里通常有这样一行:

nginx
include /etc/nginx/sites-enabled/*;

也就是说——只有 sites-enabled 里的文件才会被加载,sites-available 只是一个"仓库",放着你所有的站点配置模板。

第二层:为什么这样设计? ​

这是 Debian/Ubuntu 系 Linux 的最佳实践:

目录作用被 nginx 读取?
sites-available/所有站点配置的原件存放地(仓库)❌ 不读取
sites-enabled/需要启用的站点配置的符号链接(实际生效)✅ 读取

好处:想启用一个站点就 ln -s 做个软链接,想停掉就 rm 删链接,配置文件本身不动。比直接改文件名优雅得多。

第三层:符号链接 vs 直接复制 ​

很多新手会 cp sites-available/xxx sites-enabled/xxx,这样做虽然也能生效,但会带来一个隐患:

  • 后面你改了 sites-available/xxx,但 sites-enabled/xxx 还是老版本(因为是 cp 不是 ln)
  • 于是你又一次陷入"改了怎么不生效"的困境

正确的做法就是 ln -s 做符号链接。

第四层:DNS 变更的连锁反应 ​

回到 DNS 的问题。风哥的教训 #1:"改 DNS 没考虑旧 APP"。

当你改了一个域名的 A 记录,旧的 APP/客户端如果没做热更新,会直接请求到旧 IP。看起来就像"nginx 不生效",其实是请求根本没到这台服务器。

所以排查 nginx 配置问题的第一步永远是:确认请求到底到了没有。

解决方案 ​

标准工作流(复制即用) ​

Step 1:创建配置文件

bash
sudo vim /etc/nginx/sites-available/xxx

写一个基础反向代理配置:

nginx
server {
    listen 80;
    server_name xxx.sirenzhuli.cn;

    location / {
        proxy_pass http://127.0.0.1:8898;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Step 2:检查 sites-enabled 里到底有什么

bash
ls -la /etc/nginx/sites-enabled/

看看已有的文件是 symlink 还是普通文件:

bash
# 如果是软链接(箭头 → 指向原文件)
lrwxrwxrwx 1 root root   41 Jul 19 12:00 default -> /etc/nginx/sites-available/default

# 如果是普通文件(- 开头,没有箭头)
-rw-r--r-- 1 root root 1234 Jul 19 12:00 default

Step 3:创建符号链接

bash
sudo ln -s /etc/nginx/sites-available/xxx /etc/nginx/sites-enabled/xxx

Step 4:语法检查(永远别跳过这步!)

bash
sudo nginx -t

预期输出:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Step 5:重载配置(不中断服务)

bash
sudo systemctl reload nginx

⚠️ 用 reload 而不是 restart!reload 不中断现有连接,restart 会断开所有请求。

常见踩坑排查命令 ​

bash
# 1. 看 nginx 到底加载了哪些 server 块
sudo nginx -T 2>/dev/null | grep -A 20 "server_name"

# 2. 看某个域名解析到了哪里
dig +short xxx.sirenzhuli.cn

# 3. 看端口有没有在监听
sudo ss -tlnp | grep nginx

# 4. 测试请求是否真的到了 nginx
curl -v -H "Host: xxx.sirenzhuli.cn" http://127.0.0.1/

# 5. 实时看 nginx 访问日志(确认请求到了没有)
sudo tail -f /var/log/nginx/access.log

预防措施 ​

操作前确认清单 ​

每次改 nginx 配置前,先跑:

bash
# □ 确认 sites-enabled 里有什么
ls -la /etc/nginx/sites-enabled/

# □ 确认当前生效的配置内容
sudo nginx -T 2>/dev/null | grep -E "(server_name|listen|proxy_pass)" | head -30

# □ 确认 DNS 解析正确
dig +short xxx.sirenzhuli.cn

改完配置必须做 ​

bash
# □ 语法检查
sudo nginx -t

# □ 重载
sudo systemctl reload nginx

# □ 验证服务状态
sudo systemctl is-active nginx   # 应该输出 active

# □ 实际请求测试
curl -I -H "Host: xxx.sirenzhuli.cn" http://localhost/

铁律 ​

  1. 永远用 ln -s 而不是 cp:确保 sites-available 和 sites-enabled 保持同步
  2. 改配置前先看 sites-enabled:确认链接状态,别改了半天改的是死链接
  3. 用 reload 不用 restart:生产环境别断流
  4. nginx -t 是底线:这条命令不绿,别动 prod

关联知识点 ​


🎯 本章要点 ​

  • nginx -t先检查语法,确认无误再reload,否则服务中断
  • sites-enabled用ln -s指向sites-available,cp独立文件会导致不同步
加载练习题中...