修复
This commit is contained in:
+67
-1
@@ -1,14 +1,16 @@
|
||||
from contextlib import asynccontextmanager
|
||||
from pathlib import Path
|
||||
import logging
|
||||
import asyncio
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.responses import FileResponse
|
||||
from starlette.requests import Request
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
|
||||
from backend.database import init_db
|
||||
from backend.database import init_db, async_session
|
||||
from backend.routers import api, admin
|
||||
from backend.config import get_settings
|
||||
from backend.bootstrap import ensure_self_signed_cert
|
||||
@@ -25,12 +27,75 @@ from backend.routers.admin import (
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logger = logging.getLogger("certcenter")
|
||||
|
||||
scheduler = AsyncIOScheduler()
|
||||
|
||||
|
||||
async def auto_renew_job():
|
||||
"""定时任务:自动续签即将过期的证书"""
|
||||
from backend.routers.admin import _get_domain_acme_config
|
||||
from backend.models import Domain, AcmeLog
|
||||
from backend.acme_service import AcmeService
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import selectinload
|
||||
from datetime import datetime
|
||||
|
||||
logger.info("[定时任务] 开始检查证书续签...")
|
||||
try:
|
||||
async with async_session() as db:
|
||||
settings = get_settings()
|
||||
result = await db.execute(select(Domain).options(selectinload(Domain.acme_config)))
|
||||
domains = result.scalars().all()
|
||||
|
||||
renewed = 0
|
||||
for d in domains:
|
||||
try:
|
||||
config = await _get_domain_acme_config(d, db)
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
service = AcmeService(config, settings.cert_dir)
|
||||
need_renew, days_left = service.check_expiry(d.domain)
|
||||
if not need_renew:
|
||||
continue
|
||||
|
||||
logger.info(f"[定时任务] {d.domain} 需要续签(剩余 {days_left} 天)")
|
||||
log = AcmeLog(domain_id=d.id, action="renew", status="pending", message=f"自动续签 {d.domain}")
|
||||
db.add(log)
|
||||
await db.flush()
|
||||
|
||||
try:
|
||||
success, msg = service.renew_certificate(d.domain)
|
||||
log.status = "success" if success else "failed"
|
||||
log.message = msg
|
||||
if success:
|
||||
info = service.get_cert_info(d.domain)
|
||||
if info:
|
||||
d.cert_not_after = datetime.fromisoformat(info["not_after"])
|
||||
d.version = str(int(d.version or "0") + 1)
|
||||
renewed += 1
|
||||
logger.info(f"[定时任务] {d.domain}: {'成功' if success else '失败'} - {msg}")
|
||||
except Exception as e:
|
||||
log.status = "failed"
|
||||
log.message = str(e)
|
||||
logger.error(f"[定时任务] {d.domain} 续签异常: {e}")
|
||||
|
||||
await db.commit()
|
||||
logger.info(f"[定时任务] 检查完成,续签 {renewed} 个证书")
|
||||
except Exception as e:
|
||||
logger.error(f"[定时任务] 执行异常: {e}")
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
await init_db()
|
||||
settings = get_settings()
|
||||
ensure_self_signed_cert(settings.base_url, settings.cert_dir)
|
||||
|
||||
# 启动定时续签任务(每天凌晨3点执行)
|
||||
scheduler.add_job(auto_renew_job, "cron", hour=3, minute=0, id="auto_renew", replace_existing=True)
|
||||
scheduler.start()
|
||||
logger.info("=== 定时续签任务已启动(每天 03:00) ===")
|
||||
|
||||
logger.info("=== 服务启动完成 ===")
|
||||
# 打印所有已注册的路由
|
||||
for route in app.routes:
|
||||
@@ -41,6 +106,7 @@ async def lifespan(app: FastAPI):
|
||||
else:
|
||||
logger.info(f" [included router] {type(route).__name__}")
|
||||
yield
|
||||
scheduler.shutdown()
|
||||
|
||||
|
||||
app = FastAPI(title="CertCenter", version="1.0.0", lifespan=lifespan)
|
||||
|
||||
Reference in New Issue
Block a user