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
直接修改它存在两个问题:
- 需要管理员权限;
- 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
只保留必要的代理修改,并同步系统文件的新字段。
十六、经验总结
- 界面文案不是根因。
waiting for network只说明该应用链路失败,不能直接等同于系统断网。 - 优先做对照实验。 同机网页版正常、桌面版失败,迅速把范围从全局网络缩到客户端路径。
- 进程存在不代表功能完整。 app-server 已启动,仍可能因为代理、DNS或证书环境不同而无法访问外部服务。
- 环境变量属于进程,不属于“整台电脑”。 终端有变量,不代表 GNOME 启动的 GUI 应用也有。
- 父子进程会继承环境。 从带代理的终端启动成功,是验证环境变量假设的干净实验。
- 永久修复前先临时验证。 先从终端启动,确认假设后再改
.desktop,避免无证据修改系统。 - 优先做用户级覆盖。
~/.local/share/applications/比直接修改/usr/share/applications/更安全、更容易回滚。 - 保留
%U等桌面规范占位符。 修改Exec=时不要无意破坏原启动行为。 - Electron 有很多同路径进程。 选择 PID 时要区分主进程、renderer、GPU 和 utility,不能盲信
pgrep -n。 - 功能 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 知识点是:
终端环境不是桌面环境;环境变量属于进程,并沿父子进程链继承。

浙公网安备 33010602011771号