HTTPS证书过期自动检测脚本,提前告警提醒
HTTPS证书一旦过期,浏览器会直接拦截访问,用户看到的是红色警告页。
本文提供一个可直接运行的Shell检测脚本,自动读取证书到期时间,并在剩余天数低于设定阈值时通过邮件或企业微信发出告警。
适合所有维护HTTPS站点的零基础运维人员,跟着操作即可完成配置。
准备检测环境和依赖
先确认服务器上已安装openssl和curl,绝大多数Linux发行版默认自带:
openssl version
curl --version
如果提示命令不存在,用系统包管理器安装即可。
以Ubuntu/Debian为例:
apt update && apt install -y openssl curl
脚本还需要一个存放日志和状态文件的目录,建议统一放在/opt/cert-check/下:
mkdir -p /opt/cert-check/logs
告警方式二选一:邮件需要mailx或sendmail,企业微信只需一个Webhook地址。
下面脚本默认使用企业微信机器人,邮件方式在注释中说明替换点。
编写证书过期检测脚本
创建脚本文件/opt/cert-check/check_cert.sh,内容如下:
#!/bin/bash
# 需要检测的域名列表,每行一个
DOMAINS=(
"www.example.com"
"api.example.com"
)
# 剩余天数低于此值触发告警
THRESHOLD=15
# 企业微信机器人Webhook
WEBHOOK="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的KEY"
LOG="/opt/cert-check/logs/cert.log"
for domain in "${DOMAINS[@]}"; do
end_date=$(echo | openssl s_client -servername "$domain" -connect "$domain:443" 2>/dev/null \
| openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
if [ -z "$end_date" ]; then
msg="证书检测失败:$domain 无法获取证书信息"
echo "$(date '+%F %T') $msg" >> "$LOG"
continue
fi
end_ts=$(date -d "$end_date" +%s)
now_ts=$(date +%s)
days_left=$(( (end_ts - now_ts) / 86400 ))
echo "$(date '+%F %T') $domain 剩余 $days_left 天" >> "$LOG"
if [ "$days_left" -lt "$THRESHOLD" ]; then
alert="【HTTPS证书告警】$domain 证书剩余 $days_left 天,请尽快续期"
curl -s -X POST "$WEBHOOK" \
-H 'Content-Type: application/json' \
-d "{\"msgtype\":\"text\",\"text\":{\"content\":\"$alert\"}}" >/dev/null
fi
done
关键点说明:
DOMAINS数组里替换成你实际要监控的域名,支持多个。THRESHOLD=15表示剩余不足15天就告警,可按需改成30或7。- 使用
openssl s_client -servername是为了正确处理SNI,避免多域名共用IP时取错证书。 date -d在CentOS 7+和Ubuntu 18.04+均可用,老系统如CentOS 6需改用date --date。
保存后赋予执行权限:
chmod +x /opt/cert-check/check_cert.sh
手动运行一次验证输出:
/opt/cert-check/check_cert.sh
cat /opt/cert-check/logs/cert.log
日志中应出现每个域名的剩余天数。
如果某个域名显示“无法获取证书信息”,先用浏览器访问该域名确认HTTPS是否正常。
配置定时任务与告警验证
用crontab -e添加定时任务,每天上午9点执行一次:
0 9 * * * /bin/bash /opt/cert-check/check_cert.sh
保存后确认任务已生效:
crontab -l
验证告警是否可达:临时把THRESHOLD改成一个很大的值,例如9999,手动执行脚本,企业微信应收到测试消息。
确认后再改回正常阈值。
如果使用邮件告警,把curl那行替换为:
echo "$alert" | mail -s "HTTPS证书告警" your@email.com
注意:邮件方式需要服务器已配置可用的MTA,否则邮件会静默失败。
建议先用命令行发一封测试邮件确认。
避坑指南与常见问题
坑1:openssl取到的是负载均衡或CDN的证书。
如果域名走了CDN,脚本检测的是CDN节点证书,而非源站。
这种情况需将-connect指向源站IP加端口,例如-connect 1.2.3.4:443,同时保留-servername。
坑2:证书链不完整导致检测失败。
部分服务器只配置了站点证书未配中间证书,openssl s_client可能返回异常。
可加-showcerts参数排查,或在Nginx中补全ssl_certificate文件。
坑3:cron环境变量缺失。
脚本中所有命令尽量用绝对路径,或在cron任务开头添加PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin。
坑4:告警被忽略。
建议设置两级阈值,例如剩余30天发提醒、剩余7天发紧急告警,避免单次告警被淹没。
坑5:多域名漏检。
新增站点后记得同步更新DOMAINS数组,可以结合配置管理工具或从Nginx配置中自动提取域名列表。
效果检查与后续维护
运行一周后,检查日志文件是否每天都有记录:
tail -n 20 /opt/cert-check/logs/cert.log
如果日志为空,说明cron未执行或脚本路径有误,用grep CRON /var/log/syslog(Ubuntu)或/var/log/cron(CentOS)排查。
证书续期后,手动执行一次脚本,确认剩余天数已更新为新的有效期。
建议把脚本和域名列表纳入版本管理,服务器迁移时直接复用。
对于使用宝塔面板的用户,也可以在面板的“计划任务”中添加Shell脚本任务,执行周期选择每天,脚本内容粘贴上述代码即可,效果与cron一致。
整体来看,这套方案不依赖额外服务,一台普通VPS即可运行,维护成本低,能有效避免因证书过期导致的访问中断。