init: 初始化 dpb 桃育种系统代码库
前后端 + 后端 FastAPI 全量源码、部署脚本与文档。
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
"""每日 02:00 数据库备份 job —— 包装 backend/scripts/pg_backup.sh。
|
||||
|
||||
独立脚本可手动/CI 直跑;系统调度经此包装,保证与脚本同一份备份逻辑与轮转策略。
|
||||
Windows 下须显式定位 Git Bash(PATH 里的 bash 可能是 WSL shim,mount/PATH 均不匹配),
|
||||
脚本路径统一转 MSYS /d/... 格式传给子进程。
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# backend/app/utils/backup_job.py → parents[2] = backend/
|
||||
_SCRIPT = Path(__file__).resolve().parents[2] / "scripts" / "pg_backup.sh"
|
||||
|
||||
_GIT_BASH_CANDIDATES = (
|
||||
Path(r"C:\Program Files\Git\bin\bash.exe"),
|
||||
Path(r"C:\Program Files\Git\usr\bin\bash.exe"),
|
||||
)
|
||||
|
||||
|
||||
def _find_git_bash() -> str | None:
|
||||
for cand in _GIT_BASH_CANDIDATES:
|
||||
if cand.exists():
|
||||
return str(cand)
|
||||
return shutil.which("bash")
|
||||
|
||||
|
||||
def _msys_path(p: Path) -> str:
|
||||
"""D:/dpb/... → /d/dpb/...(Git Bash 挂载约定)。"""
|
||||
s = p.as_posix()
|
||||
if len(s) >= 2 and s[1] == ":":
|
||||
return f"/{s[0].lower()}{s[2:]}"
|
||||
return s
|
||||
|
||||
|
||||
async def run_daily_backup() -> bool:
|
||||
"""每日备份:调用 pg_backup.sh(独立脚本,pg_dump 自定义格式 + N 天轮转)。"""
|
||||
script = _SCRIPT
|
||||
if not script.exists():
|
||||
alt = Path.cwd() / "scripts" / "pg_backup.sh"
|
||||
script = alt if alt.exists() else script
|
||||
if not script.exists():
|
||||
logger.error(f"备份脚本不存在: {script}")
|
||||
return False
|
||||
git_bash = _find_git_bash()
|
||||
if not git_bash:
|
||||
logger.error("未找到 Git Bash(C:/Program Files/Git/bin/bash.exe)")
|
||||
return False
|
||||
proc = await asyncio.create_subprocess_exec(
|
||||
git_bash, _msys_path(script),
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE,
|
||||
)
|
||||
stdout, stderr = await proc.communicate()
|
||||
if proc.returncode == 0:
|
||||
logger.info(f"每日备份完成: {stdout.decode().strip()}")
|
||||
return True
|
||||
logger.error(f"每日备份失败(rc={proc.returncode}): {stderr.decode()[:500]}")
|
||||
return False
|
||||
Reference in New Issue
Block a user