跳到主要内容

退出码

每条 arc 命令都用退出码报告结果——0 表示成功,另有七个各不相同的非零值(其中一个已预留但还没有产出)——脚本不用读报错文本就知道遇到的是哪一类失败。

每条 arc 命令退出时都带一个可供脚本分支判断的数字。非零值不止一个,正是关键所在:"你要的路径不在"、"你把命令拼错了"、"没有 daemon 在跑",这三件事需要脚本做三种不同的反应,而分辨它们不该依赖去匹配英文报错文本。

退出码含义适用范围
0命令做了你要它做的事所有命令
1不在——或者,对 service start 来说,已经在了所有命令
2权限拒绝已预留——这个版本里没有命令会返回它(见下文)
3实例有记录但没有在跑(stoppedstartingarc service status
4实例记录说它在跑,但它的进程已经没了(deadarc service status
5运行时错误,所有用法错误都算在内所有命令
6这条命令需要一个 daemon,而没有 daemon 在跑所有命令
7在没有 llm renderer 的命令上要求了 --view llm任何命令的 --view llm

注意"适用范围"这一列。上面的 34arc service status 对实例记录的自有解读,并不是对整个 CLI 的承诺:在别处这两个数字表示运行时的通用含义——3 是冲突,4 是部分成功——而且 4 有真实的产出方,就是一批 arc did issue 里有的 provider 成功、有的失败的情况。把 rc == 4 读成"daemon 死了"的脚本,会把那一批误判。只在 arc service status 上按 4 分支。

2 在枚举里,但这个版本没有任何产出点。下面 2 那一节写了这是怎么核实出来的,不是拍脑袋断言。7 的适用范围很窄:它只在 --view llm 上触发,而且只在没有 llm renderer 的命令上;每条命令依然接受 --view default / --view json / --view human

下面每一节都是对应场景的一次真实运行,对照的是 arc 2.0.0-beta.48(构建 5a5316bde,2026-09-10)。单看版本号分不清你手上是哪个构建——2.0.0-beta.48 这一轮周期里已经指过不止一个二进制——所以在相信这页上任何输出逐字节一致之前,先跑一遍 arc --version,把它的第三个字段(commit)跟这里写的对一下。这张表要读作"这些码分别是什么意思",而不是"arc 可能返回的全部数字":以别的方式失败的命令同样以非零退出,后续版本也可能新增退出码。

0 —— 命令做了你要它做的事

bash
$ arc service list
NAME          ID                PORT   STATUS   HOME                          SOURCES
(no instances)

结果为空同样是成功。没东西可列不是失败——去要一个具体的、而它不在,这才会拿到 1

1 —— 不在,或者已经在了

读一个不存在的路径:

bash
$ arc afs read /no-such-file --instance notes
ERROR: No data found for path: /no-such-file

指名一个从未创建过的实例:

bash
$ arc service status --instance nope
ERROR: no instance named "nope". `arc service list` shows 1

以及——这条值得记住——去 start 一个已经起着的实例:

bash
$ arc service start --instance notes
ERROR: instance "notes" is already running
       pid 93652, port 61430, started 15s ago
       use `arc service restart --instance notes` or pick another name

最后这条是 1,不是 5。这个码的意思是"你点名的东西不处于你需要的状态",既涵盖"它不存在",也涵盖"它已经存在了"。这不是用法错误,所以不是 5

2 —— 权限拒绝,定义了但还没有产出

运行时的退出码枚举把 2 留给了 PermissionDeniedError,这个类确实存在于 CLI 自己的错误模块里。但这个版本里没有任何东西抛出它:没有命令会构造 PermissionDeniedError,而 CLI 之下 AFS 层抛出的权限失败也没有被转译成它——它就那样原样继续往上传播,跟其他没被特殊处理的失败一样落到 5。这一条是核实过的,不是假设:拿 chmod 000 做出一个读不了的文件,直接复现了真实行为。

bash
$ arc afs read /vault/locked.txt --standalone
ERROR: EACCES: permission denied, open '/tmp/arc-perm-test/secret/locked.txt'

这条命令退出码是 5。把 2 当作协议预留给一个 CLI 目前还没做出区分的数字,而不是实践中会遇到的一个。

3 —— 实例存在,但没有在跑

bash
$ arc service stop --instance notes
Service stopped: notes
$ arc service status --instance notes
  Instance: notes
  ID:       ab5aa97074c454a0
  Status:   stopped
  PID:      93652
  Port:     61430
  URL:      http://127.0.0.1:61430
  Home:     /tmp/arc-docs-demo/notes
  Note:     PID / Port / URL above are the LAST KNOWN values from this instance's previous run, not a live process.

上面省略了 VersionCommitCheckoutSpaceSourcesHostStarted 几个字段。停掉之后 pid、port、URL 照样报出来,Note: 那行明确说了这些是历史值——--json 里同一件事表现为 lastKnown 标记。

starting 同样返回 3,这一点在你写"等它起来"的循环时很要紧:3 的意思是"还没就绪",不是"起不来了"。冷启动时这个窗口有几秒钟,轮询 status 会依次看到 stoppedstarting(退出 3)→ up(退出 0)。把 3 当作"继续等",把 4 当作"别等了"。

4 —— 记录说它在跑,但进程已经没了

正常的命令序列走不到这里,因为这个码描述的是损坏,而不是某种选择。要看到它,就起一个实例,然后直接杀掉它的 daemon,让注册表那行仍然声称 up,而背后的进程已经不存在:

start 自己也会打印一整块状态;下一步要用的 pid 就在它的 PID: 那行。下面两块都只截取了这里用得上的字段。

bash
$ arc service start --instance notes --home /tmp/arc-docs-demo/notes
  Instance: notes
  Status:   up
  PID:      95288
  Port:     61430
  Home:     /tmp/arc-docs-demo/notes
$ kill -9 95288
$ arc service status --instance notes
  Instance: notes
  ID:       ab5aa97074c454a0
  Status:   dead
  PID:      95288
  Port:     61430
  URL:      http://127.0.0.1:61430
  Home:     /tmp/arc-docs-demo/notes
  Note:     PID / Port / URL above are the LAST KNOWN values from this instance's previous run, not a live process.

崩溃、被 OOM 杀掉、机器重启——任何没走 arc service stop 就结束了进程的情况,拿到的都是 dead。跟 3 分开是有价值的:stopped 是有人选择的状态,dead 是没有人选择的状态。arc service gc 清理的正是且仅是这个状态的记录。

5 —— 运行时错误,用法错误也算

这是覆盖面最宽的一个码。把命令行写错的每一种方式都落在这里。下面三种在你看到的内容之后还会继续打印用法说明——第一种打印完整命令列表,另外两种打印该命令自己的帮助。未知命令:

bash
$ arc serivce list
ERROR: Unknown command: "serivce"

Did you mean?
  arc serve
  arc service

未知选项:

bash
$ arc service list --bogus
ERROR: Unknown argument: bogus

缺少必填参数:

bash
$ arc space rm
ERROR: Not enough non-option arguments: got 0, need at least 2

以及越过命令行之后,运行时无法路由的请求:

bash
$ arc afs exec /no-such-action --instance notes
ERROR: No module found for path: /no-such-action in namespace 'default'

5 同样覆盖"命令跑对了、但报告了一个真实世界的问题"——arc network doctor 只要有检查失败就以 5 退出。所以单看 5 并不能告诉你是你写错了、还是外面有东西坏了;那是报错文本的职责。

6 —— 这条命令需要 daemon,而没有 daemon 在跑

bash
$ arc afs ls /
ERROR: No AFS daemon is running for instance "default".
Start it with:  arc service start
Or use --standalone for ad-hoc mode (no runtime state)

第二行的建议命令只会照抄你实际打过的那些参数——不带 --instance--home 就建议裸的 arc service start;自己传了 --instance foo --home ~/foo,它就照原样建议回去,绝不会冒出一个你没打过的值。6 存在,就是为了让这种情况不读报错文本也能跟 5 区分开。"前置条件没满足、起个 daemon 就能解决"跟"命令执行失败"是两回事,而报错文本把修法写出来了。指名的实例其 daemon 处于 stoppeddead 时,回来的同样是 6,不只是 default 才这样。

7 —— 要求了 --view llm,但这条命令渲染不了

--view llm 是全局都接受的,但不是每条命令都有 llm renderer 来处理它,而一个没实现的会 fail closed,不会悄悄退回默认视图。arc network doctor 没有 llm renderer:

bash
$ arc network doctor --view llm
ERROR: --view llm is not implemented for `network doctor`. This command has no llm renderer (declare ⇒ execute; will not silently fall back to default).

arc afs ls 是实现了的,同一个 flag 用在支持它的命令上就会成功:

bash
$ arc afs ls / --standalone --view llm
ENTRY /spaces CHILDREN=-1 DESC="Local DID Space logical roots"
ENTRY /peers CHILDREN=-1 DESC="Dispatchable ARC hosts (always includes local)"
ENTRY /ash CHILDREN=-1 DESC="ASH pipeline DSL for deterministic data pipelines"
ENTRY /dev CHILDREN=-1
ENTRY /modules CHILDREN=-1
ENTRY /team CHILDREN=-1
ENTRY /.knowledge KIND=afs:system CHILDREN=-1 DESC="Provider capability index"
ENTRY /.meta KIND=afs:system CHILDREN=-1 DESC="Root metadata and mount info"
ENTRY /.actions KIND=afs:system CHILDREN=-1 DESC="Root-level executable actions"
TOTAL 9

对脚本来说要紧的区分在这里:一个不认得的 --view 值(比如 --view bogus)是参数解析就抓到的用法错误,跟其他写错的 flag 一样退出 5——

bash
$ arc service list --view bogus
ERROR: Invalid values:
  Argument: view, Given: "bogus", Choices: "default", "llm", "human", "json"

——而在没有 llm renderer 的命令上用 --view llm,是一个合法、认得出的值,只是这条命令目前实现不了,退出 7。没有这个区分,脚本就没法不解析英文文本地分辨"我把 flag 打错了"和"flag 是对的,只是这条命令还不支持"。