06 · 超时、权限、日志与 UI
一个系统维护工具的可靠性,往往由“系统命令不响应时怎么办”决定,而不是由正常路径决定。
超时是一种依赖隔离
Spotlight、mdls、du、diskutil、system_profiler 等命令可能因磁盘、网络卷或系统服务异常而卡住。run_with_timeout 统一处理 gtimeout/timeout 能力与回退,timeouts.sh 给短查询、扫描、外部卷等场景定义不同预算。
调用者仍需决定超时语义:发现应用元数据超时可以降级为未知;Trash 或验证超时则不能假装成功。统一的是“等待有上界”,不是“所有超时都忽略”。
sudo 只建立一次会话
清理和优化先集中请求管理员权限,再由 keepalive 维持凭据;若用户拒绝,Optimize 会一次性把 sudo 能力标记为不可用,各任务返回 skipped,而不是每个任务重复弹出密码提示。
测试模式设置 MOLE_TEST_NO_AUTH=1,sudo helper 必须硬拒绝真实授权。测试脚本还在 PATH 前置假的 sudo、osascript 和 launchctl,把“单元测试意外操作宿主机”的风险变成可观察失败。
临时目录也有信任边界
公共 temp 模块创建会话级临时空间并用 trap 清理。root 模式的 dry-run 预览先写 root 所有的 staging,再安全发布给调用用户,避免直接在用户可替换的目标上以 root 写文件。
安装器还有一个范围极窄的 safe_rm:只接受 TMPDIR 或 /tmp 下的子项,拒绝临时根本身和任何非临时路径。这是“独立安装脚本无法依赖完整 core”时的最小安全实现。
UI 不应污染机器输出
颜色、spinner、分页菜单和 summary block 集中在 core UI。命令会检查 TTY:非交互输出关闭动画;Status 自动转 JSON;Uninstall --list 在管道中直接输出 JSON。NO_COLOR 也被尊重。
这保证同一命令既能服务人,也能服务脚本,而不是让调用者去剥 ANSI 转义和进度字符。
日志是另一条产品 API
Mole 区分:
mole.log:一般运行日志;- debug session:调试细节与风险说明;
operations.log:命令会话、动作与结果;deletions.log:删除对象、模式、大小、结果的 TSV 证据。
mo history --json 将这些记录转成可消费数据。会话开始/结束使批量动作可以关联,失败任务也进入记录,而不是只统计成功数量。
关键源码索引
lib/core/timeout.sh:有界执行适配。lib/core/timeouts.sh:场景化时间预算。lib/core/sudo.sh:授权与 keepalive。lib/core/base.sh:基础环境与临时资源生命周期。lib/core/log.sh:会话与操作日志。
下一章开始进入命令流水线,先看 Clean 如何把大量目标规则压缩成可审计的删除计划。