我配了三年 GitHub Actions,今天发现这个超时机制是个隐藏炸弹——超时了进程不是「优雅退出」,是被直接 SIGKILL 崩掉的,中间状态全留在了 runner 上。

我配了三年 GitHub Actions,今天发现这个超时机制是个隐藏炸弹——超时了进程不是「优雅退出」,是被直接 SIGKILL 崩掉的,中间状态全留在了 runner 上。

GitHub Actions 的 job timeout 默认 360 分钟(6 小时),最长可以配到 5760 分钟(4 天)。听起来很长对吧?但如果你跑的是长任务构建或者 AI 推理流程,这个上限很容易摸到。

问题在于:超时之后 GitHub 不会给你发 SIGTERM 说「优雅退出一哈」,而是直接 SIGKILL 崩掉。这意味着:

进程来不及清理的东西,全留下了。

比如你起了一个后台 HTTP 服务做端到端测试,超时前没手动 kill,runner 上就留着一个孤儿进程占端口。再比如你开了 SSH 隧道、起了数据库连接池、写了临时文件——这些东西都不会被自动回收,下次 job 跑起来端口就冲突了。

有个真实场景我踩过:一个 Playwright E2E 测试 job,超时前浏览器 driver 进程还没关,下次跑的时候 Chromedriver 占用了上一次的端口,测试直接报 WebDriverError: unable to connect to chromedriver。当时排查了半天,最后发现是超时遗毒。

官方文档里有一句容易被忽略的说明:timeout-minutes 到达时,GitHub 会向 runner 发送 SIGKILL,container 会被强制终止,finally 块里的代码也不保证执行。所以如果你依赖 Node.js 的 process.on("exit") 或者 Python 的 finally 做清理,对不起,不一定管用。

正确的做法是分两层处理:

第一层,用 timeout-minutes 限制最大时长,防止 job 永远跑下去。第二层,在你的脚本里自己实现倒计时退出,留出清理窗口:

# 给脚本设一个比 job timeout 更短的内部倒计时
MAX_JOB_TIME=540  # 9 分钟,比 job timeout 少一分钟
INTERVAL=60

elapsed=0
while [ $elapsed -lt $MAX_JOB_TIME ]; do
  # 你的任务逻辑
  do_some_task

  # 检查是否该停了
  if check_should_stop; then
    cleanup_and_exit  # 这里做优雅退出
  fi

  sleep $INTERVAL
  elapsed=$((elapsed + INTERVAL))
done

第二层是 finally 清理脚本,在 job 任何出口路径都调用:

cleanup() {
  # 杀掉所有 chromedriver 进程
  pkill -9 chromedriver 2>/dev/null || true
  # 清理临时目录
  rm -rf /tmp/test-* 2>/dev/null || true
  # 关闭端口占用
  fuser -k 9222/tcp 2>/dev/null || true
}
trap cleanup EXIT

有个细节很多人不知道:如果你的 job 用的是 container:,container 的生命周期跟着 job走,超时后 container 网络不会自动清理,需要在 cleanup 里手动 docker stop。但因为 SIGKILL 可能跳过这一步,很多人发现自己的 Docker 网络在 runner 上越积越多。

GitHub 官方推荐的做法其实是:不要依赖超时来结束任务,而是让你的任务自己知道什么时候该退出。 比如在循环里加心跳检测、把任务拆成更小的 step 并设置 continue-on-error: true + 每个 step 单独 timeout。

还有一个更隐蔽的坑:如果你用的是 GitHub-hosted runners,超时后 runner 会被回收,下次启动的是一个全新的虚拟机。但如果你用的是 self-hosted runners,超时后 runner 不会自动清理,下次 job 可能跑在「脏环境」里,进程冲突、磁盘满等问题就全来了。self-hosted 的场景下,cleanup 脚本更是必须项。

一句话:timeout 不是「优雅关机」,是「强制拔电源」。 你的清理逻辑要写在 trap EXIT 里,不能写在 finally 块期望它一定会跑。

把 cleanup 脚本固化到你的 workflow 模板里,比出事后再排查省十倍时间。

评论区

0 条评论

登录后可评论。

阿监·前端工程化 1133 阅读