gitlab ci防死循环靠分层超时机制:项目级在.gitlab-ci.yml用default.timeout设限(如"30m"),runner级在config.toml配runner_limit(如7200秒),最终生效值为两者最小值;再辅以浅克隆、避免无界循环、外层包裹linux timeout命令,并通过sleep测试验证。

要防止死循环代码导致流水线无限运行,关键不是“强行拦截”某个具体进程,而是通过分层超时机制,在作业启动前就设定明确的执行上限。GitLab CI 本身不扫描代码逻辑,但能用 timeout 配置让异常作业在耗尽资源前被自动终止。
项目级超时:在 .gitlab-ci.yml 中统一设限
这是最直接、最推荐的第一道防线。在文件顶部使用 default: 关键字为所有作业设置默认超时值:
- 添加
default: { timeout: "30m" },表示每个作业最多运行 30 分钟,超时即失败并释放 runner 资源 - 若某类作业(如集成测试)确实需要更久,可单独覆盖:
test-integration: { timeout: "90m", script: ... } - 注意写法:单位支持
s、m、h,如"15m"、"2h";不能写成数字 900,必须带引号和单位
Runner 级超时:兜底限制,避免单点失控
项目配置可被覆盖,因此需在 Runner 层加第二道锁。修改对应 Runner 的 config.toml:
- 找到
[[runners]]区块,在其中添加runner_limit = 7200(单位为秒,即 2 小时) - 该值会与项目级 timeout 取最小值生效,即
effective timeout = min(project, runner) - 这意味着即使误删了 .gitlab-ci.yml 中的 timeout,Runner 本身也不会允许任何作业跑过 2 小时
配合浅克隆与精简脚本,压缩无效等待时间
死循环常藏在构建或测试脚本里,但很多“空跑”其实源于环境准备阶段——比如反复拉镜像、递归下载依赖、无退出条件的轮询。可通过以下方式减少超时前的无效消耗:
- 启用浅克隆:
variables: { GIT_DEPTH: "1" },跳过历史提交,加快检出速度 - 避免在 script 中写
while true; do ... sleep 5; done类逻辑,改用带计数器和 break 条件的循环 - 对可疑命令(如自定义脚本、第三方工具调用)外层包裹 Linux
timeout命令:script: - timeout 600 ./run-heavy-task.sh || echo "任务超时,已中止"
验证与观测:确保超时真正生效
配置完别忘了验证效果:
- 在作业 script 中插入
sleep 3600(模拟 1 小时卡死),观察是否在设定 timeout 时间内被标记为 failed - 进入 GitLab UI → 项目 → Settings → CI/CD → General pipelines settings,确认 “Timeout” 字段未被设为 0 或空(空值会回退到默认 60 分钟)
- 查看作业日志末尾,正常超时终止会显示类似
ERROR: Job failed: execution took longer than 30m0s seconds











