feat: 升级下载 zip 后解压还原 jar
上传端为绕过中间设备对 jar 的拦截,升级包以 zip 下发;Agent 下载 zip 并 sha256 校验后,解压取内层 jar 再走替换/重启/回滚。 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,7 @@ import shutil
|
||||
import subprocess
|
||||
import threading
|
||||
import time
|
||||
import zipfile
|
||||
|
||||
import requests
|
||||
|
||||
@@ -118,6 +119,18 @@ class UpgradeCommand:
|
||||
return self._fail(version, f"SHA-256 校验失败:expected={sha256}, actual={actual}")
|
||||
log.info("SHA-256 校验通过")
|
||||
|
||||
# ===== 2.5 解压 zip 得到内层 jar(上传端为绕过中间设备拦截,jar 被打成 zip) =====
|
||||
extracted_jar = os.path.join("tmp", f"upgrade-{version}.jar.extracted")
|
||||
try:
|
||||
result = extract_jar_from_zip(tmp_jar, extracted_jar)
|
||||
if result is None:
|
||||
os.remove(tmp_jar)
|
||||
return self._fail(version, "zip 包内未找到 jar 文件")
|
||||
os.remove(tmp_jar) # 删除临时 zip
|
||||
tmp_jar = extracted_jar # 后续替换使用解压出的真 jar
|
||||
except Exception as e:
|
||||
return self._fail(version, f"解压 zip 失败:{e}")
|
||||
|
||||
# ===== 3. 备份 =====
|
||||
# jar 路径来自配置(main.jar.path),适配不同部署结构
|
||||
#(如 Agent 与主程序分目录、jar 文件名带版本号等)
|
||||
@@ -333,6 +346,19 @@ def copy_with_retry(src: str, dst: str, retries: int):
|
||||
) from last_error
|
||||
|
||||
|
||||
def extract_jar_from_zip(zip_path: str, dst_jar: str) -> str | None:
|
||||
"""从 zip 中取出第一个 .jar 文件写到 dst_jar,返回 dst_jar;找不到返回 None。"""
|
||||
with zipfile.ZipFile(zip_path) as z:
|
||||
jars = [n for n in z.namelist()
|
||||
if n.lower().endswith(".jar") and not n.endswith("/")]
|
||||
if not jars:
|
||||
return None
|
||||
with z.open(jars[0]) as src, open(dst_jar, "wb") as dst:
|
||||
shutil.copyfileobj(src, dst)
|
||||
log.info("解压 zip 得到 jar:%s → %s", jars[0], os.path.basename(dst_jar))
|
||||
return dst_jar
|
||||
|
||||
|
||||
def sha256_file(path: str) -> str:
|
||||
"""文件 SHA-256(分块读取,支持大文件)。"""
|
||||
digest = hashlib.sha256()
|
||||
|
||||
Reference in New Issue
Block a user