一次「cargo 突然消失」之后:聊聊 GitHub Actions + 本机 self-hosted runner 的正确打开方式

最近踩了个挺典型的坑:
前一天还能正常构建,第二天终端里 cargo --version 直接变成 command not found。更离谱的是,~/.zshrc 里 PATH 配置明明还在。

当时第一反应是 shell 配置坏了,结果查下来不是。

现象看起来像 PATH,实际上是“断链”

先看几个关键信息:

  • PATH 里有 ~/.cargo/bin
  • ~/.cargo/bin/cargo 存在
  • cargo 是个软链:cargo -> rustup
  • 真正的 ~/.cargo/bin/rustup 文件没了

也就是说,不是找不到 cargo,是 cargo 指向的目标没了。

这种情况很容易误判成“环境变量没生效”,其实是工具链启动器被清理了。

根因:self-hosted runner 和开发环境共用 HOME,被 CI 的缓存清理逻辑误伤

我项目是 GitHub Actions 跑在本机 self-hosted runner 上(同一个用户)。
Workflow 里用了 swatinem/rust-cache@v2,默认 cache-bin: true

这件事在 GitHub-hosted runner 上通常没问题,因为机器是一次性的;
但在长期运行的 self-hosted 上,~/.cargo/bin 是你本机常驻环境的一部分,一旦 post-cleanup 动到它,就会出现这种“本机 cargo 消失”的事故。

一句话总结:CI 没删你代码,但删了你本机共享环境里的关键二进制

最小改动修复

我最后没把缓存全关,而是只关了 bin 缓存:

1
2
3
4
5
- name: Cache Rust build
uses: swatinem/rust-cache@v2
with:
workspaces: './src-tauri -> target'
cache-bin: "false"

这行建议至少加在所有 self-hosted 的 Rust job 里(比如 macOS / Linux)。
这样还能继续缓存 registry/git/target,构建速度保住,同时避开 ~/.cargo/bin 被清理。

如果你现在已经中招了,可以先这么做

1
2
3
4
curl https://sh.rustup.rs -sSf | sh -s -- -y
source "$HOME/.cargo/env"
cargo --version
rustup show

另外建议顺手检查一下:

1
2
ls -l ~/.cargo/bin/cargo
ls -l ~/.cargo/bin/rustup

如果 cargo -> rustup 但 rustup 不存在,就是同类问题。

这类问题的通用治理建议(不只 Rust)

这次是 Rust,换成 Node/Python/Go 也可能发生。核心原则就两条:

  1. 不要让 CI 和你的日常开发环境“共用生活空间”
    最好给 runner 单独用户(甚至单独机器/容器)。

  2. 缓存“构建产物”和“依赖仓库”,少碰“全局工具目录”
    例如 ~/.cargo/bin~/.nvm~/.pyenv 这种位置,一旦被清理就是系统性故障。

再补一个实用建议:
给 self-hosted runner 加个构建前自检脚本(比如检查 cargo/node/python 是否可用),早失败比跑完才发现要省很多时间。

写在最后

self-hosted 的优势是快、可控、省钱;
代价是你得把“本机”当“生产环境”来管理。

这次问题本身不复杂,但很有代表性:
不是代码错了,是运行边界没隔离好。

如果你也在用 GitHub Actions + self-hosted,建议现在就看一眼你的 workflow:
缓存到底是在加速构建,还是在悄悄改你的机器状态。

Comments

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×