GitHub Actions 与自托管 Runner:国内注册失败、任务排队、checkout 超时怎么解决
GitHub Actions 自带的托管 Runner 在海外机房,私有仓库按分钟计费,构建一大、依赖一多,免费额度很快就用完。于是不少团队把 Runner 装在公司的服务器、办公室的旧电脑或者自己的开发机上:构建能复用本地缓存,能访问内网数据库,不占托管分钟数。问题在于 Runner 不是一次连上就完事,它要长期轮询 GitHub 领取任务,还要下载 Action、拉代码、上传日志与产物,国内网络下最常见的失败是注册时报 404、任务一直显示 Waiting for a runner to pick up this job、checkout 步骤报 Failed to connect to github.com port 443。
这些失败分属四个环节:注册令牌与网络、Runner 进程与服务、任务标签匹配、任务执行时访问的各个域名。注册与执行阶段都依赖一条稳定的出境连接,而且不止 github.com 一个域名;标签匹配则纯粹是配置问题,换网络也没用。下面先讲托管与自托管的差别,再按顺序把 Runner 从注册到稳定运行的步骤走一遍。GitHub 的计费与分钟额度近年有过调整,以官方最新条款为准。
托管 Runner 与自托管 Runner 的区别
自托管的最大收益是复用缓存与访问内网,代价是你要自己负责网络与升级。GitHub 官方明确建议不要给公开仓库挂自托管 Runner,因为任何人提交的 Pull Request 都可能在你的机器上执行代码。国内机器做 Runner 的核心难点只有一个:它和 GitHub 之间的每一次通信都要稳定。
| 对比项 | GitHub 托管 | 自托管(国内机器) | 自托管(海外服务器) |
|---|---|---|---|
| 分钟计费 | 私有仓库按分钟计 | 不占托管分钟 | 不占托管分钟 |
| 连接 GitHub | 机房内网,几乎不出问题 | 需要稳定出境连接 | 直连即可 |
| 访问内网资源 | 做不到 | 可以直接访问 | 需要额外打通 |
| 本地缓存 | 每次全新环境 | 可复用依赖与镜像 | 可复用 |
| 维护成本 | 无 | 需要自己升级与看护 | 需要自己升级与看护 |
| 安全边界 | 每次任务隔离 | 公开仓库有被滥用风险 | 同左 |
从零注册一个可用的 Runner:分步操作
- 第一步:先把线路准备好。在要做 Runner 的那台电脑上连上刺猬VPN,再打开 github.com 确认能登录。客户端自定义用户名和密码即可匿名注册,不需要邮箱和手机号;按域名分流时,确保下面提到的 GitHub 相关域名都走线路,或者临时切到全局模式;
- 第二步:进入仓库的 Settings → Actions → Runners,点 New self-hosted runner,选择操作系统与架构。组织级 Runner 在组织的 Settings 里配置,能给多个仓库共用;
- 第三步:按页面给出的命令下载并解压 Runner 安装包。安装包来自 GitHub 的 Releases,下载慢或中断时先确认线路,再重新执行下载命令;
- 第四步:运行 config.sh(Windows 上是 config.cmd),填入页面上的仓库地址与注册令牌。注意这个令牌只在一小时内有效,页面开着太久再复制,就会在注册时报 404 或 Not Found;
- 第五步:配置时会问 Runner 名称与额外标签。默认会带上 self-hosted、操作系统和架构三个标签,按用途再加一个自定义标签,比如 gpu 或 intranet,方便工作流精确指定;
- 第六步:如果 Runner 跑在没有图形界面的服务器上,在 Runner 目录里新建 .env 文件,写入 https_proxy 与 no_proxy 两行,指向你已有的出口代理,并把内网地址放进 no_proxy,避免访问内网也绕出去;
- 第七步:先用 run.sh 前台运行一次,看到 Listening for Jobs 说明已连上。再用 svc.sh install 与 svc.sh start 装成系统服务,Windows 在配置时选择以服务方式运行,这样重启后能自动上线;
- 第八步:在工作流里把 runs-on 改成数组形式,例如同时写 self-hosted、linux 与自定义标签。标签必须全部匹配,任何一个写错,任务都会一直排队;
- 第九步:手动触发一次工作流,依次确认 checkout、依赖安装、缓存与上传产物几步都通过,再把其他工作流迁过来。
按现象排查:注册、在线、排队与执行
Runner 的问题大多能从现象直接定位到环节,先看是卡在哪一步再动手。
- 注册时报 404 或 Not Found:注册令牌过期或仓库地址写错,回到 New self-hosted runner 页面刷新后重新复制命令;
- 注册时一直卡住后超时:连不上 api.github.com,确认线路已连上且该域名走线路;
- Runners 列表里显示 Offline:进程退出或网络断开,先看服务状态,再看 Runner 目录下 _diag 文件夹里的日志;
- 任务一直显示 Waiting for a runner to pick up this job:runs-on 标签与 Runner 不匹配,或者 Runner 被分配在别的 Runner 组里;
- 卡在 Download action repository:Action 的代码要从 codeload.github.com 与 api.github.com 拉取,这两个域名要能访问;
- checkout 报 Failed to connect to github.com port 443:执行环境里的 git 没走代理,检查 .env 是否生效,必要时给 git 单独配置 http.proxy;
- 上传产物或缓存失败:产物和缓存存放在另一组存储域名,分流规则没覆盖到就会失败,临时切全局模式验证;
- 日志提示 Runner 版本已废弃、不再接收任务:自动更新下载失败,手动下载新版覆盖安装;
- 任务中途 The runner has received a shutdown signal:机器休眠或服务被停止,关闭系统休眠并确认服务开机自启。
网络方案怎么选:开发机、办公室与服务器
Runner 是长期在线的进程,轮询本身流量很小,但每次 checkout 大仓库、拉镜像、上传产物都会产生可观的流量。先用免费节点验证注册与一次完整构建能跑通,确认要长期挂机再考虑时长套餐,有效期内不限流量、不限速。断线保护能在线路中断时阻止流量走直连,对 Runner 来说意味着断开就重连,而不是半途改走另一条不通的路。实际可用性取决于当前网络环境。
| 对比项 | 免费节点 | 会员节点 | 海外服务器直连 |
|---|---|---|---|
| 注册与轮询 | 可以完成 | 长期在线更合适 | 直连可用 |
| 大仓库 checkout | 视当前负载而定 | 时长套餐期间不限流量、不限速 | 取决于服务器带宽 |
| 长时间挂机 | 适合测试 | 适合日常构建 | 适合 |
| 断线保护 | 客户端支持 | 客户端支持 | 无此需求 |
| 访问内网 | 可以 | 可以 | 需要组网 |
| 适合场景 | 验证流程能否跑通 | 国内机器做常驻 Runner | 不依赖内网的构建 |
Windows、macOS 与 Linux 上的差别
Linux 服务器最常见,用 svc.sh 装成 systemd 服务,代理写在 .env 里即可被 Runner 与它启动的任务继承;注意 Docker 容器任务不会自动继承宿主机的代理,需要在容器配置或 Docker 守护进程里单独设置。macOS 适合需要 Xcode 的 iOS 构建,用 launchd 运行,记得在系统设置里关闭自动休眠,否则合上盖子 Runner 就会离线。
Windows 上配置时选择以服务方式运行,服务默认用 NETWORK SERVICE 账户,它读不到当前用户的代理设置,所以同样要写 .env。PowerShell 步骤里如果要调用 git,建议在仓库根目录用 git config 单独设置代理,比依赖系统设置更可靠。三个平台的日志都在 Runner 目录的 _diag 文件夹下,遇到问题先看最新的那份。
迁移顺序:从托管 Runner 切到自托管
不要一次把所有工作流都改成自托管。稳妥的顺序是:先挑一个耗时最长、依赖最多的构建任务,比如前端打包或者镜像构建,单独复制一份工作流指向自托管 Runner,与原来的托管任务并行跑一周,对比耗时与成功率;确认稳定后,再把测试、代码检查这类轻量任务迁过来;发布与部署类任务放在最后,因为它们通常要用到仓库密钥,迁移前要先确认 Runner 机器的访问权限只开放给必要的人。
迁移过程中保留一个托管 Runner 的备用方案很有必要:在工作流里用条件判断或者手动触发参数,让任务在自托管 Runner 离线时退回到托管环境执行。这样即使办公室断电、开发机关机,关键的发布流程也不会被卡住。每次 Runner 大版本更新后,先在一台机器上验证,再批量升级其余机器。另外建议给 Runner 机器单独建一个系统账户运行服务,不要用管理员账户,工作目录放在空间充足的磁盘上,并定期清理 _work 目录里残留的旧构建文件,避免磁盘写满导致任务莫名失败。仓库密钥只给确实需要的工作流使用,Runner 机器上不要长期保存明文令牌,离职或换机时记得在 Runners 列表里移除旧的 Runner。
和其他代码托管工具的分工
Runner 只解决「在哪里构建」,日常的 clone、push 与网页浏览仍然要靠稳定连到 GitHub。clone 慢、push 超时、Releases 下载中断的处理见 GitHub 访问加速指南,那里讲的 git 代理设置在 Runner 机器上同样适用。
如果团队同时用 GitLab 或 Bitbucket,它们也有各自的自托管执行器,网络上的坑几乎一样,见 GitLab 与 Bitbucket 访问指南。一种常见做法是代码主仓放在 GitHub,用自托管 Runner 构建,再把镜像推到内网仓库,这样只有拉代码与回传状态需要出境。
常见报错速查表
| 现象 | 原因 | 解决办法 |
|---|---|---|
| 注册报 404 | 注册令牌过期 | 刷新页面重新复制命令 |
| Runner 显示 Offline | 进程退出或网络中断 | 检查服务状态与 _diag 日志 |
| 任务一直 Waiting for a runner | 标签不匹配 | 核对 runs-on 与 Runner 标签 |
| Download action 卡住 | codeload 域名不通 | 确认该域名走线路 |
| checkout 连不上 443 | git 未走代理 | 检查 .env 或给 git 设代理 |
| 产物上传失败 | 存储域名未覆盖 | 临时切全局模式验证 |
| 提示 Runner 版本废弃 | 自动更新下载失败 | 手动下载新版覆盖安装 |
高频问答
- 问:自托管 Runner 需要开放入站端口吗?答:不需要,Runner 主动向 GitHub 发起 HTTPS 连接领取任务,只要出站 443 可用即可;
- 问:一台机器能装多个 Runner 吗?答:可以,分别解压到不同目录各自注册,适合同时跑多个任务;
- 问:自托管 Runner 还收费吗?答:长期以来不占托管分钟数,但计费规则有过调整讨论,以官方最新条款为准;
- 问:公开仓库能用自托管 Runner 吗?答:技术上可以,但不建议,外部提交的代码可能在你的机器上执行;
- 问:Docker 任务里为什么还是连不上?答:容器不继承宿主机的 .env 代理,需要在容器或 Docker 守护进程里单独配置;
- 问:Runner 断网后会自己恢复吗?答:会自动重连,但长时间离线可能导致任务超时,建议配合断线保护与服务自启。
让国内 Runner 长期稳定的做法
GitHub Actions 自托管 Runner 在国内的问题,归根到底是它和 GitHub 之间要长期、多域名地通信:注册看令牌时效,在线看服务与网络,排队看标签,执行看 codeload、存储与 git 各自是否走了线路。三个习惯能省很多排查时间:注册时现取令牌,代理统一写在 .env 而不是依赖系统设置,新 Runner 上线先跑一次完整工作流再迁移其他任务。
刺猬VPN 采用 HTTPS+AES 加密传输,自定义用户名和密码即可匿名注册,不需要邮箱和手机号;免费节点永久免费、不限流量、不限速,适合先验证 Runner 能否注册与构建;时长套餐有效期内不限流量、不限速,适合长期挂机的开发机。客户端带断线保护与按域名分流,一个账号支持多设备同时在线。GitHub 的计费与功能以官方最新条款为准,实际可用性取决于当前网络环境。
开发者的稳定通道:用刺猬VPN流畅访问 GitHub 与全球开发资源
刺猬VPN提供永久免费节点,不限流量;无需邮箱,自定义用户名即可匿名注册。一个账号支持多设备同时在线,实际可用性取决于当前网络环境。