From 16bb794a43d69486c1c3766f8e888763c7bb7936 Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Thu, 22 Oct 2026 23:47:15 +0800 Subject: [PATCH] =?UTF-8?q?ci:=20=E4=BA=8C=E6=AC=A1=E5=8A=A0=E5=9B=BA=20?= =?UTF-8?q?=E2=80=94=E2=80=94=20=E4=B8=8A=E4=B8=80=E7=89=88=E5=AF=B9=20apt?= =?UTF-8?q?=20=E5=8D=A1=E6=AD=BB=E6=97=A0=E6=95=88=EF=BC=8C=E6=94=B9?= =?UTF-8?q?=E7=94=A8=20timeout=20=E7=A1=AC=E8=B6=85=E6=97=B6=E5=B9=B6?= =?UTF-8?q?=E5=8E=BB=E6=8E=89=20-qq?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 上一版为什么没解决 第一版加了 `Acquire::http::Timeout=60` + `Retries=3` + step 6 分钟超时。 CI 实测结果: 15:39:48 需要安装: gcc-aarch64-linux-gnu 15:46:01 ##[error]The action '安装 C 工具链(已装则跳过)' has timed out after 6 minutes. **依然卡满 6 分钟**,而且日志里**一个 apt 输出都没有** —— 因为 `-qq` 把 所有输出静默了。两个结论: 1. `Acquire::*Timeout` 只管**单个连接**,不管 apt 整体 —— 源重试、DPKG 锁 等待、依赖计算都不受它约束,所以它拦不住这类卡死 2. `-qq` 让卡死**完全不可观测**:既看不到卡在哪个源,也看不到在下载什么。 不可观测正是它能悄悄拖满超时的原因 (顺带证明"已装则跳过"这条是有效的:cmake/clang 都在镜像里,只列出了 `gcc-aarch64-linux-gnu` 一项要装。) ## 这一版改法 | 改动 | 理由 | |---|---| | 去掉 `-qq`,保留可读进度 | 下次卡死必须能看出卡在哪,否则无从诊断 | | `timeout 120 apt-get update` | **外层硬超时**,强制结束,不依赖 apt 自身行为 | | `timeout 180 apt-get install` | 同上;120+180=300s 配 step 5 分钟正好 | | 失败即 `exit 1` + `::error::`,不重试整段 | 宁可红一次让人看见,不要用重试掩盖真实问题 | | `--no-install-recommends` 保留 | 减少下载量与依赖面 | ## 本地实测 | 验证 | 结果 | |---|---| | YAML 可解析 | ✅ | | `timeout 3 sleep 60` 行为 | ✅ 3 秒强制结束,退出码 124,可被 `if !` 捕获 | | "已装则跳过"分支 | ✅ 「✅ 跳过 apt-get」 | | 上一版缺工具 `[SKIP] ... exit 0` 风险 | ✅ 已复现并拦截(见前一提交) | ## 仍待 CI 验证 这一版的真实效果只有在 runner 上才知。若这次仍然卡满,说明 `timeout` 对 sudo+apt 组合失效(可能性低),届时改用「换源」或「预装镜像」方案。 --- .github/workflows/ci.yml | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7f290a9..a06f027b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -187,7 +187,9 @@ jobs: # 而不是把整个 job 拖到 job 级 timeout(后者报错信息毫无指向性) # 3. 装完立即 `command -v` 复核,缺工具就红 —— 见下方"缺工具即失败" - name: 安装 C 工具链(已装则跳过) - timeout-minutes: 6 + # 120s(update) + 180s(install) = 300s,给 5 分钟正好; + # 超出说明 timeout 命令本身没生效,此时应当红而不是继续等。 + timeout-minutes: 5 run: | set -uo pipefail need="" @@ -201,17 +203,29 @@ jobs: fi echo "需要安装:$need" - # apt-get 自己的超时:卡住时 4 分钟内失败,而不是拖到 6 分钟 step 超时。 - # 重试一次 —— runner 网络偶发抖动不该让门禁变红。 - sudo apt-get -o Acquire::http::Timeout=60 \ - -o Acquire::https::Timeout=60 \ - -o Acquire::Retries=3 \ - update -qq + + # ★ 2026-10-22 实测:加 Acquire::*Timeout=60 + Retries=3 之后仍然卡满 + # 6 分钟 step 超时,且**日志里一个 apt 输出都没有** —— 因为 `-qq` + # 把一切静默了。卡死不可观测正是它拖满超时的原因:既看不到卡在哪个 + # 源,也看不到到底在下载什么。 + # + # 所以: + # · 去掉 `-qq`,保留可读进度(否则下次卡死仍然无从诊断) + # · 用 `timeout` 命令做外层硬超时 —— Acquire::Timeout 只管单个连接, + # 不管 apt 整体(源重试、DPkg 锁等待都不受它约束) + # · 失败后**不重试整段**:宁可红一次让人看见,也不要为偶发网络 + # 抖动掩盖真实问题 + APT_OPTS="-o Acquire::http::Timeout=30 -o Acquire::https::Timeout=30 -o Acquire::Retries=2" # shellcheck disable=SC2086 - sudo apt-get -o Acquire::http::Timeout=60 \ - -o Acquire::https::Timeout=60 \ - -o Acquire::Retries=3 \ - install -y -qq --no-install-recommends $need + if ! timeout 120 sudo apt-get $APT_OPTS update; then + echo "::error::apt-get update 超时/失败(120s)—— runner 网络或源不可用" + exit 1 + fi + # shellcheck disable=SC2086 + if ! timeout 180 sudo apt-get $APT_OPTS install -y --no-install-recommends $need; then + echo "::error::apt-get install 超时/失败(180s)需要安装:$need" + exit 1 + fi # ── 缺工具即失败(★ 这条是本次加固的核心)──────────────────── #