系统:Ubuntu 26.04
设备:Lenovo Y7000
客户端:ChatGPT Linux 桌面版
网络代理:*** Verge,本地端口127.0.0.1:7897
一、故障现象
ChatGPT 桌面版的普通对话可以正常使用,但 Work 模式持续出现:
text
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 恢复正常。
二、最关键的 A/B 测试:网页版与桌面版对照
在同一台电脑、同一个账号、同一网络环境中测试:
text
网页版 Work:约半分钟后正常回复
桌面版 Work:持续 Reconnecting
这个对照一次排除了很多方向:
-
不是当前网络完全无法访问互联网;
-
不是 Work 服务对该账号完全不可用;
-
不是 OpenAI 所有访问路径都失败。
问题范围被缩小到:
text
Linux 桌面客户端
或
桌面客户端启动的本地 Work/Codex 后端
或
桌面客户端特有的代理与网络环境
这比不断重启 ChatGPT、重装应用或反复修改系统网络设置更有效。
三、确认桌面客户端及其本地后端确实已启动
先查看 ChatGPT 相关进程:
bash
ps aux | grep -i chatgpt
命令含义:
-
ps:列出进程; -
a:显示更多用户和终端相关进程; -
u:用详细的用户格式显示; -
x:包括没有绑定终端的进程; -
|:把左侧输出交给右侧; -
grep -i chatgpt:只保留包含chatgpt的行,并忽略大小写。
输出表明主程序是:
text
/usr/lib/chatgpt/ChatGPT
同时可以看到 ChatGPT 启动了本地 Codex 后端:
text
/usr/lib/chatgpt/resources/codex ... app-server
这说明问题不是"Work 后端根本没有启动"。下一步应检查:后端虽然启动了,为什么网络请求仍失败。
四、从日志中确认超时发生在 Work 请求链路
当时用下面的命令读取最近 5 分钟的用户级 systemd 日志,并筛选与 ChatGPT、Codex、网络和错误有关的行:
bash
journalctl --user --since "5 minutes ago" | grep -Ei 'chatgpt|codex|websocket|network|error|failed'
命令可以拆开理解:
-
journalctl:读取 systemd journal 日志; -
--user:只查看当前用户会话中的服务和桌面程序日志,而不是整个系统的内核与系统服务日志; -
--since "5 minutes ago":只读取最近 5 分钟,避免旧日志干扰; -
|:把左侧日志交给右侧继续处理; -
grep -E:使用扩展正则表达式,允许在引号内用|表示"或者"; -
grep -i:忽略大小写; -
引号中的关键词:只保留可能与 ChatGPT、Codex、连接或错误有关的行。
筛选结果中出现过一条类似记录。原日志是一整行,这里为了便于阅读拆成三个字段:
text
method=app/read
durationMs=30223
errorCode=-32603
以及:
text
failed to read app metadata
Failed to send request
以及同一时刻 Work 界面持续 Reconnecting,可以合理推断失败发生在 Work 加载应用元数据的请求链路,并具有典型的请求超时特征。
五、检查进程是否继承代理环境变量
终端中已经存在 *** 代理变量:
text
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. 检查终端环境
bash
env | grep -i proxy
-
env:显示当前进程的环境变量; -
grep -i proxy:只看名称包含proxy的变量,忽略大小写。
终端能够正常显示 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 等变量。
2. 检查 ChatGPT 或 Codex 后端进程环境
先找到目标进程 PID,再读取:
bash
tr '\0' '\n' < /proc/进程PID/environ | grep -i proxy
其中:
-
/proc/PID/environ:Linux 暴露的该进程环境变量; -
环境变量之间使用 NUL 字符分隔,不是普通换行;
-
tr '\0' '\n':把 NUL 分隔符转换成可读的换行; -
grep -i proxy:筛选代理变量。
检查结果没有任何输出。
当时的差异非常清楚:
text
终端进程
├── 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 配置中,启动链是:
text
打开终端
↓
Bash 读取 .bashrc
↓
终端中出现 HTTP_PROXY 等变量
↓
从该终端启动的程序继承变量
但从 GNOME 应用菜单点击图标时,启动链通常是:
text
GNOME 桌面
↓
.desktop 启动项
↓
ChatGPT
这里没有启动交互式 Bash,也不会自动读取 .bashrc。因此:
终端中的
env能看到代理,不能证明整个桌面会话以及所有 GUI 应用都有这些变量。
普通 ChatGPT 对话仍能使用,可能是因为 Electron/Chromium 的网络服务还会读取系统代理,或者普通聊天与 Work 后端使用了不同的网络路径。但 Codex app-server 是独立的本地进程,它不一定使用 Chromium 的同一套代理机制。
七、决定性 A/B 测试:从终端启动 ChatGPT
在永久修改配置前,先做一次可逆的对照实验。
1. 完全退出当前 ChatGPT
bash
pgrep -af '/usr/lib/chatgpt/ChatGPT'
-
pgrep:查找进程; -
-a:显示完整命令行; -
-f:按完整命令行匹配,而不只匹配进程名。
没有输出,说明旧进程已经退出。
2. 从已经具有代理变量的终端启动
bash
/usr/lib/chatgpt/ChatGPT
此时父子关系变为:
text
终端 / Bash
├── HTTP_PROXY
├── HTTPS_PROXY
└── ALL_PROXY
↓ 继承
ChatGPT
↓ 继承
Codex app-server
测试结果:
text
从终端启动 ChatGPT → Work 正常
从 GNOME 图标启动 ChatGPT → Work 持续 Reconnecting
这是本次排障最有说服力的实验。除了启动来源和继承的环境变量外,账号、网络、系统、应用程序和测试目标均保持不变。
因此根因基本确认:
GNOME 图标启动的 ChatGPT 没有代理环境变量,导致其 Codex/Work 后端的外部请求超时。
八、找到 ChatGPT 的 .desktop 启动文件
Linux 桌面应用菜单背后通常使用 .desktop 文件,可以把它理解为带有标准字段的应用快捷方式。
常见字段包括:
ini
[Desktop Entry]
Name=ChatGPT
Icon=chatgpt
Exec=chatgpt %U
Type=Application
其中:
-
Name=:菜单中显示的名称; -
Icon=:应用图标; -
Exec=:点击图标后实际执行的命令; -
%U:Desktop Entry 规范中的 URL 参数占位符,不是 Shell 变量。
先按文件名寻找启动项:
bash
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:隐藏无关的标准错误输出。
找到系统级文件:
text
/usr/share/applications/chatgpt.desktop
读取关键字段:
bash
grep -E '^(Name|Exec|Icon)=' /usr/share/applications/chatgpt.desktop
结果为:
text
Name=ChatGPT
Exec=chatgpt %U
Icon=chatgpt
这就确认了,从 GNOME 图标启动时并没有显式附加代理环境变量。
九、为什么使用用户级覆盖,而不直接改系统文件
系统级启动项位于:
text
/usr/share/applications/chatgpt.desktop
直接修改它存在两个问题:
-
需要管理员权限;
-
ChatGPT 软件包升级时可能覆盖修改。
更稳妥的方法是复制到当前用户目录:
bash
mkdir -p ~/.local/share/applications
cp /usr/share/applications/chatgpt.desktop ~/.local/share/applications/chatgpt.desktop
-
mkdir -p:确保用户级应用目录存在,已存在时不报错; -
cp:复制系统启动文件; -
用户级同名启动项会优先于系统级启动项。
这种做法把修改限制在当前用户,也更容易回滚。
十、最终修复
编辑用户级启动项:
bash
nano ~/.local/share/applications/chatgpt.desktop
把:
ini
Exec=chatgpt %U
改为一整行:
ini
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 在这里的用法是:
text
env 变量=值 变量=值 程序 参数
也就是:
只为这次启动的 ChatGPT 设置代理环境变量,然后运行
chatgpt %U。
它不会把代理强行写给 Ubuntu 的所有程序,只影响由这个启动项启动的 ChatGPT 及其子进程。
变量作用:
-
HTTP_PROXY:HTTP 请求代理; -
HTTPS_PROXY:HTTPS 请求代理; -
ALL_PROXY:其他支持该变量的网络请求统一代理; -
NO_PROXY:本机、局域网地址不走代理; -
%U:保留原启动项接受 URL 参数的能力。
十一、验证修复
1. 检查用户级启动命令
bash
grep '^Exec=' ~/.local/share/applications/chatgpt.desktop
应显示包含 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 的完整启动命令。
2. 完全退出旧进程
先退出当前从终端启动的 ChatGPT,确保没有残留旧进程:
bash
pgrep -af '/usr/lib/chatgpt/ChatGPT'
3. 从应用菜单重新启动
这次不要从终端启动,而是:
text
Ubuntu 应用菜单 → ChatGPT 图标
然后进入 Work 执行最小测试。
实际结果:
text
从桌面图标启动 → Work 恢复正常
这个功能测试已经验证修复成功。
4. 可选:检查运行进程环境
可以进一步找到正确的 ChatGPT 主进程 PID,再执行:
bash
tr '\0' '\n' < /proc/codex进程PID/environ | grep -i proxy
十二、回滚方法
由于系统级启动项没有被修改,回滚非常简单。
bash
rm ~/.local/share/applications/chatgpt.desktop
删除后,GNOME 会重新使用:
text
/usr/share/applications/chatgpt.desktop
结论
本次 ChatGPT Work 持续 Reconnecting 并不是系统整体断网,也不是 Work 后端没有启动。
决定性证据是:同机网页版 Work 正常;桌面版失败;从带有 *** 代理环境变量的终端启动同一个 ChatGPT 程序后,Work 立即恢复。
根因是 GNOME 通过系统 .desktop 文件执行:
ini
Exec=chatgpt %U
这一启动路径没有获得仅存在于 Shell 环境中的 HTTP_PROXY、HTTPS_PROXY 和 ALL_PROXY。ChatGPT 启动的 Codex app-server 也无法继承这些变量,最终导致 Work 的部分外部请求约 30 秒后超时。
通过创建用户级 .desktop 覆盖,并使用 /usr/bin/env 为 ChatGPT 启动进程显式附加 *** 代理变量后,从 GNOME 图标启动的 Work 恢复正常。
这次排障最值得保留的 Linux 知识点是:
终端环境不是桌面环境;环境变量属于进程,并沿父子进程链继承。