b6df028839
变更摘要: - [fix] 清理根目录 index.html 遗留代码(questionnaire-error + retryLoad 移除) - [fix] 副标题同步更新为自估591分 + 候选志愿546条数据校准 - [fix] 页脚注入版本号 v1.0.0 - [fix] 部署版 index.html: 取消家长标签,统一 filler-tianheng - [fix] Dashboard 文案修正(4份→2份线上问卷) - [fix] 清理冗余部署脚本(v1-v4归档至 archived_scripts/) - [fix] 等效位次工具纳入 deploy 目录 - [chore] .gitignore 初始化 - [init] Git 仓库初始化
91 lines
2.8 KiB
Python
91 lines
2.8 KiB
Python
"""
|
|
快速部署问卷更新到 NAS
|
|
"""
|
|
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)
|
|
out = stdout.read().decode("utf-8", errors="replace").strip()
|
|
err = stderr.read().decode("utf-8", errors="replace").strip()
|
|
status = stdout.channel.recv_exit_status()
|
|
if out:
|
|
for line in out.split("\n")[:5]:
|
|
print(f" > {line}")
|
|
if err and status != 0:
|
|
for line in err.split("\n")[:3]:
|
|
print(f" ! {line}")
|
|
return out, err, status
|
|
|
|
def run_stdin(client, cmd, data, desc=""):
|
|
if desc:
|
|
print(f"[{desc}]")
|
|
transport = client.get_transport()
|
|
ch = transport.open_session()
|
|
ch.exec_command(cmd)
|
|
ch.sendall(data)
|
|
ch.shutdown_write()
|
|
while not ch.exit_status_ready():
|
|
time.sleep(0.1)
|
|
out = ch.recv(4096).decode()
|
|
err = ch.recv_stderr(4096).decode()
|
|
status = ch.recv_exit_status()
|
|
print(f" 传输完成,退出码 {status}")
|
|
return out, err, status
|
|
|
|
# 打包
|
|
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)
|
|
|
|
print("=" * 50)
|
|
print("部署问卷更新")
|
|
print("=" * 50)
|
|
|
|
# 1. 上传
|
|
run_stdin(client, "base64 -d > /tmp/seed_data.py", b64, "上传")
|
|
|
|
# 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_data.py {NAS_DEPLOY_PATH}/backend/seed_data.py", "替换新文件")
|
|
|
|
# 3. 重建容器(重新运行 seed)
|
|
print("\n重建容器...")
|
|
compose = f"{DOCKER} compose"
|
|
run_cmd(client, f"cd {NAS_DEPLOY_PATH} && {compose} down", "停止容器")
|
|
run_cmd(client, f"cd {NAS_DEPLOY_PATH} && {compose} up -d --build", "重新构建", timeout=120)
|
|
|
|
# 4. 等待
|
|
print("\n等待容器启动...")
|
|
for i in range(6):
|
|
time.sleep(5)
|
|
out, _, _ = run_cmd(client, f"cd {NAS_DEPLOY_PATH} && {compose} ps", f"检查 {i+1}/6")
|
|
if "Up" in out:
|
|
print(" 容器已启动!")
|
|
break
|
|
|
|
# 5. 验证
|
|
run_cmd(client, f"curl -s http://localhost:8080/api/questionnaires | head -100", "验证问卷API")
|
|
|
|
# 6. 清理
|
|
run_cmd(client, "rm -f /tmp/seed_data.py", "清理")
|
|
|
|
print("\n完成!刷新问卷页面查看新问卷。")
|
|
|
|
client.close() |