1560 字
约 5 分钟
3
退出码契约:怎么给外部一个清晰的"成/败/大错"信号

退出码契约:怎么给外部一个清晰的"成/败/大错"信号

通用工程思想 · 编程博客 · 第 9 篇 主题:程序跑完,怎么让"外部的调度者"(定时任务 / CI / 服务器脚本)一眼看懂"这趟成功没"?靠退出码。这篇讲怎么设计一套清晰的"结论码"。


开场一个比喻

你家楼下有个外卖柜。每一单外卖送到,柜子会显示一个状态:

  • "已到柜" → 你可以去取;
  • "在途中" → 还得等;
  • "送错了" → 要人工处理;
  • "柜子坏了" → 这单有问题,得找客服。

这些状态,就是柜子和"取外卖的人"之间约定的一套信号。它让"人/别的系统"不用问细节,一看就知道该怎么应对。

程序的退出码,就是程序和"调度它的人"之间的这套约定信号。


先理解:为什么要有退出码

你写的不是"孤零零跑一下"的程序,往往是被别的东西调起来的:

  • 定时任务(cron)每天到点调它;
  • 持续集成(CI)提交代码后调它;
  • 服务器脚本调它。

关键问题:"它怎么告诉外面'我这趟干得怎么样'?" 命令行的答案就是——退出时带一个数字(退出码)。外面看这个数字,就知道要不要报警、要不要重试、要不要人工看。

没有这套约定,外面只能傻等——不知道成功没,也不知道该不该响警报。


一套好的退出码,该是"少而清晰"

很多人的直觉是"给每种错误一个码",其实反了——好的退出码应该少、每个含义都明确,因为外部的调度器只需要"做几个决定":

调度器真正想问的问题 需要几个信号
成功了,一切正常? 一个"成功"码
有失败,但还能接受? 一个"部分失败"码
出了大问题,得立刻注意? 一个"致命错误"码
被人为中断了? 一个"取消"码

所以常见的一套大概4~5个就够:

退出码 含义 外部通常怎么做
0 成功 什么也不用做
1 有失败(非致命) 可告警、可看日志
2 致命错误(配置/凭据/安全/资源) 重点排查、通知人
130 被用户取消(Ctrl+C) 自行判断要不要重跑

关键:信号要"能被一个判断消化",而不是"罗列所有细节"。 细节放日志,退出码只给"该往哪处理"的方向。


更重要的一课:成败要"分级",不能只分"成败"

新手最容易犯的错是只有两种:成功 / 失败。但这根本不够——因为它没法表达**"坏的程度"**:

情况 该算什么 为什么不能简单叫"失败"
所有对象都成功 成功(0) 正常
单个对象失败,但整体继续 有失败(1) 别把它当成"天塌了"去报警
全局坏了(登录/配置/凭据) 致命(2) 这个必须立刻注意
用户主动中断 取消(130) 不是出错,是用户选择

所以设计的精髓是:先分清"致命 / 可容忍 / 成功 / 取消",再给每种一个明确结论码。 不是"出错就一个码",而是"不同严重度的错误,给不同码、触发不同处理"。


常见的坑

表现 后果 破法
只有一个"失败"码 一切非成功都归 2 单对象小败也触发"致命"告警 分级:致命/可容忍分开给码
不写退出码/永远退出 0 外面以为成功 悄悄挂掉没人发现 明确 0=成功,其它=各种失败
用了奇怪的私有大数字 外部调度器不认 报警逻辑失灵 用常规的小数字,并文档化
只码不说明 知道"是2"不知"为什么" 得去翻日志猜 报错信息 + 日志里写清原因

用的时候注意(边界)

  • 退出码是给"调度者"看的,不是给人看的:人看日志、看提示;调度者看退出码。别把一层意思既塞进日志又塞进码。
  • 别为每一种错误设个码:会变成没人维护得动的巨大映射表。保持少而清晰,细节进日志。
  • 要有文档:这套码的含义、什么时候返回哪个,写成一张表放 README——不然没人知道 2 是啥意思。

落地检查清单

  • 是否给"成功 / 有失败 / 致命 / 取消"这几种基本结局,配了清晰的退出码?
  • 成功对象、单对象失败、全局致命,是否被分级处理(而不是一律叫"失败")?
  • 退出码是否都写成"外部调度器能直接判断做啥"的简单数字?
  • 每个失败码是否都伴随了足够原因(报错信息/日志)?
  • 这套退出码是否已写成文档,让外部使用者知道含义?

一句话带走

"退出码是程序和'调度它的东西'之间的一纸合约:少而清晰地告诉外面'成功、可容忍失败、致命、取消'各是哪种。真实世界的失败有多种严重度,好的合约按严重度分级,而不是一刀切成'成/败'。"

退出码契约:怎么给外部一个清晰的"成/败/大错"信号
http://clxhxhhr.top/posts/546/
作者
clxstart
发布于
2026-09-08
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。