修了一个隐藏的代理问题 — pi daemon 启动排查记

昨晚家里断电,NAS 和 Mac 都关了。今天回来发现 pi(飞书机器人 daemon)没自动启动。本来以为简单重启一下就行,结果花了半小时才找到真正的问题——一个已经关闭的 WiFi 代理留下的幽灵。

症状

pi 启动后飞书连接显示「已连接」,但几秒后进程就退出了。重新启动,同样的情况反复出现。

第一层:以为是 stdin 问题

pi 用的是 RPC 模式,需要 stdin 保持打开。进程退出最先想到的就是 stdin EOF。加上 tail -f /dev/null 喂 stdin——这是之前验证过的方案:

tail -f /dev/null | pi --mode rpc \
  --no-extensions --no-skills --no-prompt-templates \
  -e /path/to/feishu/index.ts

但这次没用,进程还是退。

第二层:日志里的 ECONNREFUSED

daemon.log,看到一行关键报错:

Error: connect ECONNREFUSED 192.168.1.2:20172
  at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1637:16)

[feishu] daemon autoStart failed:
  Cannot destructure property 'tenant_access_token'
  of '(intermediate value)' as it is undefined.

192.168.1.2:20172 是 NAS 上的 HTTP 代理。 pi 的飞书插件请求飞书 API 获取 tenant_access_token,但请求被代理拦截——而代理已经死了。

问题是:我之前已经在 Mac 的 WiFi 设置里把代理关了啊?

第三层:系统代理关了,环境变量还在

这是最坑的地方。macOS 的 WiFi 代理设置关掉后,当前 shell 会话里的 http_proxy / https_proxy 环境变量并不会自动清除。这些变量是在代理开启时被注入到进程环境中的,只要终端/session 不重启,它们就一直存在。

pi 作为子进程继承了这些环境变量,所有 HTTP 请求都先走 192.168.1.2:20172——一个已经不存在的代理。

修复

启动前手动 unset 所有代理变量:

export PATH="/Users/hai/.nvm/versions/node/v22.22.2/bin:$PATH"
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY all_proxy

tail -f /dev/null | pi --mode rpc \
  --no-extensions --no-skills --no-prompt-templates \
  --no-themes --no-context-files --no-builtin-tools \
  -e /Users/hai/.pi/agent/git/github.com/AX1202/pi-feishu-lark/.pi/extensions/feishu/index.ts

这次飞书连接成功,进程稳定运行不再退出。

两个坑,一个比一个隐蔽

问题原因表现
代理幽灵WiFi 代理关闭后 http_proxy 环境变量未清除ECONNREFUSED,飞书 token 获取失败
stdin EOFRPC 模式读 stdin,EOF 触发退出飞书已连接但进程秒退

两个问题叠加在一起,第一个导致飞书连不上,第二个导致即使连上了也保不住。单独排查任何一个都找不到完整答案。

教训

  1. 关闭代理 ≠ 清除环境变量。macOS 系统代理设置变更不会同步到已运行的 shell session。以后关代理后,要么重开终端,要么手动 unset
  2. 看日志比猜原因快。第一反应是 stdin 问题(因为是已知的老问题),差点忽略了日志里的 ECONNREFUSED。如果一开始就 tail daemon.log,5 分钟就能定位。
  3. 把排查过程写成 Skill。这次的问题(代理残留 + stdin EOF)以后断电重启还会遇到。直接写成了一个 Hermes Skill(pi-feishu-daemon),下次同样的情况,Agent 加载技能就能自动按正确步骤启动,不用再重新排查。
每一次断电都是一次灾难恢复演练。问题是,你不想每次都从头排查。

附:pi feishu daemon 排查速查

# 1. 检查 pi 是否在运行
ps aux | grep "[e]arendil"

# 2. 看飞书连接状态
tail -5 ~/.pi/agent/feishu/daemon.log

# 3. 看有没有代理残留
env | grep -i proxy

# 4. 启动(unset 代理 + tail stdin)
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY
tail -f /dev/null | pi --mode rpc ...
← 返回首页