退出码 0、日志干净,但一件事也没干成:自动化脚本的 9 种静默失败

自动化脚本的 9 种"静默失败":不报错、不崩溃、就是不干活

脚本跑完退出码 0,日志干干净净,一件事也没干成。

这种失败最难查,因为它不留下任何线索。下面 9 种是我实际踩过的,每一种都给出现象、真因、一条自检命令、修法。

1. 浏览器随父进程一起被回收

现象 :脚本里启动的 Chrome,等脚本跑完就消失了;下次再连接 CDP 端口直接 ECONNREFUSED。

真因 :浏览器进程是命令行会话的子进程,会话结束即被清理。用 Start-Process、schtasks、WMI 启动也躲不掉。

自检:

bash 复制代码
curl -s --noproxy '*' --max-time 3 http://127.0.0.1:9333/json/version
# 空输出 = 已经没了

修法 :启动和操作必须写在同一条命令里:

bash 复制代码
cmd //c start "" "C:/Program Files/Google/Chrome/Application/chrome.exe" \
  --remote-debugging-port=9333 --user-data-dir="C:\...\profile" --no-first-run \
  ; sleep 14 ; node your-script.js

2. curl 探测本地端口走了代理

现象 :明明服务在跑,curl 就是超时或返回代理的错误页。

真因 :环境里设了 http_proxy,本地请求也被送到代理去了。

自检:

bash 复制代码
env | grep -i proxy

修法 :探测本地端口一律加 --noproxy '*'。这条我记了很久才形成肌肉记忆。

3. 运行时版本被静默升级

现象 :昨天还好好的脚本,今天报 No such file or directory。

真因 :托管运行时被自动升级,路径里的版本目录变了(比如 Node 22.22.2-3 → 22.22.2-6)。写死路径的任务全部失效。

自检:

bash 复制代码
ls C:/Users/<你>/.workbuddy/binaries/node/versions/

修法:脚本里先探测再取用,别写死版本号:

bash 复制代码
N=$(ls -d /path/to/versions/*/ | tail -1)/node.exe

4. 定时任务到期自动停跑

现象:任务一直在列表里,状态还是 ACTIVE,但就是没执行记录。

真因 :任务设了 validUntil,过期后静默停跑,状态字段不更新。

自检:创建/修改任务时检查有效期字段;定期核对"最近一次执行时间"。

修法 :要么不设 validUntil,要么设一个远超预期的日期,并在任务描述里写明"到期前续期"。

5. 后台标签页里鼠标键盘全部静默失效

现象:坐标算对了、事件也发了,页面上毫无反应;同样的代码在前台标签就正常。

真因 :标签处于后台时 visibilityState === 'hidden',浏览器会抑制输入事件。

自检:

js 复制代码
document.visibilityState   // 'hidden' 就是它

修法:操作前先切前台:

js 复制代码
await send('Page.bringToFront');

顺带一提:后台标签里 window.screenX / screenY 也会返回 0,拿它算坐标就是错的(详见滑块验证码那篇)。

6. 灌入长文本时换行被吞掉

现象:脚本把 Markdown 塞进编辑器,结果所有换行消失,全文糊成一坨。

真因 :Input.insertText 对换行符处理不可靠,富文本编辑器(CodeMirror / Tiptap / Draft.js)尤其明显。

修法 :走剪贴板 + Ctrl+V:

python 复制代码
import pyperclip, time
pyperclip.copy(markdown_text)
# 聚焦编辑器后
pyautogui.hotkey('ctrl', 'v')

7. 二维码过期了但页面上没写"过期"

现象:脚本一直等扫码,等满十几分钟超时退出;页面上那个码其实早就失效了。

真因 :过期态的视觉表现是"模糊的码 + 中间一个刷新圈",innerText 里不含"过期"两个字,按文字判断永远判断不出来。

修法 :要么定时刷新二维码(点二维码框中心),要么看图------截图后人工确认。别指望文本匹配。

8. 接口返回 200,业务其实是失败的

现象:抓包看状态码全 200,事情没办成。

真因:业务错误码藏在响应体里。比如签到接口:

json 复制代码
{"code":10001,"msg":"今天已签到,请明天再来"}

HTTP 状态是 200,code 才是真相。再比如状态查询接口返回 200 但字段全是零值------那不代表"真的为零",可能只是它查的是另一套维度。

修法 :断言要打到响应体字段,不能只看 HTTP 状态。而且要先搞清楚哪个字段才是权威口径。

9. 状态查询接口和实际操作接口口径不一致

这是我踩得最狠的一条。

同一个签到功能,查询接口说 today_checked_in: false、streak_days: 0,看起来就是"没签到、连签断了"。但实际调操作接口,返回的是"今天已签到,请明天再来"。

哪个是真的?操作接口的回执是真的。 查询接口在这个上下文里返回的是另一套维度的数据(赛季维度,赛季未开启时字段全零)。

教训 :判断"做没做成",永远以操作接口的回执为准,不要用查询接口的状态字段去推断。

附:一条命令的自检清单

把上面最容易犯的几条串起来,开工前跑一次:

bash 复制代码
#!/usr/bin/env bash
# 自检:端口 / 代理 / 运行时路径 / 标签前台
PORT=${1:-9333}

echo "[1] CDP 端口"
curl -s --noproxy '*' --max-time 3 "http://127.0.0.1:${PORT}/json/version" \
  && echo "  OK" || echo "  ✗ 浏览器没起来(可能被回收)"

echo "[2] 代理环境"
if env | grep -qi 'http_proxy'; then
  echo "  ⚠ 存在代理,本地请求请加 --noproxy '*'"
else
  echo "  OK"
fi

echo "[3] Node 运行时"
ls -d "$HOME/.workbuddy/binaries/node/versions/"*/ 2>/dev/null | tail -1

echo "[4] Python venv"
ls -d "$HOME/.workbuddy/binaries/python/envs/"*/ 2>/dev/null | tail -1

跑完这四项,能挡掉一半的"脚本没反应"。

总结

这些坑的共同点:失败路径上没有报错。

所以写自动化脚本时,别只看退出码。关键动作后面要跟断言:

  • 点完按钮 → 断言 URL 变了 / 出现了成功文案
  • 提交表单 → 断言列表里多了一条
  • 调用接口 → 断言响应体里的业务码
  • 上传文件 → 断言页面上出现了新资源的 URL

没有断言的自动化,等于没有自动化。 它只是在安静地假装成功。

相关推荐
许雪里21 小时前
XXL-AI v1.4.0 发布|AI应用开发平台
agent·ai编程
EnCi Zheng1 天前
Agent 如何进行工具调用:从一次 Function Calling 到生产级工具编排的完整链路
大数据·人工智能·agent·ai编程·工具调用
狼爷1 天前
AI正在制造通缩:一场闭门会背后,三个被大多数人忽略的底层逻辑
人工智能·aigc·ai编程
超级架构师1 天前
PRAXO-CORE 2.5.0:用 conformance 和显式边界构建 Go Agent 框架
开发语言·人工智能·后端·golang·ai编程·智能体框架·praxo-core
十七喜欢前端1 天前
工具调用没那么简单:Agent 和外部世界打交道时,有四道坎
agent·ai编程
jarvisuni1 天前
白嫖Tripo3D ?Kimi 3D Make可以玩起来!
人工智能·ai编程
码间留白1 天前
鸿蒙也能热更新了:uni-app WGT 热更新的真机结论、六道校验闸与五个深坑
uniapp·ai编程·鸿蒙os开发·鸿蒙热更新·wgt热更新
掘黄金的打工人1 天前
DeepSeek 参数解读
openai·ai编程
金銀銅鐵1 天前
[Java] 用纯 Swing 做一个《論語·學而》阅读器
java·ai编程·交互设计
李剑一1 天前
为什么几乎所有的知名开源项目都是外国人写的?
前端·ai编程·deepseek