3172 字
约 10 分钟
21
S27-A07 · 自动化的边界:哪些环节该写脚本

"写了五十个脚本,一半没人用"——问题通常不在写得差,而在该不该写从来没被判断过。写的反馈即时(跑通就有成就感),成本却延迟出现:三个月后参数靠记忆、半年后报错没人修、换人接手直接废弃。等仓库躺满半死脚本,清理成本比当初手写还高。下面给判断框架:收益来源、三个前提、成本构成、失败模式、升级判据。


1. 脚本的收益只来自三处

收益来源 计算方式 典型量级
省下的人工时间 单次耗时 × 年执行次数 高:每天跑、单次十几分钟
减少的人为错误 错误率降幅 × 单次错误代价 高:手工步骤多、易漏
让流程可复制 新人上手时间下降 中:需交接或多人执行

三项都不成立时,脚本的唯一价值是"写得爽"。顺序固定:先频率,再错误代价,最后可复制性。频率不够的,后两项再好也不值得——维护成本按年计,收益按次计。

2. 三个前提,缺一不可

前提 判据问句 缺了会怎样
重复频率 一年执行多少次? 一年两次的,写比手做更慢
步骤稳定 流程最近半年变过几次? 每月都变,脚本永远在改
错误可检 跑错了怎么发现? 静默跑错,比不跑更危险

第三个最容易被忽略也最致命:前两个决定"值不值得写",第三个决定"敢不敢用"。

3. 该写与不该写

场景 判断 理由
每天定时取数、聚合、出报表 该写 高频、固定、结果可核
发布前固定检查清单 该写 高频、漏一步就出事
批量改名、批量转码 该写(带确认) 固定,人工容易漏
一年两次的年度归档 不该写 写+调的时间超过手做
每次都要看情况决定的排查 不该写 判断密集,脚本只会误导
需要对外担责的审批动作 不该全自动 责任必须落在人身上

后三行不是"技术难",而是投入产出比或责任结构不允许。这层判断不需要技术能力,只需要诚实。

4. 成本的真实构成

新手只算第一项,所以普遍低估:

成本项 内容 相对量级
编写 写通主路径 1
维护 依赖升级、参数变、上游改 2–3(按年累计)
失效排查 定位脚本错还是环境错 1–2
交接 让别人能读懂能改 1(有文档)否则 3

维护成本主要来自外部变化:上游改字段、路径变了、权限模型换了。脚本几乎不会自己坏,坏的是它依赖的世界。设计期压维护面即可:少依赖、少硬编码、出错早暴露。

5. 半自动:机器做枯燥段,人做判断段

全自动与全手动之间有一大片空间,多数场景的最优解在这里:

环节 谁做 形态
收集、汇总、比对 机器 一条命令出结果
异常标注 机器 输出"待人工确认"清单
最终决策与执行 人 看清单后确认或修正
# 机器只做前半段,判断留给人
report=$(collect_and_diff)                 # 只读、可重跑
echo "$report" | grep -E '^(DIFF|MISSING)' || { echo "无差异"; exit 0; }

# 有差异不自动处理,落成待确认文件
echo "$report" > /tmp/review-$(date +%F).txt
echo "待确认 $(grep -c '^DIFF' /tmp/review-$(date +%F).txt) 项"

三个好处:判断仍由人做、枯燥段被压缩、失效时后果有限;代价是一次人工确认。

6. 脚本腐化的四个信号

信号 表现 处置
半年没跑过 想不起它存在 删,或归档注明原因
报错没人修 输出全红字,大家绕开 修或删,别留噪声
参数靠记忆 只有作者知道传什么 补 --help 与默认值
需要"先手动改一行" 每次跑都要编辑文件 改成参数,否则不算脚本

根因几乎总是一个:没有主人。最有效的团队规则是"每个脚本写一行 owner",而不是要求全部写文档。

7. 失败模式:静默失败最危险

失败模式 后果 防御
静默失败 以为成功,实际没做 退出码 + 结果断言
部分成功 一半改了、一半没改 幂等 + 可重入
越权执行 一次错操作被放大 最小权限账号
重复执行 重跑产生双份数据 幂等键/前置检查

原则只有一条:**宁可吵醒,也不要沉默。**脚本要自己声明成功,不能靠"没报错"推断成功。

#!/usr/bin/env bash
set -euo pipefail          # 任一步失败即中断,未定义变量报错

target=/data/out/report.csv
before=$(wc -l < "$target" 2>/dev/null || echo 0)
do_the_work
after=$(wc -l < "$target" 2>/dev/null || echo 0)

[ "$after" -gt "$before" ] || { echo "FAIL: 行数未增长" >&2; exit 2; }
echo "OK: $before -> $after"

set -euo pipefail 挡住最常见的事故:中间命令失败、脚本继续跑,最后打印"完成"。

8. 幂等与可重入是硬要求

操作 幂等做法 不幂等的后果
创建资源 先查存在性,存在即成功 重跑产生重复条目
更新配置 全量覆盖(目标态) 追加式改配置越跑越乱
发通知 带去重键,或先标记已发 群里刷屏,读者开始无视

判断幂等有个简单测试:**连跑两次,结果应一致。**不一致处就是重跑会出事的地方,而自动化里最难排查的故障几乎都来自"重跑一次"。

9. 触发方式的三种与各自风险

触发方式 优点 风险 适用
手动 完全可控,出事有人在场 依赖人的记忆 低频、有判断
定时 稳定,不依赖人 环境变了照跑,可能跑错窗口 取数、巡检、备份
事件 实时,耦合低 风暴、重复、乱序 数据同步、通知

定时任务的坑是跑在错误的时刻:节假日、月初、上游维护窗口。规避靠给脚本一个"允许运行时间窗",窗外退出并留一行日志。

事件触发的坑是重复与乱序:同一消息投两次,或先到的后处理。只能靠幂等与版本号解决,靠脚本内部状态机硬扛会失败。

10. 告警与兜底:脚本挂了谁知道

没有告警的定时任务等于没有。最小可用方案是心跳:

# 成功执行时才刷新心跳
date +%s > /var/run/report-gen.heartbeat

# 独立检查:心跳过期就告警(比查进程可靠)
now=$(date +%s); last=$(cat /var/run/report-gen.heartbeat 2>/dev/null || echo 0)
[ $((now - last)) -lt 90000 ] || echo "report-gen 超 25h 未成功" | notify

心跳比"进程在不在"可靠:进程在但卡住、跑完但结果错,查进程都看不出来。兜底还要回答:**脚本没跑成,流程怎么继续?**通常是"有手动路径",且要写下来、偶尔演练;否则只是把单点故障从人搬到了脚本。

11. 权限与审计

做法 目的 代价
专用账号而非个人账号 人走脚本能跑,权限可追溯 一次授权配置
最小权限 出错时影响面有限 需拆分脚本职责
动作留日志(谁、何时、改了什么) 事后可归因 一点存储与实现成本
高危动作走人工闸门 不可逆操作不自动执行 每次几十秒确认
# 用固定账号跑,脚本里不出现个人凭证
sudo -u opsbot /opt/ops/bin/report-gen.sh

# 高危动作:只打印将要执行的内容
echo "将删除 $n 条记录:$(echo "$ids" | head -3)..."
echo "确认后执行:./purge.sh --ids-file /tmp/ids.txt"

用个人账号跑定时任务是隐性债:此人调岗或离职,任务悄然停摆且无人知晓。

12. 从脚本到工具的升级判据

判据 脚本够用 该升级为工具
使用者 只有我 第二个人开始用
输入形态 固定参数 组合多变,需校验与提示
失败处理 我看日志就行 别人看不懂日志

"有第二个人用"是最清晰的信号:从这一刻起 --help、错误信息、默认值、退出码都是接口,而接口要维护。升级不等于重写,多数情况下把参数解析与错误输出做规范就够。

13. 度量

指标 口径 判读
节省时间 单次节省 × 次数 − 维护工时 为负就该删
失败率 失败次数 ÷ 执行次数 上升说明环境在变
无人值守率 无需人工介入即成功的比例 低说明半自动环节太多
维护工时 每月花在修它的时间 超过收益一半就该重估
saving = per_run_saved * runs_per_year - maintenance_hours
maintain_share = maintenance_hours / total_hours_saved

maintain_share 超过 0.5 是明确信号:它在拖累你而不是帮你。此时正确动作通常是删掉它、改回清单式手动流程,而不是继续修。

14. 排错

现象 常见原因 处理
跑完但结果不对 静默失败,缺断言 加行数/校验和断言,失败即退出
重跑一次数据翻倍 非幂等写入 改目标态覆盖或加去重键
换人接手就废 参数靠记忆、无 owner 补 --help、默认值、owner 行
定时任务悄悄停了 个人账号、无心跳 专用账号 + 心跳告警
每月都在改 步骤不稳定,本不该自动化 降级为清单 + 半自动

15. 边界:这些环节手做更划算

场景 为什么不该写 替代
一年跑一两次 编写调试超过手做 写成清单照着做
步骤每月都在变 维护成本永远高于收益 半自动:机器收集,人执行
判断密集、每次不同 脚本覆盖不了分支 只工具化"信息收集"
需现场判断与担责 责任无法转移到脚本 人执行,脚本做记录
环境本身不稳定 失效排查成本高 先修环境,再谈自动化

一句话收口:自动化的门槛不是"能不能写出来",而是"一年跑几次、错了谁发现、坏了谁修"。三问答不上来,就先别写。


16. 自测

  1. 你手上的脚本,收益来自省时间、减错误还是可复制?哪一项其实不成立?
  2. 三个前提里,你的脚本最常缺哪个?缺它时发生了什么?
  3. 维护成本的主要来源是什么?举一个"脚本没坏、世界变了"的例子。
  4. 什么失败最危险?你的脚本怎么声明"成功"?
  5. 怎么用一个简单测试判断脚本是否幂等?
  6. 哪些环节手做比写脚本划算?你打算删掉哪个脚本?
S27-A07 · 自动化的边界:哪些环节该写脚本
https://www.clxhxhhr.top/posts/6235/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。