Skip to content

nginx 配置不生效:symlink 陷阱与三指令区别

一个血泪教训:改了 sites-available 里的文件以为能生效,因为 sites-enabled 里那个同名文件是独立副本而不是符号链接。

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

事故经过

场景一:改了配置但死活不生效

那天给 kb.sirenzhuli.cn 更新 nginx 配置,增加一个 gzip 压缩的优化。改动很简单,在 /etc/nginx/sites-available/kb 里加了几行:

nginx
gzip on;
gzip_types text/css application/javascript text/plain;
gzip_min_length 256;

然后:

bash
sudo nginx -t          # ✅ syntax is ok
sudo systemctl reload nginx  # ✅ 重载成功

用浏览器打开页面,检查 Response Headers —— 没有 Content-Encoding: gzip。等了五分钟再试,还是没有。

重新 vim 打开 sites-available/kb,配置好好的在那里。折腾了一个多小时。

最终发现

bash
$ ls -la /etc/nginx/sites-enabled/
lrwxrwxrwx 1 root root  31 Jul 13 17:00 chat -> /etc/nginx/sites-available/chat
lrwxrwxrwx 1 root root  32 Jul 13 17:00 fayan -> /etc/nginx/sites-available/fayan
lrwxrwxrwx 1 root root  29 Aug  7 15:07 kb -> /etc/nginx/sites-available/kb
-rw-r--r-- 1 root root 1896 Aug  2 09:07 sandbox-proxy
-rw-r--r-- 1 root root 3303 Aug  1 23:42 sirenzhuli

sirenzhulisandbox-proxy 两个文件前面是 -rw-r--r--(普通文件),不是 l(符号链接)。

之前有人用 cp 而不是 ln -s 把这两个配置塞进了 sites-enabled。后来有人改了 sites-available/sirenzhuli 里的配置,但 sites-enabled/sirenzhuli 是独立副本,根本没被更新。

根因分析

第一层:nginx 到底读哪个目录

主配置文件 /etc/nginx/nginx.conf 里最关键的一行:

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

nginx 只读取 sites-enabled 目录sites-available 只是一个"仓库",放着所有站点的配置模板/原件。

Ubuntu/Debian 的设计哲学:

text
sites-available/     ← 配置仓库(原件),nginx 不读
    ├── chat         ← 真实配置
    ├── fayan
    ├── kb
    └── sirenzhuli

sites-enabled/       ← 生效目录(符号链接或副本),nginx 只读这里
    ├── chat -> ../sites-available/chat   ← symlink,改动同步生效
    ├── fayan -> ../sites-available/fayan
    ├── kb -> ../sites-available/kb
    ├── sandbox-proxy                     ← 独立普通文件,改了sites-available也没用
    └── sirenzhuli                        ← 同上

启用一个站点:ln -s sites-available/xxx sites-enabled/xxx 停用一个站点:rm sites-enabled/xxx(删除链接而已,原件还在)

第二层:cp vs ln -s 的本质区别

操作sites-enabled 里是什么改 sites-available 会同步?
ln -s (推荐)符号链接 → 指向原文件✅ 自动同步
cp独立的文件副本❌ 不会同步

符号链接就像一个快捷方式:当你读取 /etc/nginx/sites-enabled/kb 时,Linux 核心自动重定向到 /etc/nginx/sites-available/kb。所以改原文件等于改链接。

cp 复制是两个独立的文件:改了 sites-available/kbsites-enabled/kb 纹丝不动。

第三层:三个"重载"命令的区别

这是另一个常见的混乱点:

bash
# 1. nginx -t → 只测试语法,不重载
sudo nginx -t
# 输出: syntax is ok / test is successful
# 作用:检查配置文件语法是否有错误(缺分号、括号不匹配等)
# 但不检测逻辑错误(端口冲突、upstream 不通等)
# 不重载配置!不生效!

# 2. nginx -s reload → 热重载(直接发信号)
sudo nginx -s reload
# 作用:向 nginx master 进程发送 SIGHUP 信号,触发重新读取配置
# 不中断现有连接,新连接用新配置
# 前提:必须能访问 nginx.pid 文件(/run/nginx.pid)

# 3. systemctl reload nginx → 通过 systemd 管理重载
sudo systemctl reload nginx
# 作用:systemd 帮你找到进程、发送信号
# 好处:统一的 systemd 管理界面,有日志、有状态跟踪
# 前提:nginx 必须是通过 systemd 管理的服务

关系systemctl reload nginxnginx -s reload(底层都是发 SIGHUP),但 systemctl 更规范。

什么时候用哪个

场景用什么
改了配置,不确定语法对不对nginx -t
语法没问题,让新配置生效systemctl reload nginx
nginx 不是 systemd 管理的nginx -s reload
想知道 nginx 正在加载什么配置nginx -T

当前服务器的真实配置结构

服务器上实际有 4 个站点生效:

站点域名sites-enabled 类型说明
聊天chat.sirenzhuli.cnsymlink ✅指向 sites-available/chat
法眼fayan.sirenzhuli.cnsymlink ✅指向 sites-available/fayan
知识库kb.sirenzhuli.cnsymlink ✅指向 sites-available/kb(Let's Encrypt 自动管理)
小雅主页www.sirenzhuli.cn普通文件 ⚠️独立副本,需要手动同步
沙箱代理(端口 8899)普通文件 ⚠️独立副本,没有对应 sites-available

解决方案

正确的工作流

Step 1:永远从 sites-available 开始

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

Step 2:如果 sites-enabled 里是普通文件 → 先删掉,再建 symlink

bash
# 检查状态
ls -la /etc/nginx/sites-enabled/sirenzhuli

# 如果是普通文件(-rw-r--r--),先备份
sudo cp /etc/nginx/sites-enabled/sirenzhuli /etc/nginx/sites-available/sirenzhuli.bak

# 删除 sites-enabled 里的副本
sudo rm /etc/nginx/sites-enabled/sirenzhuli

# 建符号链接
sudo ln -s /etc/nginx/sites-available/sirenzhuli /etc/nginx/sites-enabled/sirenzhuli

# 验证
ls -la /etc/nginx/sites-enabled/sirenzhuli
# 预期输出: lrwxrwxrwx ... sirenzhuli -> /etc/nginx/sites-available/sirenzhuli

Step 3:语法检查 → 重载 → 验证

bash
sudo nginx -t && sudo systemctl reload nginx

一键诊断命令

bash
# 列出 sites-enabled 中的所有文件,标注类型
ls -la /etc/nginx/sites-enabled/

# 看 nginx 实际加载的所有配置(含所有 server 块)
sudo nginx -T 2>/dev/null | grep -E "^# configuration file|server_name|listen" | head -40

# 检查有没有 orphan 文件(sites-available 有但 sites-enabled 没有链接的)
comm -23 <(ls /etc/nginx/sites-available/ | sort) <(ls /etc/nginx/sites-enabled/ | sort)
# 输出示例: default, miniflux — 这些配置存在但未启用

预防措施

铁律

  1. 永远用 ln -s,不许用 cp — 进 sites-enabled 的唯一合法方式
  2. 改配置前先 ls -la /etc/nginx/sites-enabled/ — 确认链接状态
  3. 改完配置先 nginx -tsystemctl reload nginx — 两步缺一不可
  4. 怀疑不生效时跑 nginx -T — 直接看 nginx 真正加载的内容

日常检查命令

bash
# 定时任务(cron weekly):检查是否有副本而非symlink
find /etc/nginx/sites-enabled/ -maxdepth 1 -type f ! -type l

# 如果有输出 → 那些文件就是隐患,该改成 symlink

关联知识点


🎯 本章要点

  • 改配置后必须 nginx -t 检查语法,再重载
  • nginx -s reload 热重载不会断开已有连接
  • sites-enabled 应通过 symlink 指向 sites-available
加载练习题中...