1. 触发场景

用宝塔面板装的 nginx(二进制在 /www/server/nginx/sbin/nginx),改完 vhost 后执行:

sudo systemctl reload nginx

2. 症状

命令返回 0。systemctl status nginx 甚至显示:

Process: 10794 ExecReload=/etc/init.d/nginx reload (code=exited, status=0/SUCCESS)

但新写的 vhost / 新换的证书就是没生效。于是你回去反复检查 vhost 文件、证书路径、nginx -t——全是对的,因为问题不在那。

3. 决定性判据

别信退出码,实测。 用一个只有新配置才会给出的特征去问 nginx:

# 新装了证书:问它现在给哪张证书
echo | openssl s_client -connect 127.0.0.1:443 -servername <新域名> 2>/dev/null | openssl x509 -noout -subject

# 或者直接拿新路径要内容
curl -s -o /dev/null -w "%{http_code}\n" https://<新域名>/<新路径>

拿到旧行为 = 没生效。

4. 根因

宝塔的 nginx 由 /etc/init.d/nginx 管。systemd 看到的 nginx.service 是 sysv-generator 自动生成的壳(/run/systemd/generator.late/nginx.service):

ExecStart=/etc/init.d/nginx start
ExecStop=/etc/init.d/nginx stop
ExecReload=/etc/init.d/nginx reload
Type=forking
GuessMainPID=no

systemctl reload 实际是去跑这个 init 脚本的 reload 分支。在这台机器上它没有真正让正在跑的 nginx 重新读配置,退出码却是 0。

5. 修法

绕开 systemd,直接对二进制发信号:

sudo /www/server/nginx/sbin/nginx -t && sudo /www/server/nginx/sbin/nginx -s reload

改完再实测一次(第 3 节),确认真的生效。

6. 下次如何识别

  • 「reload 说成功了,但行为没变」→ 直接换 nginx -s reload 重试,再实测。
  • 在宝塔的机器上,默认用 nginx -s reload,不用 systemctl。注意二进制路径是宝塔的,不是 /usr/sbin/nginx。
  • 这类「退出码 0 但没生效」的坑不只出现在 nginx:凡是靠退出码判断成功的地方,都要补一个行为断言——证书看 subject、接口看响应、文件看内容。

7. 相关

来源:2026-09-22 在 LA 小鸡(宝塔面板,nginx 1.28.1)上新增 vhost。systemctl reload nginx 返回 0、status 显示 SUCCESS,但 openssl s_client 仍拿到旧证书;改用 /www/server/nginx/sbin/nginx -s reload 后立刻生效。

本文归档于个人知识库 · 领域:CS & AI · 模块:04 Project_CS_AI/Network