# 机器

机器（控制台上叫「服务节点」）是真正跑会话的电脑：Mac 或 Linux。会话会在机器之间搬，成员不用挑哪台。

> **托管客户**：机器由我们加、维护、下线，这一页你不用动手。你能在「服务节点与客户端」页上看到每台机器的状态；看到「维护中」「失联」时会发生什么，读本页后半的「状态」一节就够了。机器不够用、要多开几个人，告诉我们。

## 状态：在线 · 维护中 · 失联

| 状态 | 是什么 | 入口怎么对待它 |
|---|---|---|
| **在线** | 正常报到 | 一切照常 |
| **维护中** | 管理员标了「要下线」 | 不往它派新会话；上面已有的会话照跑 |
| **失联** | 大约 15 秒没报到 | 只标记：它上面的会话在列表里变灰；它们手上的任务认领 30 分钟后释放，**不会自动在别处重开** |

「失联」压过「维护中」：标了维护又断了的机器就是失联。

在哪里看：控制台「服务节点与客户端」页的卡片徽章；成员客户端侧栏顶行 `● mac-a 22 · ◐ mac-b 3 维护中 · ○ linux-a 0`（● 在线 · ◐ 维护中 · ○ 失联）；命令行 `fleet hub machines`，每台机器的状态、会话数、负载、账号数（备用 · 已用 / 上限）。

## 省下多少内存

打开一台机器的详情，在「负载与内存」里看会话总数、在算、已停放、省下的内存和空闲常驻。没有停放会话时隐藏「已停放」；旧节点尚未上报时整行隐藏。统计汇总这台机器上已上报的托管登录，任何登录缺少计量时不显示部分合计。

「省」是当前 `@park_state=停放中` 的会话按身份读取最后一次 park 动作行的 `rss_mb` 之和（含外壳的进程树 RSS）；接回后不再计入。没有对应动作行时可读 `@park_rss_mb` 快照，没有读数显示「节省量未采到」。未报告停放状态时停放数为 0。

「空闲常驻」与本批指标使用同一口径：本轮已结束（done / looping / 等你），至少 60 秒 CPU 采样少于每分钟 0.5 秒，且无人正在观看、没有后台命令。只累加这些会话含外壳的进程树 RSS；非零时写明老外壳、等待停放等原因。采样不足时空闲数、在算数和空闲 RSS 保持未知，机器页暂不显示计量行。

节点上 `fleet doctor --park` 可单独读同一份计数。按 UTC 日查看停放账本汇总：`python3 ~/.claude/fleet/bin/fleet_park_metrics.py daily --day YYYY-MM-DD`，包含停放、接回、失败、顺延次数，以及成功接回的 p50 / p95；定时接回有约定与开始时刻时才计算 30 秒内准时率，无样本显示未知。

## 只让一个人用某几台机器

每台机器上的登录都还在，只是暂时不让某个人用其中几台：管理员给这个人设一张**机器白名单**。

```sh
fleet-machine-policy.sh set gh:2987262 linux-a   # 只许用 linux-a
fleet-machine-policy.sh show gh:2987262                # 每台机器：开放 / 停用 + 原因
fleet-machine-policy.sh clear gh:2987262               # 撤掉名单：恢复全部机器
```

名单外的机器上：他连不进去（`fleet <机器>` 会说「这台机器暂未对你开放，可用：…」），新会话不会派过去（自动选机和点名都不行），已经开着的会话在半分钟内停用，列表里显示「已停用（管理员限制）」。他在那台机器上的登录、家目录、记录都不删，撤掉名单后原样恢复。不设名单 = 全部机器都能用。

## 加一台机器（自托管）

1. 控制台「服务节点与客户端」→ **加服务节点**。弹窗给出一个加入码和一行命令，1 小时内有效、只能用一次。
2. 在那台机器上执行那一行命令（要 sudo）。Mac 上它形如：

   ```sh
   curl -fsSL https://hub.example.com/install/bin/fleet-node-install.sh | sudo bash -s -- --hub https://hub.example.com --join <加入码>
   ```

   已经装了 `fleet` 的 Mac 也可以 `sudo fleet node install --join <加入码>`。Linux 照弹窗给的命令执行。
3. 等它出现在页面上、徽章「在线」，就加好了。

同一条命令再执行一遍就是修复：已经做好的步骤会跳过，坏了的重新做。加入码不要贴进聊天、工单或提交记录里。

每台机器能开几个人的账号默认是 10 个：`fleet hub set fleet.node_user_cap.mac-a 20` 改。设置页「每台电脑备好空账号」打开后，每台机器预先备几个空账号，新人登录即用。

## 计划下线：升级、搬机、换硬件（自托管）

每一步都是人做的，没有哪一步会自动关机。

1. **标维护中**：卡片上 **维护** → 填原因（比如「升级系统，预计 40 分钟」）。或命令行 `fleet hub set fleet.node_maintenance.mac-a "升级系统"`。从这一刻起不往它派新会话。
2. **把空闲的会话搬走**：在这台机器上，每个账号各执行一次

   ```sh
   ~/.claude/fleet/bin/fleet-evacuate.sh --dry-run   # 先看会搬哪些、去哪
   ~/.claude/fleet/bin/fleet-evacuate.sh             # 真搬
   ```

   只搬空闲、没有未提交改动的会话，正在干活的一个都不碰；搬过去的会话在另一台机器上原样接着。输出的 `left N` 是还留着的，等它们做完再执行一次。
3. **确认**：卡片上会话数降到 0（或只剩你决定让它随机器一起断的）。
4. **关机、升级**。
5. **回来以后**：开机，机器自己连回入口，徽章回到「维护中」。在它上面执行 `fleet doctor` 看没有红项，然后卡片上 **结束维护**（或 `fleet hub unset fleet.node_maintenance.mac-a`）。

## 意外下线：断电、死机、断网

- **成员**：什么都不用做。`fleet` 会自动落到别的在线机器；失联机器上的会话暂时动不了，要紧的事在别的机器上重新开（任务认领 30 分钟后自动释放）。
- **自托管的管理员**：先判断是断网还是真停了。断网时会话其实还在跑，网回来一切自动复原。真停了：机器回来后**先**标维护中（不然入口立刻往它派活），执行 `fleet doctor` 检查；同一个任务若已经在别的机器上重开，留新的、关掉旧的，再结束维护。
- **托管**：我们处理，并在恢复后告诉你。

## 永久移除一台机器（自托管）

1. 先按「计划下线」把会话搬空。
2. 机器上的每个人的账号先收回（[开号与删号](accounts.md)）。
3. 卡片上 **移除**：这台机器的入场证立刻作废，卡片消失。以后要再接回来，得用新的加入码。
