核心是验证worker进程实际加载的证书文件:用lsof或/proc/[pid]/fd查看句柄,对比文件时间戳和openssl x509有效期;reload不强制刷新旧worker证书,需检查error.log错误、确保nginx -t通过,并在必要时强制终止旧进程。

直接看 Nginx worker 进程实际加载的证书文件,而不是只信配置里写的路径——这是排查“reload 后仍用旧证书”的核心动作。
确认 worker 进程是否已加载新证书
Nginx -s reload 不会强制所有 worker 进程立即丢弃旧证书内存副本,旧进程可能还在处理请求并沿用旧证书。需验证当前提供服务的进程到底读的是哪个文件:
- 查主进程 PID:
ps -ef | grep nginx | grep master,再用lsof -p [pid] | grep ssl或ls -l /proc/[worker-pid]/fd/ | grep ssl查看 worker 进程打开的证书文件句柄(注意找worker进程,不是master) - 对比时间戳:运行
ls -l /etc/nginx/ssl/your.crt看修改时间是否为你替换证书的时间;再用openssl x509 -in /path/to/crt -noout -dates确认生效/过期时间是否为新证书 - 若发现 worker 进程打开的仍是旧路径或旧文件,说明 reload 没真正触发证书重载,可能因配置未生效、权限阻断或进程残留
检查 reload 是否真正完成且无报错
reload 表面成功不代表证书被重新加载。Nginx 在 reload 时不会主动校验证书内容,只有在首次读取或 TLS 握手初始化时才加载证书。因此:
- 执行
nginx -t确保语法正确、路径存在、权限可读——这一步失败会静默跳过证书加载 - 查看 error.log:
tail -f /var/log/nginx/error.log,关注是否有cannot load certificate、PEM_read_bio_X509或no start line类错误,这类错误常因格式/权限问题导致 Nginx 回退使用内存中缓存的旧证书 - 注意:即使 reload 返回 success,只要 worker 进程没退出重建,它就继续用旧 SSL 上下文,证书不会刷新
强制终止旧 worker 进程释放证书句柄
reload 是平滑的,但旧 worker 可能长期存活(尤其低流量站点),持续持有旧证书文件句柄。此时需主动清理:
- Linux 下:先
nginx -s stop停止全部进程,再nginx启动全新实例(非 reload),确保所有 worker 都是新进程 - 或更精准操作:
kill -USR2 $(cat /var/run/nginx.pid)触发二进制升级(生成新 worker),再kill -QUIT $(cat /var/run/nginx.pid.oldbin)安全退出旧 worker - Windows 下:
taskkill /f /im nginx.exe彻底结束所有 nginx 进程,再手动启动,避免残留多个实例各自持不同证书
验证客户端实际收到的证书链
绕过浏览器缓存,直接抓取服务端真实响应:
- 用 OpenSSL 测试:
echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>/dev/null | openssl x509 -noout -dates -subject,输出应显示新证书的生效时间和 CN - Chrome 开发者工具 → Security 标签页 → View Certificate,确认“颁发给”和有效期与你替换的新证书一致
- 若上述结果仍是旧证书,说明服务端根本没换;若已是新证书但浏览器仍提示旧的,问题在客户端缓存(HSTS、TLS session cache、DNS 缓存),需单独清理











