63 lines
2.8 KiB
Python
63 lines
2.8 KiB
Python
import getpass
|
|
import hashlib
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
|
|
import paramiko
|
|
|
|
root = Path(__file__).resolve().parent.parent
|
|
client = paramiko.SSHClient()
|
|
client.load_host_keys(str(Path.home() / ".ssh" / "known_hosts"))
|
|
client.connect("47.108.78.12", username="root", password=getpass.getpass("SSH password: "), timeout=20)
|
|
|
|
|
|
def run(command):
|
|
print(command, flush=True)
|
|
_, stdout, stderr = client.exec_command(command, timeout=120)
|
|
output = stdout.read().decode() + stderr.read().decode()
|
|
print(output, flush=True)
|
|
if stdout.channel.recv_exit_status():
|
|
raise RuntimeError("部署命令失败,保留已有版本和备份")
|
|
return output.strip()
|
|
|
|
|
|
switched = False
|
|
previous = ""
|
|
try:
|
|
run("nginx -t && systemctl is-active nginx && df -h /opt && ss -ltnp '( sport = :9999 or sport = :19999 )'")
|
|
previous = run("readlink -f /opt/fdm/current || true")
|
|
stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
|
|
release = f"/opt/fdm/releases/{stamp}"
|
|
backup = f"/var/backups/fdm/{stamp}"
|
|
run(f"install -d -m 755 {release} {backup} && cp -a /etc/nginx/conf.d/fdm-odacm.conf {backup}/")
|
|
sftp = client.open_sftp()
|
|
binary = root / "artifacts/fdm-studio"
|
|
sftp.put(str(binary), release + "/fdm-studio")
|
|
sftp.chmod(release + "/fdm-studio", 0o755)
|
|
expected = hashlib.sha256(binary.read_bytes()).hexdigest()
|
|
run(f"echo '{expected} {release}/fdm-studio' | sha256sum -c -")
|
|
sftp.put(str(root / "deploy/fdm-studio.service"), "/etc/systemd/system/fdm-studio.service")
|
|
sftp.put(str(root / "deploy/nginx-program-http.conf"), release + "/nginx-http.conf")
|
|
run("systemctl daemon-reload")
|
|
run(f"systemd-run --unit=fdm-candidate-{stamp.lower()} --property=DynamicUser=yes {release}/fdm-studio -listen 127.0.0.1:19999")
|
|
run("sleep 2 && curl -fsS http://127.0.0.1:19999/healthz")
|
|
run(f"systemctl stop fdm-candidate-{stamp.lower()}")
|
|
switched = True
|
|
run(f"ln -sfn {release} /opt/fdm/current")
|
|
run(f"cp {release}/nginx-http.conf /etc/nginx/conf.d/fdm-odacm.conf && nginx -t && systemctl reload nginx")
|
|
run("sleep 3 && systemctl enable fdm-studio && systemctl restart fdm-studio && sleep 3 && systemctl is-active fdm-studio")
|
|
run("curl -fsS http://127.0.0.1:9999/healthz && curl -fsS --resolve odacm.cn:443:127.0.0.1 https://odacm.cn/healthz")
|
|
run("systemctl is-enabled certbot.timer || true")
|
|
sftp.close()
|
|
print("部署完成:" + release, flush=True)
|
|
except Exception:
|
|
if switched:
|
|
print("切换验证失败,恢复先前配置", flush=True)
|
|
run("systemctl stop fdm-studio || true")
|
|
if previous:
|
|
run(f"ln -sfn {previous} /opt/fdm/current && systemctl start fdm-studio")
|
|
run(f"cp {backup}/fdm-odacm.conf /etc/nginx/conf.d/fdm-odacm.conf && nginx -t && systemctl reload nginx")
|
|
raise
|
|
finally:
|
|
client.close()
|