修复中控自更新触发与错误提示;实例页改为表格,带鱼屏宽度锁 1800。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-04 07:44:12 +08:00
parent 2e460efb73
commit 5b4e35c582
8 changed files with 303 additions and 190 deletions
+81 -22
View File
@@ -13,6 +13,7 @@ from typing import Any
_ROOT = Path(__file__).resolve().parent.parent
_update_lock = threading.Lock()
_update_pending_until = 0.0
_UPDATE_LOG = _ROOT / "logs" / "hub_update.log"
def _repo_root() -> Path:
@@ -41,6 +42,15 @@ def _run_git(args: list[str], *, cwd: Path) -> tuple[bool, str]:
return proc.returncode == 0, out
def _append_log(line: str) -> None:
try:
_UPDATE_LOG.parent.mkdir(parents=True, exist_ok=True)
with open(_UPDATE_LOG, "a", encoding="utf-8") as f:
f.write(time.strftime("%Y-%m-%d %H:%M:%S") + " " + line + "\n")
except Exception:
pass
def read_git_version() -> dict[str, Any]:
root = _repo_root()
out: dict[str, Any] = {
@@ -52,6 +62,7 @@ def read_git_version() -> dict[str, Any]:
"dirty": False,
"msg": "",
"online": True,
"platform": sys.platform,
}
if not (root / ".git").exists() and not (root / ".git").is_file():
out["ok"] = False
@@ -73,35 +84,83 @@ def read_git_version() -> dict[str, Any]:
return out
def schedule_pull_and_restart(*, delay_seconds: float = 1.5) -> dict[str, Any]:
def _run_pull_and_restart(root: Path, script: Path) -> None:
log_path = _UPDATE_LOG
try:
log_path.parent.mkdir(parents=True, exist_ok=True)
except Exception:
pass
env = os.environ.copy()
env["REPO"] = str(root)
if not (env.get("PM2_APP_NAME") or "").strip():
env["PM2_APP_NAME"] = "crypto_okx_hub"
try:
with open(log_path, "a", encoding="utf-8") as logf:
logf.write(
time.strftime("%Y-%m-%d %H:%M:%S")
+ f" start pull_and_restart REPO={root}\n"
)
logf.flush()
proc = subprocess.run(
["bash", str(script)],
cwd=str(root),
env=env,
stdout=logf,
stderr=subprocess.STDOUT,
text=True,
timeout=180,
)
logf.write(
time.strftime("%Y-%m-%d %H:%M:%S")
+ f" finish returncode={proc.returncode}\n"
)
except Exception as e:
_append_log("pull_and_restart error: " + (str(e) or "unknown"))
def schedule_pull_and_restart(*, delay_seconds: float = 2.0) -> dict[str, Any]:
if not sys.platform.startswith("linux"):
return {"ok": False, "msg": "仅 Linux 服务器支持更新", "deferred": False}
msg = f"仅 Linux 服务器支持更新(当前 platform={sys.platform})"
_append_log("reject: " + msg)
return {"ok": False, "msg": msg, "deferred": False, "platform": sys.platform}
root = _repo_root()
script = root / "deploy" / "pull_and_restart.sh"
if not script.is_file():
return {"ok": False, "msg": f"缺少更新脚本: {script}", "deferred": False}
msg = f"缺少更新脚本: {script}"
_append_log("reject: " + msg)
return {"ok": False, "msg": msg, "deferred": False}
if not (root / "ecosystem.config.cjs").is_file():
msg = f"缺少 ecosystem.config.cjs: {root}"
_append_log("reject: " + msg)
return {"ok": False, "msg": msg, "deferred": False}
global _update_pending_until
now = time.time()
with _update_lock:
if now < _update_pending_until:
return {"ok": False, "msg": "已有更新任务进行中,请稍后再试", "deferred": False}
_update_pending_until = now + 120.0
msg = "已有更新任务进行中,请稍后再试"
return {"ok": False, "msg": msg, "deferred": False}
_update_pending_until = now + 180.0
version = read_git_version()
delay = max(1.0, float(delay_seconds))
def _worker() -> None:
try:
time.sleep(delay)
_run_pull_and_restart(root, script)
finally:
with _update_lock:
# 保留短暂冷却,避免连点
pass
try:
delay = max(0.5, float(delay_seconds))
cmd = (
f"sleep {delay} && "
f"cd {shlex.quote(str(root))} && "
f"exec bash {shlex.quote(str(script))}"
)
subprocess.Popen(
["bash", "-c", cmd],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
start_new_session=True,
cwd=str(root),
t = threading.Thread(target=_worker, name="hub-self-update", daemon=True)
t.start()
_append_log(
f"accepted before={version.get('short_sha') or ''} delay={delay}s root={root}"
)
return {
"ok": True,
@@ -110,12 +169,12 @@ def schedule_pull_and_restart(*, delay_seconds: float = 1.5) -> dict[str, Any]:
"before_sha": version.get("sha") or "",
"before_short_sha": version.get("short_sha") or "",
"branch": version.get("branch") or "",
"repo": str(root),
"log": str(_UPDATE_LOG),
}
except FileNotFoundError:
with _update_lock:
_update_pending_until = 0.0
return {"ok": False, "msg": "未找到 bash", "deferred": False}
except Exception as e:
with _update_lock:
_update_pending_until = 0.0
return {"ok": False, "msg": str(e) or "触发更新失败", "deferred": False}
msg = str(e) or "触发更新失败"
_append_log("reject: " + msg)
return {"ok": False, "msg": msg, "deferred": False}