03 · CLI 路由与启动链
顶层
mole有意只做路由。越靠近入口,越不应该复制业务规则。
启动阶段
入口首先启用 set -euo pipefail,确定脚本目录。history 是一个特殊快速路径:在完整公共库加载前直接分发,减少查看历史所需的启动成本。随后才 source common.sh 与命令帮助,声明版本 1.48.1。
`mo` ──exec──► `mole`
│
├─ `history` ──► 早期快速分发
├─ 无参数且 TTY ─► 交互菜单
└─ 子命令 ──────► bin 脚本 / manage 函数mo 本身几乎没有逻辑,只把参数原样 exec 给 mole。使用 exec 意味着不额外保留一个等待中的 Shell 进程,信号与退出码也更直接。
为什么有的命令 exec,有的 source
清理、卸载、优化、分析、状态等独立命令由新进程执行;update、remove 等管理动作需要使用当前安装上下文,因此加载管理模块后在当前进程调用。这个差异不是风格问题,而是生命周期与状态所有权的选择。
交互菜单最终也 exec 到具体命令。菜单不持有任务状态,因此用户退出 Clean 后不需要返回一个长期驻留的父菜单。
别名只在路由层消化
入口接受 optimise/analyse 等拼写别名,但内部文件和函数保持单一规范名称。这样兼容性留在边界,不会把多套名称扩散到日志、测试与任务注册表。
错误传播
set -euo pipefail 能尽早暴露未定义变量与失败管道,但也带来一个风险:放在命令替换中的网络探测若返回非零,可能在上层展示错误前结束进程。因此更新模块的“获取最新版本”函数有意以空字符串表示未知,并用 || true 把网络失败变为可处理状态。
设计评价
入口脚本保持薄是正确的:它只知道命令名、帮助与进程边界,不知道缓存目录清单或应用保护规则。代价是 source/exec 的差异需要测试覆盖,否则环境变量、trap 和退出码容易出现命令间不一致。
关键源码索引
mole#L1-L65:严格模式、history 快路径与公共库加载。mole#L231-L315:命令分发与别名。mo:薄启动器。lib/manage/update.sh:可恢复的版本发现。
下一章进入整套项目最重要的边界:一个候选路径如何被允许进入删除汇点。