最可靠方式是用 openssl x509 -in cert.pem -noout -dates,需确保证书为 PEM 格式(以-----BEGIN CERTIFICATE-----开头)、路径正确、权限可读;远程站点则用 echo | openssl s_client -servername domain.com -connect domain.com:443 2>/dev/null | openssl x509 -noout -dates。

openssl x509 -in 怎么用才不报错
直接对证书文件执行 openssl x509 -in cert.pem -noout -dates 是最常用也最可靠的方式。但常见错误是:传入了非 PEM 格式证书(比如 DER 或 P7B),或路径写错导致读不到文件,报 Error opening certificate file 或 unable to load certificate。
实操建议:
- 先确认证书是 PEM 格式:用
head -n 2 cert.pem看是否以-----BEGIN CERTIFICATE-----开头 - 如果不是 PEM,先转换:DER 转 PEM 用
openssl x509 -inform DER -in cert.cer -out cert.pem - 路径必须是绝对路径或相对路径正确;如果从 Nginx/Apache 配置里复制的路径,注意别漏掉
/etc/ssl/certs/这类前缀 - 权限不足时会静默失败,加
sudo并不解决证书读取问题——openssl不需要 root 权限读证书文件,但若文件属主是 root 且权限为600,普通用户确实打不开,此时用sudo cat cert.pem | openssl x509 -noout -dates
curl -v 查 HTTPS 站点时怎么提取有效期
当证书部署在远程服务上(如网站),你没法直接访问 .pem 文件,这时靠 curl -v https://example.com 2>&1 | grep "expire\|after" 很容易漏掉或误匹配。真正稳定的做法是让 curl 输出原始证书链,再交给 openssl 解析。
实操建议:
- 用
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates——这是最干净的组合,绕过 curl 的 HTML/HTTP 解析干扰 - 如果站点用了 SNI(绝大多数 HTTPS 站点都用),必须加
-servername example.com,否则可能拿到默认证书或握手失败:echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates - 超时或防火墙拦截时,
s_client可能卡住,默认无 timeout;加-timeout参数(OpenSSL 1.1.1+ 支持)或用timeout 5s包裹整条命令
批量检查多个域名或证书文件
运维中常要巡检一堆域名或证书文件,手动敲太累。关键不是“写个脚本”,而是避免常见陷阱:空行、DNS 解析失败、证书链不全导致 s_client 拿不到 leaf 证书。
实操建议:
- 检查本地文件列表:用
for f in *.pem; do echo "$f:"; openssl x509 -in "$f" -noout -dates 2>/dev/null || echo "invalid or empty"; done - 检查域名列表(
domains.txt每行一个):while read -r d; do [ -z "$d" ] && continue; echo "$d:"; timeout 5s openssl s_client -servername "$d" -connect "$d:443" 2>/dev/null | openssl x509 -noout -dates 2>/dev/null || echo "fail or timeout"; done - 注意:
s_client默认只返回 leaf 证书;如果中间证书缺失,openssl x509仍能解析成功——它不验证信任链,只看当前证书字段,所以过期判断不受 CA 证书缺失影响
为什么 date -d 输出看起来不对
很多人把 notAfter=Jan 15 12:00:00 2025 GMT 丢给 date -d 做计算,结果报 invalid date。根本原因是 OpenSSL 输出的日期格式不是 GNU date 默认支持的格式,尤其 GMT 时区缩写和空格分隔易出问题。
实操建议:
- 别硬 parse
openssl x509 -dates输出;改用openssl x509 -in cert.pem -noout -enddate | cut -d= -f2-提取 raw 时间串,再用date -d "$(openssl x509 -in cert.pem -noout -enddate | cut -d= -f2- | sed 's/ */ /g') GMT" +%s 2>/dev/null - 更稳妥的做法是用 Python 一行搞定:
python3 -c "import ssl,datetime; print(ssl._ssl._test_decode_cert('cert.pem')['notAfter'])"(仅限 Python 3.10+,且依赖 OpenSSL 绑定) - 如果只是判断是否快过期,用
openssl x509 -checkend 86400(检查未来 24 小时内是否过期),返回 0 表示即将过期,比自己算时间安全得多
证书过期时间本身是个简单字段,但实际操作中卡点往往不在「怎么看」,而在「看的是不是目标证书」——SNI 漏设、中间证书干扰、PEM 封装错位、时区理解偏差,这些细节一错,查出来的日期就不是你要的那个。


















