退出码 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

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

相关推荐
单向箔1 小时前
08|一套可复制的 AI Coding 流程:从需求到提交怎么走
人工智能·prompt·ai编程
自律懒人1 小时前
openJiuwen 企业级 AgentOS 实测:4 层架构 + 5 步部署,多智能体协作省 60% Token
ai编程
熊出没2 小时前
从Copilot到Agent:AI编程工作流的重构与落地实践
软件工程·copilot·ai编程·ai agent
Sammyyyyy3 小时前
jev-ultrafast 实战:浏览器操作代理加本地 AI 网关,把云控制台配置做成自动化流水线
运维·人工智能·自动化·ai编程·servbay
啵啵啵鱼3 小时前
对数据的增删改查
数据库·mysql·ai·idea·ai编程·navicat·obsidian
AINative软件工程4 小时前
LLM 异步任务的 Webhook 工程实践:回调可靠投递、重试与幂等消费的生产设计
后端·ai编程
小蠢驴打代码15 小时前
给 Codex Plan 模式加一本决策账本:问过什么、选了什么,都进仓库
开源·openai·ai编程
就叫飞六吧17 小时前
nat打洞和frp区别
ai编程
桃西西呀18 小时前
LangGraph4j之一:客服请求分诊既要循环又要分流,我用 LangGraph4j 把控制流抽成了数据
人工智能·llm·ai编程