AIGC标识 Ubuntu 桌面版 ChatGPT Work 一直 Reconnecting:代理环境变量排障复盘

Ubuntu 桌面版 ChatGPT Work 一直 Reconnecting:代理环境变量排障复盘

系统:Ubuntu 26.04
设备:Lenovo Y7000
客户端:ChatGPT Linux 桌面版
网络代理:*** Verge,本地端口 127.0.0.1:7897

一、故障现象

ChatGPT 桌面版的普通对话可以正常使用,但 Work 模式持续出现:

Reconnecting 1/5
...
Reconnecting 5/5
waiting for network

典型现象包括:

  • 普通 ChatGPT 对话可以收发消息;
  • 图片可以正常上传;
  • 浏览器和其他联网应用工作正常;
  • Work 运行一段时间后不断重连;
  • 重启 ChatGPT 后仍然复现;
  • 同一台电脑上的网页版 Work 等待约半分钟后可以正常回复;
  • Linux 桌面版 Work 仍停留在 Reconnecting。

最终通过 A/B 测试确认:

从 GNOME 应用图标启动 ChatGPT 时,主进程没有获得终端中已有的 *** 代理环境变量;它启动的 Codex app-server 同样没有继承代理变量,因此 Work 的部分网络请求超时。把代理变量加入用户级 .desktop 启动命令后,从桌面图标启动的 Work 恢复正常。

二、先判断是系统断网,还是应用特定链路失败

看到 waiting for network 时,很容易下意识认为电脑已经断网。但这句界面提示只能证明某条应用连接没有建立,不能证明整个系统失去了网络连接。

当时存在以下证据:

普通 ChatGPT 对话正常
图片上传正常
浏览器及其他联网应用正常
只有 Work 持续重连

因此应先区分两个层次:

系统基础网络
└── 浏览器与其他应用能够正常联网

ChatGPT Work Reconnecting
└── 桌面客户端 / Work 后端 / 代理与网络路径问题

这一步很重要。如果仅根据 waiting for network 就修改系统网络、驱动或 DNS 配置,不但不一定能解决 Work,还会引入新的变量,使问题更难定位。

三、最关键的 A/B 测试:网页版与桌面版对照

在同一台电脑、同一个账号、同一网络环境中测试:

网页版 Work:约半分钟后正常回复
桌面版 Work:持续 Reconnecting

这个对照一次排除了很多方向:

  • 不是系统整体断网;
  • 不是当前网络完全无法访问互联网;
  • 不是账号没有 Work 权限;
  • 不是 Work 服务对该账号完全不可用;
  • 不是 OpenAI 所有访问路径都失败。

问题范围被缩小到:

Linux 桌面客户端
或
桌面客户端启动的本地 Work/Codex 后端
或
桌面客户端特有的代理与网络环境

这比不断重启 ChatGPT、重装应用或反复修改系统网络设置更有效。

四、确认桌面客户端及其本地后端确实已启动

先查看 ChatGPT 相关进程:

ps aux | grep -i chatgpt

命令含义:

  • ps:列出进程;
  • a:显示更多用户和终端相关进程;
  • u:用详细的用户格式显示;
  • x:包括没有绑定终端的进程;
  • |:把左侧输出交给右侧;
  • grep -i chatgpt:只保留包含 chatgpt 的行,并忽略大小写。

输出表明主程序是:

/usr/lib/chatgpt/ChatGPT

同时可以看到 ChatGPT 启动了本地 Codex 后端:

/usr/lib/chatgpt/resources/codex ... app-server

这说明问题不是“Work 后端根本没有启动”。下一步应检查:后端虽然启动了,为什么网络请求仍失败。

五、从日志中确认超时发生在 Work 请求链路

当时用下面的命令读取最近 3 分钟的用户级 systemd 日志,并筛选与 ChatGPT、Codex、网络和错误有关的行:

journalctl --user --since "3 minutes ago" | grep -Ei 'chatgpt|codex|websocket|network|error|failed'

命令可以拆开理解:

  • journalctl:读取 systemd journal 日志;
  • --user:只查看当前用户会话中的服务和桌面程序日志,而不是整个系统的内核与系统服务日志;
  • --since "3 minutes ago":只读取最近 3 分钟,避免旧日志干扰;
  • |:把左侧日志交给右侧继续处理;
  • grep -E:使用扩展正则表达式,允许在引号内用 | 表示“或者”;
  • grep -i:忽略大小写;
  • 引号中的关键词:只保留可能与 ChatGPT、Codex、连接或错误有关的行。

筛选结果中出现过一条类似记录。原日志是一整行,这里为了便于阅读拆成三个字段:

method=app/read
durationMs=30223
errorCode=-32603

以及:

failed to read app metadata
Failed to send request

三个字段分别表示:

  • method=app/read:失败的是名为 app/read 的请求;结合随后出现的 app metadata 错误,它与 Work 加载应用信息的链路相关;
  • durationMs=30223:从发出请求到收到失败结果共耗时 30,223 毫秒,也就是约 30.223 秒;
  • errorCode=-32603:请求最终以错误结束。-32603 是一个通用的内部错误码,仅凭它本身不能判断具体网络原因。

因此,日志直接证明的是:app/read 请求等待了约 30 秒后失败。结合紧邻的:

failed to read app metadata
Failed to send request

以及同一时刻 Work 界面持续 Reconnecting,可以合理推断失败发生在 Work 加载应用元数据的请求链路,并具有典型的请求超时特征。

六、检查进程是否继承代理环境变量

终端中已经存在 *** 代理变量:

HTTP_PROXY=http://127.0.0.1:7897
HTTPS_PROXY=http://127.0.0.1:7897
ALL_PROXY=socks://127.0.0.1:7897

但终端里有代理,不代表从 GNOME 图标启动的程序也有代理。

1. 检查终端环境

env | grep -i proxy
  • env:显示当前进程的环境变量;
  • grep -i proxy:只看名称包含 proxy 的变量,忽略大小写。

终端能够正常显示 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 等变量。

2. 检查 ChatGPT 或 Codex 后端进程环境

先找到目标进程 PID,再读取:

tr '\0' '\n' < /proc/进程PID/environ | grep -i proxy

其中:

  • /proc/PID/environ:Linux 暴露的该进程环境变量;
  • 环境变量之间使用 NUL 字符分隔,不是普通换行;
  • tr '\0' '\n':把 NUL 分隔符转换成可读的换行;
  • grep -i proxy:筛选代理变量。

检查结果没有任何输出。

当时的差异非常清楚:

终端进程
├── HTTP_PROXY  ✅
├── HTTPS_PROXY ✅
└── ALL_PROXY   ✅

GNOME 启动的 ChatGPT
├── HTTP_PROXY  ❌
├── HTTPS_PROXY ❌
└── ALL_PROXY   ❌
      ↓
Codex app-server
├── HTTP_PROXY  ❌
├── HTTPS_PROXY ❌
└── ALL_PROXY   ❌

这时代理环境已经成为主要嫌疑。

七、为什么终端有代理,桌面图标启动的应用却没有

Linux 中的环境变量属于进程环境,通常由父进程传给子进程。

如果代理变量写在 .bashrc 等 Shell 配置中,启动链是:

打开终端
    ↓
Bash 读取 .bashrc
    ↓
终端中出现 HTTP_PROXY 等变量
    ↓
从该终端启动的程序继承变量

但从 GNOME 应用菜单点击图标时,启动链通常是:

GNOME 桌面
    ↓
.desktop 启动项
    ↓
ChatGPT

这里没有启动交互式 Bash,也不会自动读取 .bashrc。因此:

终端中的 env 能看到代理,不能证明整个桌面会话以及所有 GUI 应用都有这些变量。

普通 ChatGPT 对话仍能使用,可能是因为 Electron/Chromium 的网络服务还会读取系统代理,或者普通聊天与 Work 后端使用了不同的网络路径。但 Codex app-server 是独立的本地进程,它不一定使用 Chromium 的同一套代理机制。

八、决定性 A/B 测试:从终端启动 ChatGPT

在永久修改配置前,先做一次可逆的对照实验。

1. 完全退出当前 ChatGPT

pgrep -af '/usr/lib/chatgpt/ChatGPT'
  • pgrep:查找进程;
  • -a:显示完整命令行;
  • -f:按完整命令行匹配,而不只匹配进程名。

没有输出,说明旧进程已经退出。

2. 从已经具有代理变量的终端启动

/usr/lib/chatgpt/ChatGPT

此时父子关系变为:

终端 / Bash
├── HTTP_PROXY
├── HTTPS_PROXY
└── ALL_PROXY
        ↓ 继承
ChatGPT
        ↓ 继承
Codex app-server

如果不希望程序占用当前终端,可以在新测试中使用:

/usr/lib/chatgpt/ChatGPT &

命令末尾的 & 表示把程序放到后台运行,并把终端提示符立即还给用户。

测试结果:

从终端启动 ChatGPT → Work 正常
从 GNOME 图标启动 ChatGPT → Work 持续 Reconnecting

这是本次排障最有说服力的实验。除了启动来源和继承的环境变量外,账号、网络、系统、应用程序和测试目标均保持不变。

因此根因基本确认:

GNOME 图标启动的 ChatGPT 没有代理环境变量,导致其 Codex/Work 后端的外部请求超时。

九、找到 ChatGPT 的 .desktop 启动文件

Linux 桌面应用菜单背后通常使用 .desktop 文件,可以把它理解为带有标准字段的应用快捷方式。

常见字段包括:

[Desktop Entry]
Name=ChatGPT
Icon=chatgpt
Exec=chatgpt %U
Type=Application

其中:

  • Name=:菜单中显示的名称;
  • Icon=:应用图标;
  • Exec=:点击图标后实际执行的命令;
  • %U:Desktop Entry 规范中的 URL 参数占位符,不是 Shell 变量。

先按文件名寻找启动项:

find /usr/share/applications ~/.local/share/applications -type f \
  \( -iname '*chatgpt*.desktop' -o -iname '*codex*.desktop' \) 2>/dev/null

命令含义:

  • find:在目录树中寻找文件;
  • 两个路径:系统级与当前用户级应用启动目录;
  • -type f:只找普通文件;
  • -iname:按文件名匹配并忽略大小写;
  • -o:或者;
  • 2>/dev/null:隐藏无关的标准错误输出。

找到系统级文件:

/usr/share/applications/chatgpt.desktop

读取关键字段:

grep -E '^(Name|Exec|Icon)=' /usr/share/applications/chatgpt.desktop

结果为:

Name=ChatGPT
Exec=chatgpt %U
Icon=chatgpt

这就确认了,从 GNOME 图标启动时并没有显式附加代理环境变量。

十、为什么使用用户级覆盖,而不直接改系统文件

系统级启动项位于:

/usr/share/applications/chatgpt.desktop

直接修改它存在两个问题:

  1. 需要管理员权限;
  2. ChatGPT 软件包升级时可能覆盖修改。

更稳妥的方法是复制到当前用户目录:

mkdir -p ~/.local/share/applications
cp /usr/share/applications/chatgpt.desktop ~/.local/share/applications/chatgpt.desktop
  • mkdir -p:确保用户级应用目录存在,已存在时不报错;
  • cp:复制系统启动文件;
  • 用户级同名启动项会优先于系统级启动项。

这种做法把修改限制在当前用户,也更容易回滚。

十一、最终修复

编辑用户级启动项:

nano ~/.local/share/applications/chatgpt.desktop

把:

Exec=chatgpt %U

改为一整行:

Exec=/usr/bin/env HTTP_PROXY=http://127.0.0.1:7897 HTTPS_PROXY=http://127.0.0.1:7897 ALL_PROXY=socks://127.0.0.1:7897 NO_PROXY=localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,::1 chatgpt %U

/usr/bin/env 在这里的用法是:

env 变量=值 变量=值 程序 参数

也就是:

只为这次启动的 ChatGPT 设置代理环境变量,然后运行 chatgpt %U。

它不会把代理强行写给 Ubuntu 的所有程序,只影响由这个启动项启动的 ChatGPT 及其子进程。

变量作用:

  • HTTP_PROXY:HTTP 请求代理;
  • HTTPS_PROXY:HTTPS 请求代理;
  • ALL_PROXY:其他支持该变量的网络请求统一代理;
  • NO_PROXY:本机、局域网地址不走代理;
  • %U:保留原启动项接受 URL 参数的能力。

注意:这一条 Exec= 必须是文件中的完整一行。编辑器或博客页面的视觉折行不是问题,但不能在文件中间按 Enter 形成多条物理行。

十二、验证修复

1. 检查用户级启动命令

grep '^Exec=' ~/.local/share/applications/chatgpt.desktop

应显示包含 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 的完整启动命令。

2. 完全退出旧进程

先退出当前从终端启动的 ChatGPT,确保没有残留旧进程:

pgrep -af '/usr/lib/chatgpt/ChatGPT'

3. 从应用菜单重新启动

这次不要从终端启动,而是:

Ubuntu 应用菜单 → ChatGPT 图标

然后进入 Work 执行最小测试。

实际结果:

从桌面图标启动 → Work 恢复正常

这个功能测试已经验证修复成功。

4. 可选:检查运行进程环境

可以进一步找到正确的 ChatGPT 主进程 PID,再执行:

tr '\0' '\n' < /proc/正确的主进程PID/environ | grep -i proxy

但本次曾遇到一个验证陷阱:

pgrep -n -f '/usr/lib/chatgpt/ChatGPT'

-n 只选择最新创建的匹配进程。Electron 会创建主进程、renderer、GPU、utility 等多个同路径进程,最新进程不一定是主进程。因此该命令拿到的 PID 可能不适合用于验证主进程环境。

正确思路是先列出全部进程:

pgrep -af '/usr/lib/chatgpt/ChatGPT'

再选择命令行中没有 --type=renderer、--type=gpu-process、--type=utility 等参数的主进程。

不过,如果相同的桌面启动路径在修改前稳定失败、修改后稳定成功,功能 A/B 实验本身已经是强证据,不应因为一次选错 PID 的辅助验证而推翻结果。

十三、中途判断如何被修正

修正一:waiting for network 不等于系统断网

一开始看到 Work 提示等待网络,很容易把它解释成电脑的基础网络连接失败。

但普通对话、图片上传、浏览器和网页版 Work 都正常,因此判断修正为:问题发生在桌面版 Work 的特定连接链路,而不是系统整体断网。

修正二:Work 后端启动,不代表它能访问网络

进程列表中能看到 codex ... app-server,说明后端已运行,但日志仍出现约 30 秒的外部请求超时。

因此判断从“后端是否启动”转向“后端继承了什么网络环境”。

修正三:一次 /proc 检查为空不能推翻功能验证

永久修复后,Work 已经从桌面图标启动并恢复正常,但一次代理环境检查仍返回空。

进一步分析发现,用 pgrep -n 选择到的可能是 Electron 新创建的 renderer,而不是主进程。验证方法本身存在缺陷。

因此以更干净的功能 A/B 结果为主:

原 Exec=chatgpt %U                    → Work 失败
新 Exec=/usr/bin/env ... chatgpt %U  → Work 正常

十四、回滚方法

由于系统级启动项没有被修改,回滚非常简单。

方法一:删除用户级覆盖

rm ~/.local/share/applications/chatgpt.desktop

删除后,GNOME 会重新使用:

/usr/share/applications/chatgpt.desktop

执行前可以先确认文件:

ls -l ~/.local/share/applications/chatgpt.desktop

方法二:恢复原始 Exec 行

保留用户级文件,只把 Exec= 改回:

Exec=chatgpt %U

然后完全退出 ChatGPT,再从应用菜单重新启动。

十五、安全与维护注意事项

1. 本地代理必须正在运行

启动项固定指向:

127.0.0.1:7897

如果 *** 未启动或监听端口发生变化,ChatGPT/Work 的网络请求可能再次失败。

2. 端口变化时需要同步更新

如果 *** 的 Mixed Port 从 7897 改为其他端口,应同步修改用户级 .desktop 中的代理地址。

3. 注意代理协议

本次配置为:

HTTP_PROXY=http://127.0.0.1:7897
HTTPS_PROXY=http://127.0.0.1:7897
ALL_PROXY=socks://127.0.0.1:7897

这依赖 *** 的 7897 端口支持相应协议。若代理软件配置不同,需要按实际监听协议调整。

4. 用户级启动项可能与软件更新产生差异

用户级同名文件会持续覆盖系统级文件。ChatGPT 升级后,如果系统启动项新增了重要参数,用户副本不会自动合并这些变化。

遇到升级后启动异常时,可以比较:

diff -u /usr/share/applications/chatgpt.desktop ~/.local/share/applications/chatgpt.desktop

只保留必要的代理修改,并同步系统文件的新字段。

十六、经验总结

  1. 界面文案不是根因。 waiting for network 只说明该应用链路失败,不能直接等同于系统断网。
  2. 优先做对照实验。 同机网页版正常、桌面版失败,迅速把范围从全局网络缩到客户端路径。
  3. 进程存在不代表功能完整。 app-server 已启动,仍可能因为代理、DNS或证书环境不同而无法访问外部服务。
  4. 环境变量属于进程,不属于“整台电脑”。 终端有变量,不代表 GNOME 启动的 GUI 应用也有。
  5. 父子进程会继承环境。 从带代理的终端启动成功,是验证环境变量假设的干净实验。
  6. 永久修复前先临时验证。 先从终端启动,确认假设后再改 .desktop,避免无证据修改系统。
  7. 优先做用户级覆盖。 ~/.local/share/applications/ 比直接修改 /usr/share/applications/ 更安全、更容易回滚。
  8. 保留 %U 等桌面规范占位符。 修改 Exec= 时不要无意破坏原启动行为。
  9. Electron 有很多同路径进程。 选择 PID 时要区分主进程、renderer、GPU 和 utility,不能盲信 pgrep -n。
  10. 功能 A/B 证据可能比一次辅助检查更可靠。 如果辅助验证方法存在选错对象的可能,不应据此推翻前后对照结果。

结论

本次 ChatGPT Work 持续 Reconnecting 并不是系统整体断网,也不是 Work 后端没有启动。

决定性证据是:同机网页版 Work 正常;桌面版失败;从带有 *** 代理环境变量的终端启动同一个 ChatGPT 程序后,Work 立即恢复。

根因是 GNOME 通过系统 .desktop 文件执行:

Exec=chatgpt %U

这一启动路径没有获得仅存在于 Shell 环境中的 HTTP_PROXY、HTTPS_PROXY 和 ALL_PROXY。ChatGPT 启动的 Codex app-server 也无法继承这些变量,最终导致 Work 的部分外部请求约 30 秒后超时。

通过创建用户级 .desktop 覆盖,并使用 /usr/bin/env 为 ChatGPT 启动进程显式附加 *** 代理变量后,从 GNOME 图标启动的 Work 恢复正常。

这次排障最值得保留的 Linux 知识点是:

终端环境不是桌面环境;环境变量属于进程,并沿父子进程链继承。

posted @ 2026-09-01 21:40  云里摸鱼  阅读(89)  评论(0)    收藏  举报