最直接方法是用openssl x509 -in cert.pem -noout -enddate读取本地PEM证书过期时间,需确保文件仅含一段以-----BEGIN CERTIFICATE-----开头的证书;若报错则可能混入私钥或多证书,须先分离。

用 openssl 直接读取本地证书文件的过期时间
证书没部署到服务上,只是手头有个 cert.pem 或 fullchain.pem 文件?最直接的办法就是用 openssl 解析它。关键不是“能不能看”,而是别把中间证书或私钥误当主体证书去解析。
- 确认你读的是真正的证书(PEM 格式、以
-----BEGIN CERTIFICATE-----开头),不是key.pem或ca-bundle.crt - 执行:
openssl x509 -in cert.pem -noout -enddate,输出类似notAfter=Mar 15 12:34:56 2025 GMT - 如果报错
unable to load certificate,大概率是文件里混了多段内容(比如 cert + key 合并在一个文件),先用awk或手动拆开,只保留一段证书 - 想同时看生效和过期时间:
openssl x509 -in cert.pem -noout -dates
检查正在运行的 HTTPS 服务的实时证书信息
线上网站证书可能已更新,但本地文件没同步;或者 Nginx/Apache 配置指向了错误路径。这时候必须从 TCP 层真实握手一次,才能拿到服务端实际返回的证书链。
- 命令:
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate - 注意:默认走 TLSv1.2,若服务只支持 TLSv1.3(如某些新版 Cloudflare),加
-tls1_3参数;若被 SNI 拦截,加-servername example.com - 常见错误现象:
Connection refused是端口不通,ssl handshake failure多因协议/ALPN 不匹配,不是证书问题本身 - 如果服务用了自签名或私有 CA,
s_client会报验证失败,但不影响提取-enddate,因为-noout跳过了验证步骤
批量检查多个域名或证书文件的过期时间
运维要盯几十个域名时,手动敲命令太慢,也容易漏。核心是把“提取日期 → 转成可比较的时间戳 → 判断是否临近过期”这三步串起来,而不是堆 for 循环。
- 单域名快速预警(7 天内过期):
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate 2>/dev/null | awk -F'= ' '{print $2}' | xargs -I{} date -d "{}" +%s 2>/dev/null | awk -v now=$(date +%s) '$1 - 检查本地目录下所有
*.crt:find /etc/ssl/certs -name "*.crt" -exec openssl x509 -in {} -noout -enddate \; 2>/dev/null | grep notAfter - 别依赖
date的 locale 输出格式,不同系统(CentOS vs Ubuntu)对Mar 15 12:34:56 2025 GMT解析可能失败,生产脚本建议用openssl x509 -in xxx -noout -ext subjectAltName辅助确认证书用途,避免误判泛域名或测试证书
为什么 curl -v 看不到准确过期时间
curl -v https://example.com 只显示 SSL 握手摘要,不暴露证书原始字段。它底层调用 OpenSSL 或 NSS,但默认不 dump 证书内容 —— 这不是 bug,是设计使然:避免日志泄露敏感信息,也减少输出噪音。
- 想用 curl 辅助判断?可以加
--write-out "%{ssl_verify_result}\n",返回 0 表示验证通过,但无法告诉你还剩几天 - 某些发行版的 curl 编译时禁用了 OpenSSL backend(改用 GnuTLS 或 mbedTLS),这时
s_client仍是唯一可靠选择 - 别试图从
curl -v的* Server certificate:区块里肉眼找日期——那只是摘要,没有notAfter
证书过期时间不是静态元数据,它依赖你读的是哪个文件、连的是哪个 IP、走的是哪个 TLS 版本、甚至目标服务是否做了 OCSP Stapling。最稳妥的做法永远是:用 s_client 对线上地址做一次真实握手,再解析返回的证书。其他方式都算间接推断。










