首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >WorkBuddy 自动化复盘:同一个坑修了三次,我才分清「修过」和「修完」

WorkBuddy 自动化复盘:同一个坑修了三次,我才分清「修过」和「修完」

原创
作者头像
用户12800671
发布于 2026-10-08 19:43:32
发布于 2026-10-08 19:43:32
130
举报

背景:我在 WorkBuddy 工作区里维护着一套每天定时跑的自动化脚本——签到、发文、上架、巡查,一共七八个独立脚本,各自带自己的浏览器实例和本地服务。10 月 4 日我发现一个"代理偷走本机请求"的坑并修好了;10 月 6 日它又出现了;10 月 7 日我再看到它时,已经是第三次。这篇记录的就是这三次之间到底漏了什么。

第一次:502 是从哪来的

起因很简单:脚本连本机调试端口取标签页,报 502 Bad Gateway。第一反应是浏览器挂了,但手动 curl http://127.0.0.1:9333/json/version 明明是好的。

打印出完整异常才看明白——请求根本没到本机,是被发给了代理:

代码语言:bash
复制
HTTP_PROXY=http://127.0.0.1:54344
NO_PROXY=          # 空的

环境里注入了代理变量,而 NO_PROXY 是空的,于是 urllib 把发往 127.0.0.1 的请求也丢给了代理;代理再回环转发失败,就吐了 502。更烦的是代理偶尔还吐缓存响应,制造出"刚才明明通了"的假象,让人在错误的路上排查更久。

当时的修法很直接——给本地请求套一个"不走代理"的 opener:

代码语言:python
复制
import urllib.request

# 所有本机回环请求一律走它,绕开 http_proxy
_OPENER = urllib.request.build_opener(urllib.request.ProxyHandler({}))

def local_get(url, timeout=5):
    return _OPENER.open(url, timeout=timeout).read()

改完,脚本好了。我把结论写进笔记,收工。

第二次:它不是同一个 bug,是同一个"根因"

两天后,同类脚本又在另一条线崩了,报错还是 502。查了一下——这个脚本里没有那段修复代码。当初我只改了正在报错的那一个文件。

这是第一个教训:「修过」等于改了一处,不等于修完。 同一个根因散布在多个文件里时,只修触发报错的那个,等于把坑留着等下一次触发。

于是这一轮我把修法做成了共享函数,并在整个项目里回灌:

代码语言:bash
复制
grep -rn "urllib.request.urlopen" tools/ | grep -v _OPENER

只要有输出,就说明还有漏网的直接调用。

第三次:一个写死的常量

第三次的报错和代理完全无关,反而更像"玄学":脚本先打印

代码语言:bash
复制
browser: 复用已开实例 9335

紧跟着就 ConnectionRefused。日志自相矛盾——它自己说用的是 9335,却去连了别的端口。

把代码翻出来就明白了:

代码语言:python
复制
DEBUG_PORT = 9333          # 模块级常量

def ensure_browser():
    global PORT
    PORT[0] = pick_alive_port()   # 判定出真正可用的端口,写进了 PORT[0]

def pick_tab():
    return http_get(f"http://127.0.0.1:{DEBUG_PORT}/json")   # 这里却用了常量

判定端口和连接端口用了两个变量。修法是把"一次判定、多处使用"的值收敛到唯一来源:

代码语言:python
复制
PORT = [DEBUG_PORT]        # 可变容器,全流程唯一真相源

def ensure_browser():
    PORT[0] = pick_alive_port()

def pick_tab():
    return local_get(f"http://127.0.0.1:{PORT[0]}/json")

三条可以带走的纪律

写下这三次,不是为了抱怨,而是因为它们其实是一类问题:

  1. 本机回环请求,永远不要交给代理。 显式构建空代理 opener,或把 127.0.0.1,localhost,::1 放进 NO_PROXY。这是环境特性,不是代码 bug,但它会伪装成代码 bug。
  2. 凡是"先判定、后使用"的环境值(端口、路径、实例号),必须只有一个可变来源。 常量 + 全局并存,迟早会出现"日志说 A、实际连 B"。
  3. 修完一处,立刻在项目里全局搜一次同类调用。 一行 grep 的成本,远低于再花一晚排查同一个根因。

三条纪律落地后,这套自动化连续跑了一周没再出同类故障。回头看,真正花掉时间的不是"怎么修",而是"为什么同一个东西要修三次"——修的是症状,回灌的才是修复。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 第一次:502 是从哪来的
  • 第二次:它不是同一个 bug,是同一个"根因"
  • 第三次:一个写死的常量
  • 三条可以带走的纪律
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档