125 lines
5.9 KiB
Python
125 lines
5.9 KiB
Python
#!/usr/bin/env python3
|
||
"""在新服务器上源码编译安装Python 3.10,修复CMD Agent端口,重启Runner"""
|
||
import subprocess
|
||
import os
|
||
import sys
|
||
|
||
NEW_SERVER = "172.30.18.199"
|
||
|
||
KEY_CONTENT = """-----BEGIN OPENSSH PRIVATE KEY-----
|
||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||
QyNTUxOQAAACD6GquAk5vBEfbtaJCTSfnQEhjzC8e5GF60hSbPP0BJbAAAAJiQxGNokMRj
|
||
aAAAAAtzc2gtZWQyNTUxOQAAACD6GquAk5vBEfbtaJCTSfnQEhjzC8e5GF60hSbPP0BJbA
|
||
AAAED2muzuU4BAiCqbg0ayGxgiDvfS/xI1SFvb32oLzTnn8/oaq4CTm8ER9u1okJNJ+dAS
|
||
GPMLx7kYXrSFJs8/QElsAAAAFHJ1bm5lci1hZG1pbkB4aWFveGlhAQ==
|
||
-----END OPENSSH PRIVATE KEY-----
|
||
"""
|
||
|
||
key_path = "/tmp/new_server_ed25519"
|
||
with open(key_path, "w") as f:
|
||
f.write(KEY_CONTENT)
|
||
os.chmod(key_path, 0o600)
|
||
|
||
def ssh(cmd, timeout=1800):
|
||
full_cmd = f'ssh -i {key_path} -o StrictHostKeyChecking=no -o ConnectTimeout=10 -o ServerAliveInterval=60 root@{NEW_SERVER} "{cmd}"'
|
||
print(f"\n$ {cmd[:120]}")
|
||
sys.stdout.flush()
|
||
result = subprocess.run(full_cmd, shell=True, capture_output=True, text=True, timeout=timeout)
|
||
if result.stdout:
|
||
lines = result.stdout.strip().split('\n')
|
||
for line in lines[:30]:
|
||
print(" ", line[:200])
|
||
if len(lines) > 30:
|
||
print(f" ... ({len(lines)-30} more lines)")
|
||
if result.stderr:
|
||
err_lines = result.stderr.strip().split('\n')
|
||
for line in err_lines[:15]:
|
||
if "Warning" not in line and "Connection reset" not in line and "Permanently added" not in line:
|
||
print(" ERR:", line[:200])
|
||
print(f" [RC={result.returncode}]")
|
||
sys.stdout.flush()
|
||
return result
|
||
|
||
def ssh_check(cmd, timeout=1800):
|
||
r = ssh(cmd, timeout)
|
||
if r.returncode != 0:
|
||
print(f"命令失败,退出: {cmd[:80]}")
|
||
sys.exit(1)
|
||
return r
|
||
|
||
print("=" * 60)
|
||
print("步骤0: 检查当前Python版本")
|
||
print("=" * 60)
|
||
r = ssh("export PATH=/usr/local/bin:$PATH && python3 --version 2>&1; which python3; pip3 --version 2>&1 || true")
|
||
if "Python 3.10" in r.stdout or "Python 3.10" in r.stderr:
|
||
print("Python 3.10 已安装,跳过编译")
|
||
skip_build = True
|
||
else:
|
||
skip_build = False
|
||
|
||
if not skip_build:
|
||
print("\n" + "=" * 60)
|
||
print("步骤1: 安装编译依赖")
|
||
print("=" * 60)
|
||
ssh_check("yum install -y gcc gcc-c++ make openssl-devel bzip2-devel libffi-devel zlib-devel readline-devel sqlite-devel wget 2>&1 | tail -3", timeout=300)
|
||
|
||
print("\n" + "=" * 60)
|
||
print("步骤2: 下载Python 3.10.14源码(国内镜像)")
|
||
print("=" * 60)
|
||
# 用华为云镜像,速度快
|
||
ssh_check("cd /tmp && wget -q --timeout=60 --tries=3 https://mirrors.huaweicloud.com/python/3.10.14/Python-3.10.14.tgz && echo download_ok || (echo 'huawei mirror failed, trying npmmirror...' && wget -q --timeout=60 --tries=3 https://npmmirror.com/mirrors/python/3.10.14/Python-3.10.14.tgz && echo download_ok)", timeout=300)
|
||
|
||
print("\n" + "=" * 60)
|
||
print("步骤3: 解压并编译安装(约5-10分钟)")
|
||
print("=" * 60)
|
||
ssh_check("cd /tmp && rm -rf Python-3.10.14 && tar xzf Python-3.10.14.tgz && echo extract_ok", timeout=60)
|
||
ssh_check("cd /tmp/Python-3.10.14 && ./configure --prefix=/usr/local --with-ensurepip=install 2>&1 | tail -5", timeout=180)
|
||
# 不用 --enable-optimizations 加快编译速度
|
||
ssh_check("cd /tmp/Python-3.10.14 && make -j$(nproc) 2>&1 | tail -5", timeout=1200)
|
||
ssh_check("cd /tmp/Python-3.10.14 && make altinstall 2>&1 | tail -5", timeout=300)
|
||
|
||
print("\n" + "=" * 60)
|
||
print("步骤4: 设置为默认python3和pip3")
|
||
print("=" * 60)
|
||
ssh_check("ln -sf /usr/local/bin/python3.10 /usr/local/bin/python3 && ln -sf /usr/local/bin/pip3.10 /usr/local/bin/pip3 && echo link_ok")
|
||
|
||
print("\n" + "=" * 60)
|
||
print("步骤5: 验证Python 3.10和pip --break-system-packages")
|
||
print("=" * 60)
|
||
ssh_check("export PATH=/usr/local/bin:$PATH && python3 --version && pip3 --version && pip3 install --help 2>&1 | grep -q 'break-system-packages' && echo 'pip3 supports --break-system-packages'")
|
||
|
||
print("\n" + "=" * 60)
|
||
print("步骤6: 修复CMD Agent端口 5000 -> 5927")
|
||
print("=" * 60)
|
||
ssh("grep -n 'port\\|PORT\\|5000\\|5927' /opt/cmd-agent/server.py 2>&1 | head -10 || echo 'no port found in server.py'")
|
||
ssh("cd /opt/cmd-agent && sed -i 's/port=5000/port=5927/g; s/port = 5000/port = 5927/g; s/\"5000\"/\"5927\"/g' server.py 2>&1 && echo sed_done || true")
|
||
# 检查systemd服务文件
|
||
ssh("find /etc/systemd -name 'cmd-agent*' 2>/dev/null; systemctl cat cmd-agent 2>&1 | head -20 || true")
|
||
ssh("systemctl daemon-reload && systemctl restart cmd-agent 2>&1 && sleep 2 && systemctl is-active cmd-agent")
|
||
# 验证端口
|
||
ssh("ss -tlnp 2>/dev/null | grep -E '5927|5000' || netstat -tlnp 2>/dev/null | grep -E '5927|5000' || echo 'port check done'")
|
||
|
||
print("\n" + "=" * 60)
|
||
print("步骤7: 安装git(新Runner需要git才能checkout)")
|
||
print("=" * 60)
|
||
ssh_check("which git 2>&1 || yum install -y git 2>&1 | tail -3", timeout=120)
|
||
ssh("git --version 2>&1")
|
||
|
||
print("\n" + "=" * 60)
|
||
print("步骤8: 重启6个Runner服务让新Python生效")
|
||
print("=" * 60)
|
||
ssh("for i in 1 2 3 4 5 6; do systemctl restart act-runner-$i.service 2>/dev/null && echo runner-$i\_restarted || systemctl restart gitea-runner-$i.service 2>/dev/null && echo runner-$i\_restarted_old || echo runner-$i\_notfound; done")
|
||
|
||
print("\n" + "=" * 60)
|
||
print("步骤9: 最终验证")
|
||
print("=" * 60)
|
||
ssh("echo '--- Python ---' && export PATH=/usr/local/bin:$PATH && python3 --version && pip3 --version")
|
||
ssh("echo '--- Git ---' && git --version")
|
||
ssh("echo '--- Runners ---' && systemctl list-units 'act-runner-*' --no-legend 2>/dev/null | head -10 || systemctl list-units 'gitea-runner-*' --no-legend 2>/dev/null | head -10")
|
||
ssh("echo '--- CMD Agent ---' && systemctl status cmd-agent 2>&1 | head -3")
|
||
ssh("echo '--- Port 5927 ---' && (ss -tlnp 2>/dev/null | grep 5927 || netstat -tlnp 2>/dev/null | grep 5927 || echo 'port 5927 not listening')")
|
||
|
||
print("\n" + "=" * 60)
|
||
print("全部完成!")
|
||
print("=" * 60)
|