""" 快速部署问卷更新 v2 — 只重启后端 """ import paramiko, base64, tarfile, io, time NAS_HOST = "100.85.152.112" NAS_PORT = 22 NAS_USER = "simon" NAS_PASS = "Nas82829330" NAS_DEPLOY_PATH = "/volume1/docker/gaokao-portal" DOCKER = f"echo '{NAS_PASS}' | sudo -S /usr/local/bin/docker" def run_cmd(client, cmd, desc="", timeout=30): if desc: print(f"[{desc}]") stdin, stdout, stderr = client.exec_command(cmd, timeout=timeout) # 先等一下 time.sleep(1) # 用非阻塞方式读 ch = stdout.channel out = b"" while True: if ch.recv_ready(): out += ch.recv(4096) if ch.exit_status_ready(): break time.sleep(0.2) # 读完 while ch.recv_ready(): out += ch.recv(4096) out_str = out.decode("utf-8", errors="replace").strip() err_str = stderr.read().decode("utf-8", errors="replace").strip() if out_str: for line in out_str.split("\n")[:5]: print(f" > {line}") return out_str, err_str, ch.recv_exit_status() # 打包 seed_data.py buf = io.BytesIO() with tarfile.open(fileobj=buf, mode="w:gz") as tar: tar.add("C:/Users/simon/WorkBuddy/2026-05-20-15-22-53/deploy/backend/seed_data.py", arcname="seed_data.py") tar_data = buf.getvalue() b64 = base64.b64encode(tar_data).decode("ascii") # 连接 client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(NAS_HOST, NAS_PORT, NAS_USER, NAS_PASS, timeout=20) print("部署新问卷...") transport = client.get_transport() # 1. 上传新 seed_data.py ch = transport.open_session() ch.exec_command("base64 -d > /tmp/seed_new.py") ch.sendall(b64.encode()) ch.shutdown_write() time.sleep(2) ch.recv_exit_status() # 2. 备份+替换 run_cmd(client, f"cp {NAS_DEPLOY_PATH}/backend/seed_data.py {NAS_DEPLOY_PATH}/backend/seed_data.py.bak", "备份") run_cmd(client, f"cp /tmp/seed_new.py {NAS_DEPLOY_PATH}/backend/seed_data.py", "替换") # 3. 只重启后端容器(nginx 不需要动) run_cmd(client, f"cd {NAS_DEPLOY_PATH} && {DOCKER} compose restart backend", "重启后端", timeout=60) # 等待后端启动 print("等待后端...") time.sleep(8) # 4. 验证 out, _, _ = run_cmd(client, f"curl -s http://localhost:8080/api/questionnaires", "验证问卷", timeout=15) print(f" API 返回: {out[:200]}...") # 清理 run_cmd(client, "rm -f /tmp/seed_new.py", "清理") print("\n完成!刷新问卷页面。") client.close()