Shell脚本监控SSL证书到期,提前邮件告警
网站启用HTTPS后,SSL证书一旦过期,浏览器就会弹出安全警告,用户无法正常访问。
手动记录到期时间容易遗忘,用Shell脚本自动检查并提前邮件告警,是运维中非常实用的做法。
下面从零开始,一步步带你完成脚本编写、邮件配置和定时任务,最终实现证书到期前自动发邮件提醒。
检查环境与准备工具
先确认服务器上已安装 openssl 和 mailx(或 sendmail)。
大多数Linux发行版自带openssl,用以下命令验证:
openssl version
mailx -V
如果提示命令不存在,按系统安装:
- CentOS/RHEL:
yum install -y openssl mailx - Ubuntu/Debian:
apt install -y openssl mailutils
邮件发送需要配置SMTP。
如果服务器没有本地邮件服务,建议使用外部SMTP(如企业邮箱),通过mailx配置文件指定发件服务器。
编辑/etc/mail.rc,在末尾加入(以腾讯企业邮为例):
set from=your@company.com
set smtp=smtp.exmail.qq.com:465
set smtp-auth-user=your@company.com
set smtp-auth-password=你的授权码
set smtp-auth=login
set ssl-verify=ignore
注意:密码处填写邮箱的授权码,不是登录密码。
保存后可用echo "test" | mail -s "测试" your@company.com测试,收到邮件说明配置成功。
编写证书检查脚本
脚本核心逻辑:用openssl s_client连接目标域名,获取证书的到期时间,计算剩余天数,若小于阈值则发送邮件。
创建脚本文件/opt/check_ssl.sh,内容如下:
#!/bin/bash
# 需要监控的域名列表,每行一个
DOMAINS=("www.example.com" "api.example.com")
# 告警阈值(天)
THRESHOLD=15
# 收件人
MAIL_TO="admin@example.com"
for domain in "${DOMAINS[@]}"; do
# 获取证书到期时间(GMT格式)
end_date=$(echo | openssl s_client -servername "$domain" -connect "$domain:443" 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
if [ -z "$end_date" ]; then
echo "无法获取 $domain 的证书信息" | mail -s "SSL证书检查失败: $domain" "$MAIL_TO"
continue
fi
# 转换为时间戳
end_timestamp=$(date -d "$end_date" +%s)
now_timestamp=$(date +%s)
# 计算剩余天数
remain_days=$(( (end_timestamp - now_timestamp) / 86400 ))
if [ "$remain_days" -lt "$THRESHOLD" ]; then
echo "$domain 的SSL证书剩余 $remain_days 天,请及时续期。" | mail -s "SSL证书到期告警: $domain" "$MAIL_TO"
fi
done
给脚本加执行权限:chmod +x /opt/check_ssl.sh。
手动运行/opt/check_ssl.sh测试,若证书即将到期或已到期,你应该会收到告警邮件。
关键点:openssl s_client 命令中的 -servername 参数用于SNI,对于多个域名共用IP的情况必须指定,否则可能获取到默认证书。
设置定时任务自动执行
用crontab每天检查一次。
执行crontab -e,添加一行:
0 8 * * * /bin/bash /opt/check_ssl.sh >/dev/null 2>&1
这表示每天上午8点运行脚本。
保存后可以用crontab -l查看是否添加成功。
建议先手动执行一次脚本,确认邮件能正常发出,再交给crontab。
如果脚本中使用了环境变量(如自定义PATH),在crontab中最好写绝对路径,或者直接在脚本开头source /etc/profile。
常见问题与避坑指南
邮件发送失败:检查/etc/mail.rc配置,确认SMTP地址、端口、授权码正确。
如果使用465端口,确保set ssl-verify=ignore已设置。
查看邮件日志tail -f /var/log/maillog(CentOS)或/var/log/mail.log(Ubuntu)定位错误。
证书信息获取为空:可能是网络不通、域名解析错误或端口非443。
先用openssl s_client -connect 域名:端口手动测试。
如果服务器无法直接访问外网,需要配置代理。
剩余天数计算为负数:说明证书已过期,脚本会正常发出告警,但此时网站已经不可用,建议将阈值设置得大一些(如30天),并确保续期流程及时。
多域名管理:脚本中DOMAINS数组可以添加多个域名,每行一个用空格分隔。
如果域名很多,可以考虑将域名列表放在单独文件里,用while read循环读取。
证书链问题:某些情况下openssl x509可能只获取到中间证书,导致到期时间不准确。
可以用-showcerts参数检查完整链,但通常enddate取的是服务器返回的第一个证书的到期时间,对监控来说足够。
验证告警是否生效
临时把THRESHOLD改为一个很大的值(如365),运行脚本,看是否收到邮件。
收到后改回原值。
也可以直接查看邮件日志,确认脚本执行记录。
如果希望更直观,可以在脚本中加入日志输出,例如每次检查后记录域名和剩余天数到/var/log/ssl_check.log,方便后续排查。
最后提醒:证书到期前一周才告警可能来不及处理,建议根据续期流程的耗时设置阈值,一般15-30天比较稳妥。
定期检查脚本是否正常运行,避免因为服务器重启或crontab被清理导致监控失效。