本文目录导读:

是的,脚本完全可以自动检测SSL证书的到期时间,这是运维和开发中非常常见的需求,用于提前告警,避免证书过期导致服务不可用。
下面给你介绍几种不同场景下的实现方法,包括命令行工具、Shell脚本和Python脚本。
使用 OpenSSL 命令行工具(Linux/macOS)
这是最直接、最底层的方法。openssl 通常已预装在大多数Linux系统上。
核心命令:
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate
解释:
openssl s_client:模拟SSL/TLS客户端,连接到指定服务器和端口(默认443)。-servername example.com:指定SNI(服务器名称指示),对于多域名服务器是必须的。-connect example.com:443:指定目标主机和端口。
2>/dev/null:丢弃连接过程中的调试信息。openssl x509 -noout -enddate:从获取到的证书中提取并只显示到期日期。
输出示例:
notAfter=Sep 4 23:59:59 2024 GMT
Shell 脚本示例:
这个脚本会检查一个域名,计算剩余天数,并在小于30天时发出警告。
#!/bin/bash
DOMAIN="www.baidu.com" # 替换为你要检查的域名
PORT="443"
WARNING_DAYS=30
# 获取证书到期日期
expiry_date=$(echo | openssl s_client -servername "$DOMAIN" -connect "${DOMAIN}:${PORT}" 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
# 将到期日期转换为时间戳(秒)
expiry_timestamp=$(date -d "$expiry_date" +%s)
# 当前时间戳
current_timestamp=$(date +%s)
# 计算剩余天数
remaining_days=$(( ($expiry_timestamp - $current_timestamp) / 86400 ))
echo "域名: $DOMAIN"
echo "到期日期: $expiry_date"
echo "剩余天数: $remaining_days"
if [ $remaining_days -lt 0 ]; then
echo "⚠️ 严重告警:证书已过期 $((-$remaining_days)) 天!"
elif [ $remaining_days -le $WARNING_DAYS ]; then
echo "⚠️ 警告:证书将在 $remaining_days 天后到期,请尽快更新!"
else
echo "✅ 证书状态正常。"
fi
优点: 无需安装任何额外软件,效率高。 缺点: 解析文本输出较为笨拙。
使用 Python 脚本
Python 的 ssl 和 socket 库功能强大,处理日期更方便。
前提条件: 确保安装了 python3。
Python 脚本示例:
import ssl
import socket
import datetime
from dateutil import parser as dateparser # 更健壮的日期解析
def check_ssl_expiry(hostname, port=443):
"""检查指定主机SSL证书到期时间"""
context = ssl.create_default_context()
try:
# 建立连接并获取证书
with socket.create_connection((hostname, port), timeout=5) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
cert = ssock.getpeercert() # 获取证书信息(字典)
# 获取到期日期(格式:'Sep 4 23:59:59 2024 GMT')
expiry_str = cert['notAfter']
print(f"原始到期时间字符串: {expiry_str}")
# 解析为datetime对象
expiry_date = dateparser.parse(expiry_str)
now = datetime.datetime.now(expiry_date.tzinfo) # 使用时区一致的时间
# 计算剩余天数
remaining_days = (expiry_date - now).days
print(f"域名: {hostname}")
print(f"到期日期: {expiry_date}")
print(f"剩余天数: {remaining_days}")
if remaining_days < 0:
print("⚠️ 严重告警:证书已过期!")
elif remaining_days < 30:
print(f"⚠️ 警告:证书将在 {remaining_days} 天后到期。")
else:
print("✅ 证书状态正常。")
except socket.gaierror:
print(f"❌ 错误:无法解析域名 {hostname}")
except ssl.SSLError as e:
print(f"❌ 错误:SSL连接问题 - {e}")
except socket.timeout:
print(f"❌ 错误:连接超时")
except Exception as e:
print(f"❌ 未知错误:{e}")
# 使用示例
if __name__ == "__main__":
check_ssl_expiry("www.baidu.com")
优点:
- 结果干净、结构化(字典),易于处理。
- 日期计算方便。
- 易于集成到更大的监控系统。
缺点: 需要运行环境。
批量检查(多个域名)
你可以将上面的脚本封装起来,读取一个 domains.txt 文件,实现批量检查。
Shell 版本(读取文件)
#!/bin/bash
WARNING_DAYS=30
while IFS= read -r domain; do
if [ -z "$domain" ]; then # 跳过空行
continue
fi
echo "正在检查: $domain"
# 复用上面单域名检查的代码,或直接调用openssl命令
# (为了简洁,这里只展示框架)
echo "到期日期: $(echo | openssl s_client -servername "$domain" -connect "$domain:443" 2>/dev/null | openssl x509 -noout -enddate)"
echo "---"
done < "domains.txt"
Python 版本(调用函数)
# 假设 check_ssl_expiry 函数已定义
domains = ["www.baidu.com", "www.google.com", "github.com"]
for domain in domains:
check_ssl_expiry(domain)
print("-" * 20)
总结与建议
- 最灵活/推荐:使用Python脚本。 如果你需要频繁检查、解析日期、发送告警(邮件、钉钉、Slack)、记录日志,Python 是最好选择。
- 最简单/轻量:使用OpenSSL一行的Shell命令。 适合偶尔手动检查,或者集成到简单的cron任务中,直接发送一个告警文本。
- 生产环境:使用专用工具。
- Certbot/cert-manager:如果你的证书是自动续签的(如Let‘s Encrypt),它们自己会处理到期检查。
- 商用监控软件(如Nagios、Zabbix、Prometheus + blackbox exporter):它们都有成熟的SSL证书监控插件,功能强大,有图形界面和告警历史。
- 在线服务:很多网站提供免费的SSL证书到期监控,会通过邮件通知你。
安全性提醒: 你的脚本会连接到目标服务器,确保目标服务器是可信任的,并且在可控制的环境下运行,避免被恶意中间人攻击。