HTTPS 证书还剩几天到期?一条 openssl 命令查清,顺手清掉混合内容(2026)

早上打开自己的站,浏览器地址栏冒出个红三角,才知道证书过期了。免费证书现在是 90 天一轮,自动续期大多数时候很安静,失败那次也不会给你发消息,直到访客先撞上警告页。所以别等浏览器提醒,自己查一下还剩多少天,顺手把这步做成一条能跑的检查。

一、先看清楚现在挂的是哪张证书

curl 和 openssl 本地都有,不用登服务器:

echo | openssl s_client -connect www.littlesheep.cc:443 -servername www.littlesheep.cc 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates

我这边跑出来是这样:

subject= /CN=*.littlesheep.cc
issuer= /C=US/O=Let's Encrypt/CN=YR1
notBefore=Sep 18 19:48:03 2026 GMT
notAfter=Dec 17 19:48:02 2026 GMT

通配符证书,Let's Encrypt 签的,12 月 17 日到期,写这篇的时候还剩 82 天。-servername 别省,一台服务器挂多个域名时它决定握手带哪个 SNI,不带你拿到的是默认站点那张证书,跟你要查的域名可能毫无关系。

只想判断「有没有进危险期」更省事,openssl 自己会算:

echo | openssl s_client -connect www.littlesheep.cc:443 -servername www.littlesheep.cc 2>/dev/null \
  | openssl x509 -noout -checkend 604800

-checkend 后面是秒数,问的是证书在这些秒内会不会过期。真正有用的是退出码:0 表示没到期,1 表示会在 604800 秒(7 天)内到期。刚好能塞进监控脚本的 if 里,不用自己解析日期。

二、把「还剩几天」做成每天跑一次的检查

要算具体天数,先抠出 notAfter:

END=$(echo | openssl s_client -connect www.littlesheep.cc:443 -servername www.littlesheep.cc 2>/dev/null \
  | openssl x509 -noout -enddate | cut -d= -f2)

拿到的是 Dec 17 19:48:02 2026 GMT 这种格式,转时间戳这步各平台写法不同:

# Linux(GNU date)
E=$(date -d "$END" +%s)

# macOS(BSD date)
E=$(date -j -f "%b %d %T %Y %Z" "$END" +%s)

echo $(( (E - $(date +%s)) / 86400 ))

两套我都跑过,同一张证书都算出 82 天。有了天数就能加阈值,低于 15 天就推一条通知,扔进 crontab 每天跑:

0 9 * * * /root/cert-check.sh || curl -s "你的通知接口"

懒得写脚本也行,Uptime Kuma 这类监控自带证书到期提醒,填了 https 地址就会在剩余天数低于阈值时告警,配置方法在用 Docker 搭一套监控告警那篇里。

三、续期:面板点一下,或者 acme.sh / certbot

宝塔面板最省事,网站 → 对应站点 → SSL,里面有续签按钮,不同面板版本位置略有差别,但都能找到。命令行就二选一,webroot 方式不需要停 nginx:

# acme.sh
acme.sh --issue -d littlesheep.cc -d '*.littlesheep.cc' -w /www/wwwroot/littlesheep.cc
acme.sh --install-cert -d littlesheep.cc \
  --key-file /www/server/panel/vhost/cert/littlesheep.cc/privkey.pem \
  --fullchain-file /www/server/panel/vhost/cert/littlesheep.cc/fullchain.pem \
  --reloadcmd "nginx -s reload"
# certbot
certbot certonly --webroot -w /www/wwwroot/littlesheep.cc -d littlesheep.cc -d www.littlesheep.cc \
  --deploy-hook "systemctl reload nginx"
certbot renew --dry-run

域名和路径换成你自己的,我这边 nginx 是 1.21.4,你的环境不一定一样。两个工具有个共同点,续期之后要跑一条 reload:nginx 只在启动或 reload 的时候读证书文件,新证书躺在磁盘上而进程没 reload,访客看到的还是旧那张,过期之后照旧报警。acme.sh 的 --reloadcmd 和 certbot 的 --deploy-hook 就是干这个的,别漏。

四、验证真的换上了

续期完别急着关窗口,把第一节那条 openssl 命令再跑一遍,看 notAfter 有没有往后跳。没变就是没生效,多半漏了 reload,或者证书路径写错了。

还有一层容易漏:站前面挂了 CDN、阿里云 ESA 这类边缘节点,你 openssl 打到的是边缘那张证书,不是源站那张。两边各自有到期时间,源站证书在服务器上续,边缘证书在 CDN 控制台续,只处理一边,另一边的到期时间不会动。

五、顺手清掉混合内容

启用 HTTPS 之后,页面里用 http 加载的图片和脚本会被浏览器直接拦掉,图片不显示、脚本不执行,控制台一片红。grep 一下就知道有没有:

curl -s https://www.littlesheep.cc/ | grep -oE '(src|href)="http://[^"]*"' | sort | uniq -c

我这边只出来两处,都是同一个菜单项指向 http://tool.littlesheep.cc,外链导航,不影响加载,但白给浏览器一条不安全提示不值得。顺便说个噪音:不筛 src=、href= 直接 grep http://,会命中一堆 http://www.w3.org/2000/svg 这种命名空间声明,那是 XML 标识符不是请求,别去改。

存在数据库里的旧链接(文章正文、小工具、主题选项)得用 WP-CLI 批量换,先 dry-run 看报告:

wp search-replace 'http://www.littlesheep.cc' 'https://www.littlesheep.cc' \
  --all-tables --precise --skip-columns=guid --dry-run

匹配条数符合预期,去掉 --dry-run 再跑一次。加 --skip-columns=guid 是为了别动 guid 字段,有些付费主题的授权校验认这个值。这套替换的细节我在 WordPress 搬家加换域名 里写得更全,换域名本质上就是把协议和域名一起替换。

跑 WP-CLI 的时候你可能会看到 Object Cache Pro 报 redis 扩展未加载、已降级到内存缓存,那是命令行环境的正常提示,不影响替换结果。

六、出问题怎么退回去

动证书之前先把两个文件复制一份:

cd /www/server/panel/vhost/cert/littlesheep.cc
cp fullchain.pem fullchain.pem.bak && cp privkey.pem privkey.pem.bak

续期没成功就把 .bak 覆盖回去,再 nginx -t && nginx -s reload。改数据库之前更要备份,wp db export 出一条 sql 就够,全站自动备份那篇里的脚本可以直接用。

证书这东西不出事你永远想不起它,出事那天就是最忙的一天。花十分钟把到期检查挂上,比事后救火便宜太多。

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容