[#2] agent二进制依赖改成glic 2.35版本

This commit is contained in:
yuyr 2025-09-26 01:52:02 +00:00
parent 00702f268e
commit 7f0290a8f4
4 changed files with 262 additions and 23 deletions

View File

@ -9,7 +9,21 @@ cd src/agent
./scripts/build_binary.sh # 生成 dist/argus-agent ./scripts/build_binary.sh # 生成 dist/argus-agent
``` ```
脚本会在本地创建虚拟环境、通过 `pyproject.toml` 安装依赖,并调用 PyInstaller 产出单文件可执行程序。构建过程中生成的 `build/``dist/` 会被 `.gitignore` 忽略。 脚本默认会在 Docker 容器 (`python:3.11-slim-bullseye`) 内执行 PyInstaller确保产物运行时兼容 glibc 2.31+(覆盖 2.35 环境)。构建流程注意事项:
- 每次构建前会清理 `build/``dist/` 并在容器内重新创建虚拟环境。
- 需要使用内网 Python 镜像时,可通过 `PIP_INDEX_URL``PIP_EXTRA_INDEX_URL``PIP_TRUSTED_HOST` 等环境变量传入,脚本会自动透传给容器。
- 如果宿主机无法运行 Docker可设置 `AGENT_BUILD_USE_DOCKER=0` 回退到本地构建;此时代码必须在 glibc ≤ 2.35 的机器上执行。
构建结束后脚本会在 `build/compat_check/` 下解包关键动态库并输出最高 `GLIBC_x.y` 版本,便于快速核对兼容性。如果结果中缺少 `libssl.so.3` / `libcrypto.so.3`,表示系统会在目标宿主机上使用本地 OpenSSL 库,无需额外处理。
例如:
```bash
strings build/compat_check/libpython*.so.1.0 | grep -Eo 'GLIBC_[0-9]+\.[0-9]+' | sort -Vu | tail -n1
```
如遇构建失败,常见原因是 Docker 不可用(请改用 `AGENT_BUILD_USE_DOCKER=0`)或无法访问 Python 包镜像(先设置上述镜像环境变量后重试)。
## 运行时配置 ## 运行时配置

Binary file not shown.

View File

@ -6,37 +6,257 @@ MODULE_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
BUILD_ROOT="$MODULE_ROOT/build" BUILD_ROOT="$MODULE_ROOT/build"
DIST_DIR="$MODULE_ROOT/dist" DIST_DIR="$MODULE_ROOT/dist"
PYINSTALLER_BUILD="$BUILD_ROOT/pyinstaller" PYINSTALLER_BUILD="$BUILD_ROOT/pyinstaller"
PYINSTALLER_SPEC="$PYINSTALLER_BUILD/spec"
PYINSTALLER_WORK="$PYINSTALLER_BUILD/work"
VENV_DIR="$BUILD_ROOT/venv" VENV_DIR="$BUILD_ROOT/venv"
mkdir -p "$PYINSTALLER_BUILD" AGENT_BUILD_IMAGE="${AGENT_BUILD_IMAGE:-python:3.11-slim-bullseye}"
mkdir -p "$DIST_DIR" AGENT_BUILD_USE_DOCKER="${AGENT_BUILD_USE_DOCKER:-1}"
USED_DOCKER=0
if [[ ! -d "$VENV_DIR" ]]; then
python3 -m venv "$VENV_DIR"
fi
run_host_build() {
echo "[INFO] Using host Python environment for build" >&2
rm -rf "$BUILD_ROOT" "$DIST_DIR"
mkdir -p "$PYINSTALLER_BUILD" "$DIST_DIR"
python3 -m venv --copies "$VENV_DIR"
# shellcheck disable=SC1091 # shellcheck disable=SC1091
source "$VENV_DIR/bin/activate" source "$VENV_DIR/bin/activate"
pip install --upgrade pip pip install --upgrade pip
pip install "$MODULE_ROOT" pip install .
pip install "pyinstaller==6.6.0" pip install "pyinstaller==6.6.0"
rm -rf "$PYINSTALLER_BUILD"/*
rm -f "$DIST_DIR/argus-agent"
pyinstaller \ pyinstaller \
--clean \ --clean \
--onefile \ --onefile \
--name argus-agent \ --name argus-agent \
--distpath "$DIST_DIR" \ --distpath "$DIST_DIR" \
--workpath "$PYINSTALLER_BUILD/work" \ --workpath "$PYINSTALLER_WORK" \
--specpath "$PYINSTALLER_BUILD/spec" \ --specpath "$PYINSTALLER_SPEC" \
--add-data "$MODULE_ROOT/pyproject.toml:." \ --add-data "$MODULE_ROOT/pyproject.toml:." \
"$MODULE_ROOT/entry.py" "$MODULE_ROOT/entry.py"
chmod +x "$DIST_DIR/argus-agent" chmod +x "$DIST_DIR/argus-agent"
deactivate
}
run_docker_build() {
if ! command -v docker >/dev/null 2>&1; then
echo "[ERROR] docker 命令不存在,无法在容器内构建。请安装 Docker 或设置 AGENT_BUILD_USE_DOCKER=0" >&2
exit 1
fi
USED_DOCKER=1
echo "[INFO] Building agent binary inside $AGENT_BUILD_IMAGE" >&2
docker_env=("--rm" "-u" "$(id -u):$(id -g)" "-v" "$MODULE_ROOT:/workspace" "-w" "/workspace")
pass_env_if_set() {
local var="$1"
local value="${!var:-}"
if [[ -n "$value" ]]; then
docker_env+=("--env" "$var=$value")
fi
}
pass_env_if_set PIP_INDEX_URL
pass_env_if_set PIP_EXTRA_INDEX_URL
pass_env_if_set PIP_TRUSTED_HOST
pass_env_if_set HTTP_PROXY
pass_env_if_set HTTPS_PROXY
pass_env_if_set NO_PROXY
pass_env_if_set http_proxy
pass_env_if_set https_proxy
pass_env_if_set no_proxy
build_script=$(cat <<'INNER'
set -euo pipefail
cd /workspace
apt-get update >/dev/null
apt-get install -y --no-install-recommends binutils >/dev/null
rm -rf /var/lib/apt/lists/*
rm -rf build dist
mkdir -p build/pyinstaller dist
python3 -m venv --copies build/venv
source build/venv/bin/activate
pip install --upgrade pip
pip install .
pip install pyinstaller==6.6.0
pyinstaller \
--clean \
--onefile \
--name argus-agent \
--distpath dist \
--workpath build/pyinstaller/work \
--specpath build/pyinstaller/spec \
--add-data /workspace/pyproject.toml:. \
entry.py
chmod +x dist/argus-agent
python3 - <<'PY'
from pathlib import Path
from PyInstaller.archive.readers import CArchiveReader
import sys
archive = Path('dist/argus-agent')
out_dir = Path('build/compat_check')
out_dir.mkdir(parents=True, exist_ok=True)
major, minor = sys.version_info[:2]
libpython = f'libpython{major}.{minor}.so.1.0'
expected_libs = [
libpython,
'libssl.so.3',
'libcrypto.so.3',
]
reader = CArchiveReader(str(archive))
extracted = []
missing = []
for name in expected_libs:
try:
data = reader.extract(name)
except KeyError:
missing.append(name)
continue
(out_dir / name).write_bytes(data)
extracted.append(name)
(out_dir / 'manifest').write_text('\n'.join(extracted))
if extracted:
print('[INFO] Extracted libraries: ' + ', '.join(extracted))
if missing:
print('[WARN] Missing expected libraries in bundle: ' + ', '.join(missing))
PY
compat_check() {
local lib_path="$1"
if [[ ! -f "$lib_path" ]]; then
echo "[WARN] Missing $lib_path for GLIBC check"
return
fi
local max_glibc
max_glibc=$(strings -a "$lib_path" | grep -Eo 'GLIBC_[0-9]+\.[0-9]+' | sort -Vu | tail -n 1 || true)
if [[ -n "$max_glibc" ]]; then
echo "[INFO] $lib_path references up to $max_glibc"
else
echo "[INFO] $lib_path does not expose GLIBC version strings"
fi
}
compat_libs=()
if [[ -f build/compat_check/manifest ]]; then
mapfile -t compat_libs < build/compat_check/manifest
fi
if [[ ${#compat_libs[@]} -eq 0 ]]; then
echo "[WARN] No libraries captured for GLIBC inspection"
else
for lib in "${compat_libs[@]}"; do
compat_check "build/compat_check/$lib"
done
fi
deactivate deactivate
INNER
)
if ! docker run "${docker_env[@]}" "$AGENT_BUILD_IMAGE" bash -lc "$build_script"; then
echo "[ERROR] Docker 构建失败,请检查 Docker 权限或设置 AGENT_BUILD_USE_DOCKER=0 在兼容主机上构建" >&2
exit 1
fi
}
if [[ "$AGENT_BUILD_USE_DOCKER" == "1" ]]; then
run_docker_build
else
run_host_build
fi
if [[ ! -f "$DIST_DIR/argus-agent" ]]; then
echo "[ERROR] Agent binary was not produced" >&2
exit 1
fi
if [[ "$USED_DOCKER" != "1" ]]; then
if [[ ! -x "$VENV_DIR/bin/python" ]]; then
echo "[WARN] PyInstaller virtualenv missing at $VENV_DIR; skipping compatibility check" >&2
else
COMPAT_DIR="$BUILD_ROOT/compat_check"
rm -rf "$COMPAT_DIR"
mkdir -p "$COMPAT_DIR"
EXTRACT_SCRIPT=$(cat <<'PY'
from pathlib import Path
from PyInstaller.archive.readers import CArchiveReader
import sys
archive = Path('dist/argus-agent')
out_dir = Path('build/compat_check')
out_dir.mkdir(parents=True, exist_ok=True)
major, minor = sys.version_info[:2]
libpython = f'libpython{major}.{minor}.so.1.0'
expected_libs = [
libpython,
'libssl.so.3',
'libcrypto.so.3',
]
reader = CArchiveReader(str(archive))
extracted = []
missing = []
for name in expected_libs:
try:
data = reader.extract(name)
except KeyError:
missing.append(name)
continue
(out_dir / name).write_bytes(data)
extracted.append(name)
(out_dir / 'manifest').write_text('\n'.join(extracted))
if extracted:
print('[INFO] Extracted libraries: ' + ', '.join(extracted))
if missing:
print('[WARN] Missing expected libraries in bundle: ' + ', '.join(missing))
PY
)
"$VENV_DIR/bin/python" - <<PY
$EXTRACT_SCRIPT
PY
compat_libs=()
if [[ -f "$COMPAT_DIR/manifest" ]]; then
mapfile -t compat_libs < "$COMPAT_DIR/manifest"
fi
check_glibc_version() {
local lib_path="$1"
if [[ ! -f "$lib_path" ]]; then
echo "[WARN] Skipping GLIBC check; file not found: $lib_path" >&2
return
fi
if command -v strings >/dev/null 2>&1; then
local max_glibc
max_glibc=$(strings -a "$lib_path" | grep -Eo 'GLIBC_[0-9]+\.[0-9]+' | sort -Vu | tail -n 1 || true)
if [[ -n "$max_glibc" ]]; then
echo "[INFO] $lib_path references up to $max_glibc"
else
echo "[INFO] $lib_path does not expose GLIBC version strings"
fi
else
echo "[WARN] strings command unavailable; cannot inspect $lib_path" >&2
fi
}
if [[ ${#compat_libs[@]} -eq 0 ]]; then
echo "[WARN] No libraries captured for GLIBC inspection" >&2
else
for lib in "${compat_libs[@]}"; do
check_glibc_version "$COMPAT_DIR/$lib"
done
fi
fi
else
echo "[INFO] Compatibility check executed inside container"
fi
echo "[INFO] Agent binary generated at $DIST_DIR/argus-agent" echo "[INFO] Agent binary generated at $DIST_DIR/argus-agent"

View File

@ -21,9 +21,14 @@ done
if [[ -x "$DNS_SCRIPT" ]]; then if [[ -x "$DNS_SCRIPT" ]]; then
log "执行 update-dns.sh 更新容器 DNS" log "执行 update-dns.sh 更新容器 DNS"
if ! "$DNS_SCRIPT"; then while true; do
log "update-dns.sh 执行失败,继续尝试默认 DNS" if "$DNS_SCRIPT"; then
log "update-dns.sh 执行成功"
break
fi fi
log "update-dns.sh 执行失败3 秒后重试"
sleep 3
done
else else
log "未获取到 update-dns.sh使用镜像默认 DNS" log "未获取到 update-dns.sh使用镜像默认 DNS"
fi fi