跳转至
技 · 格物札记

一次 macOS 代理配置排查

Mon 的个人花园 正在计算 阅读模式

最后修订于

切换代理软件后,GitHub 和 YouTube 都能正常访问,但 Codex 一直连接失败。

排查后发现,本机终端环境变量中固定写着旧代理端口。代理软件切换后,系统代理已经变化,但终端中的固定配置不会自动更新,因此不同程序可能走了不同的代理。

本文中的端口均为示例,已去除账号、路径和节点等隐私信息。

1 问题原因

1.1 系统代理和环境变量代理并不是一回事

macOS 中常见两套代理来源:

  • 系统代理:由代理软件修改 macOS 当前代理配置。
  • 环境变量代理:通过 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 等变量指定。

例如旧代理使用 7890,新代理使用 7891,但终端中仍然存在:

export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890

此时可能出现:

浏览器 → 系统代理 → 7891
命令行程序 → 环境变量 → 7890

所以浏览器能正常访问网络,并不能证明 Codex 使用的是同一套代理配置。

2 排查方法

2.1 查看系统代理

scutil --proxy

重点检查 HTTP、HTTPS、SOCKS 是否启用,以及对应端口。

2.2 查看端口是否监听

lsof -nP -iTCP:7890 -sTCP:LISTEN

配置文件中存在端口,不代表这个端口当前一定有代理服务运行。

2.3 查看 Codex 日志

这次日志中出现:

ERR_TUNNEL_CONNECTION_FAILED

说明代理隧道建立失败,因此可以重点检查代理地址、端口、协议以及节点连接情况。

但单凭这个错误码,不能确定唯一原因。

3 最终修改方案

检查发现,固定代理配置同时存在于:

~/.zshenv
~/.zshrc

因此只修改一个文件并不彻底。

最终处理方式是:

  1. 备份原配置。
  2. 在 .zshenv 中读取 macOS 当前系统代理。
  3. 删除 .zshrc 中重复的固定代理地址。
  4. 根据系统配置设置 HTTP、HTTPS 或 SOCKS 环境变量。
  5. 系统关闭代理时,清除遗留的旧代理变量。
  6. 保留本机和局域网地址的绕过规则。

这样以后切换代理软件时,不需要再手动修改固定端口。

4 修改后的生效范围

这套方案本质上是启动时同步。

环境变量会在进程启动时继承,所以:

  • 新启动的终端会读取当前代理。
  • 从终端启动的子进程会继承新配置。
  • 已经运行的程序可能仍然保留旧配置,需要重新启动。

另外,从 Dock 或 Finder 启动的桌面应用,不一定读取 .zshenv,因此仍需要单独验证。

PAC 和 TUN 模式属于不同的代理机制,也不能简单等价为一个 HTTP 代理端口。

5 验证结果

修改后主要进行了两类测试。

配置层面:

  • 能正确读取不同代理端口。
  • 关闭代理后能够清除旧变量。
  • SOCKS、IPv6 和异常端口能够正确处理。

实际使用层面:

  • 新终端能够读取当前系统代理。
  • 网络请求可以正常通过代理访问目标服务。
  • 切回之前出现问题的代理软件后,Codex 可以正常对话。

因此可以确认,终端中固定代理端口这一配置隐患已经解决。

但不能据此认定之前所有 Codex 连接失败都只由这一原因导致。

6 排查经验

以后遇到“浏览器正常,但开发工具无法联网”,可以按照下面的顺序检查:

  1. 确认当前使用的代理软件。
  2. 查看 macOS 当前系统代理。
  3. 检查代理端口是否监听。
  4. 检查终端是否残留旧代理环境变量。
  5. 查看应用日志中的具体网络错误。
  6. 修改后重新启动进程,并进行真实业务测试。

这次最关键的改进,是取消了多处固定代理端口配置,让新启动的进程能够跟随 macOS 当前系统代理,减少以后切换代理软件时再次出现类似问题的概率。