80 lines
2.4 KiB
Python
80 lines
2.4 KiB
Python
|
|
"""
|
||
|
|
快速部署问卷更新 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()
|