Shell脚本监控SSL证书到期,提前邮件告警提醒
SSL证书一旦过期,网站会直接报错或无法访问,用户流失和业务中断往往就在一瞬间。
本文提供一套Shell脚本方案,自动检查证书剩余有效期,并在到期前通过邮件发出告警提醒。
整个流程零基础也能照做,最终你会得到一个每天定时运行、结果可验证的监控任务。
需要提前准备的环境和工具
开始之前,确认服务器上已经具备以下条件:
- 一台能访问目标域名的Linux服务器(本地或远程均可)。
- 已安装
openssl和curl,绝大多数发行版默认自带。 - 一个可用于发送邮件的SMTP邮箱账号,比如QQ邮箱、163邮箱或企业邮箱。
- 基本的文本编辑能力,会用
vi或nano即可。
如果服务器没有openssl,可以用包管理器安装。
例如在CentOS上执行yum install -y openssl,在Ubuntu/Debian上执行apt install -y openssl。
邮件发送工具推荐使用mailx或sendmail,但更简单的方式是直接用curl调用SMTP服务。
下文会给出具体命令。
获取证书到期时间的正确方法
监控的第一步是准确拿到证书的到期时间。
不要依赖浏览器显示,直接用命令行获取:
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate
把example.com替换成你的实际域名。
执行后会输出类似notAfter=Jun 15 12:00:00 2025 GMT的结果,这就是证书的到期时间。
注意:如果域名使用了CDN或反向代理,证书可能由CDN提供,这时监控源站证书没有意义,应改为监控CDN上的证书。
拿到到期时间后,需要把它转换成剩余天数。
可以用date命令计算:
expire_date=$(echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
expire_ts=$(date -d "$expire_date" +%s)
now_ts=$(date +%s)
days_left=$(( (expire_ts - now_ts) / 86400 ))
echo "剩余天数: $days_left"
这段命令会输出证书距离过期还有多少天。86400是一天的秒数。
编写监控脚本并加入邮件告警
新建一个脚本文件,比如/opt/ssl_monitor.sh,内容如下:
#!/bin/bash
# 要监控的域名列表,每行一个
DOMAINS=(
"example.com"
"www.example.com"
)
# 提前多少天开始告警
WARN_DAYS=15
# 收件人邮箱
MAIL_TO="your_email@example.com"
# SMTP配置(以QQ邮箱为例)
SMTP_SERVER="smtp.qq.com"
SMTP_PORT="465"
SMTP_USER="your_email@qq.com"
SMTP_PASS="你的授权码"
for domain in "${DOMAINS[@]}"; do
expire_date=$(echo | openssl s_client -servername "$domain" -connect "$domain:443" 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
if [ -z "$expire_date" ]; then
echo "无法获取 $domain 的证书信息"
continue
fi
expire_ts=$(date -d "$expire_date" +%s)
now_ts=$(date +%s)
days_left=$(( (expire_ts - now_ts) / 86400 ))
if [ "$days_left" -le "$WARN_DAYS" ]; then
subject="SSL证书告警: $domain 剩余 $days_left 天"
body="域名 $domain 的SSL证书将于 $expire_date 过期,剩余 $days_left 天,请及时续期。"
curl -s --url "smtps://$SMTP_SERVER:$SMTP_PORT" --ssl-reqd \
--mail-from "$SMTP_USER" \
--mail-rcpt "$MAIL_TO" \
--user "$SMTP_USER:$SMTP_PASS" \
-T <(echo -e "From: $SMTP_USER\nTo: $MAIL_TO\nSubject: $subject\n\n$body")
fi
done
保存后赋予执行权限:
chmod +x /opt/ssl_monitor.sh
关键点:SMTP_PASS通常不是邮箱登录密码,而是邮箱服务商提供的授权码。
以QQ邮箱为例,需要在设置中开启SMTP服务并生成授权码。
设置定时任务让脚本自动运行
手动执行一次脚本,确认能正常获取到期天数且邮件能发出:
/opt/ssl_monitor.sh
如果收到测试邮件,说明配置正确。
接着用crontab设置每天自动运行:
crontab -e
加入一行:
0 9 * * * /bin/bash /opt/ssl_monitor.sh >/dev/null 2>&1
这表示每天上午9点执行一次。>/dev/null 2>&1用于丢弃正常输出,避免产生大量日志。
避坑提示:
- 脚本中的域名列表要用数组格式,每行一个,不要用逗号分隔。
- 如果服务器无法解析域名,检查
/etc/resolv.conf中的DNS配置。 - 邮件发送失败时,先用
curl命令单独测试SMTP连通性,确认端口和授权码无误。 - 部分云服务器默认封禁25端口,建议使用465或587端口。
验证监控是否真正生效
脚本部署后,需要确认它确实在工作。
可以临时把WARN_DAYS改成一个很大的值,比如365,这样所有域名都会触发告警,方便测试邮件发送流程。
测试完成后记得改回合理数值。
另外,查看crontab日志确认任务执行情况:
grep CRON /var/log/syslog
或者查看/var/log/cron(CentOS系)。
如果日志中没有报错,且收到了告警邮件,说明整个监控链路已经跑通。
建议每月手动检查一次证书剩余天数,与脚本输出对比,确保结果一致。
证书续期后,脚本会自动更新剩余天数,无需额外调整。
常见疑问
脚本能监控多个域名吗?
可以。在DOMAINS数组中添加域名即可,每个域名会独立检查并发送告警。
邮件收不到怎么办?
先检查垃圾邮件箱,再确认授权码是否正确、SMTP端口是否被防火墙拦截。用telnet smtp.qq.com 465测试连通性。
证书续期后还需要改脚本吗?
不需要。脚本每次运行都会重新获取证书到期时间,续期后剩余天数会自动增加。
可以用企业微信或钉钉告警代替邮件吗?
可以。把curl发送邮件的部分替换为调用企业微信机器人或钉钉Webhook的API即可,原理相同。