**注意: ** acme.sh默认自带续期功能,前提是不要自己调整证书路径!
免费证书都是3个月到期,需要手动续期,所以写了一个监控加自动续期的服务,有兴趣的可以试一试
import ssl
import socket
import requests
import schedule
import time
from datetime import datetime
import subprocess
# Telegram Bot设置
TELEGRAM_TOKEN = ''
TELEGRAM_CHAT_ID = ''
# 储存域名列表
domains = [
'tool.wangwangit.com'
]
def send_telegram_message(message):
url = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage"
data = {
"chat_id": TELEGRAM_CHAT_ID,
"text": message
}
requests.post(url, data=data)
def get_ssl_expiry_date_from_shell(hostname, port=443):
cmd = f"echo | openssl s_client -servername {hostname} -connect \"{hostname}:{port}\" 2>/dev/null | openssl x509 -noout -dates"
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = process.communicate()
if process.returncode != 0:
return f"Error executing command: {err.decode().strip()}"
return out.decode().strip()
def renew_ssl(domain):
subprocess.run(['nginx', '-s', 'stop'])
time.sleep(10) # 等待nginx停止
subprocess.run(['acme.sh', '--issue', '-d', domain, '--standalone', '--force'])
time.sleep(30) # 等待证书申请
subprocess.run(['nginx'])
subprocess.run(['nginx', '-s', 'reload'])
time.sleep(10) # 等待nginx重启
def format_expiry_date(date_str):
try:
# 提取日期字符串并转换为datetime对象
expiry_date = datetime.strptime(date_str, '%b %d %H:%M:%S %Y %Z')
# 返回格式化的日期字符串
return expiry_date.strftime('%Y-%m-%d %H:%M:%S')
except ValueError:
return date_str # 返回原始字符串,如果格式不匹配
def check_all_domains():
messages = []
for domain in domains:
ssl_dates = get_ssl_expiry_date_from_shell(domain)
expiry_date_line = ssl_dates.split('\n')[1] if 'notAfter' in ssl_dates else ssl_dates
expiry_date = expiry_date_line.split('=')[1] if 'notAfter' in expiry_date_line else "Unknown"
formatted_date = format_expiry_date(expiry_date)
if "Error" in ssl_dates or "Unknown" in expiry_date:
message = f"{domain} SSL证书检查失败:{formatted_date},请手动检查。"
messages.append(message)
else:
message = f"{domain} SSL证书状态正常,有效期至 {formatted_date}。"
messages.append(message)
# 将所有消息发送到Telegram
send_telegram_message("\n".join(messages))
# 设置定时任务
schedule.every().day.at("10:00").do(check_all_domains)
# 运行定时任务
while True:
schedule.run_pending()
time.sleep(1)
运行情况如下: