Ubuntu 22.04 下 VS Code Codex 插件一直卡在加载页的完整排查与解决方法

📅 2026/7/20 12:11:35
Ubuntu 22.04 下 VS Code Codex 插件一直卡在加载页的完整排查与解决方法
文章摘要记录 Ubuntu 22.04 中 VS Code Codex 插件在本地与 Remote-SSH 窗口随机卡在加载页的问题。通过对比终端和侧边栏启动方式、检查 Linux 文件描述符软硬限制及 VS Code 子进程继承关系最终将问题定位为图形桌面启动时部分进程的 soft nofile 为 1024并通过高限制启动脚本和用户级 desktop 文件完成修复。分类建议开发环境与故障排查封面建议可以截取以下内容制作封面VS Code Codex 一直加载 soft nofile1024 终端启动正常侧边栏启动失败# Ubuntu 22.04 下 VS Code Codex 插件一直卡在加载页的完整排查与解决方法 ## 一、问题背景 我的开发环境如下 - 操作系统Ubuntu 22.04 - 编辑器Visual Studio Code - 使用方式 - 本地直接打开 VS Code - 通过 VS Code Remote-SSH 连接服务器 - 插件OpenAI Codex - 当时使用的 VS Code 版本1.128.1 - 当时使用的 Codex 扩展目录 text ~/.vscode/extensions/openai.chatgpt-26.5715.31925-linux-x64一开始我是在 Remote-SSH 窗口中发现问题的因此首先怀疑的是Remote-SSH 连接异常远程服务器上的.vscode-server损坏Codex 后台进程无法在服务器启动SSH 配置或者网络代理存在问题。但是经过进一步测试我发现即使完全不连接远程服务器只在本地打开 VS CodeCodex 也会随机卡在加载页面。因此这个问题不能简单归因于 SSH 或远程服务器。二、具体故障现象问题主要表现为打开 VS Code点击左侧活动栏中的 Codex 图标Codex 页面一直显示加载动画没有明确的报错弹窗第一个 VS Code 窗口有时能正常打开第二个或第三个窗口更容易打不开有时所有窗口都正常有时只有部分窗口正常本地窗口和 Remote-SSH 窗口都可能出现删除下面的目录后第一次打开通常能恢复~/.config/Code/Service Worker但是在继续打开新窗口、重新启动 VS Code或者再次进入 Codex 后问题又会复现。整个现象看起来非常随机像是在“碰运气”。三、为什么删除 Service Worker 只能暂时恢复VS Code 中的 Codex 面板并不是一个普通的原生控件而是一个 Webview。可以把 Webview 简单理解为VS Code 内部嵌入的一个网页运行环境。Codex 页面打开时需要加载很多资源包括JavaScript 文件CSS 样式文件字体和图标Webview 本地资源Service WorkerCodex 后台服务通信本地 IPC Socket网络连接日志和缓存文件。~/.config/Code/Service Worker中保存了部分 Webview 缓存和运行状态。将其删除后相当于让 VS Code 重新建立 Webview 缓存因此第一次可能恢复正常。但需要注意删除 Service Worker 只清除了缓存并没有修改 Linux 对 VS Code 进程的资源限制。如果真正的问题是某些 VS Code 进程能够打开的资源数量太少那么缓存重建后随着窗口和插件资源继续增加问题仍然会出现。所以删除 Service Worker 更像是暂时清理了故障状态而不是解决了根因。四、第一步排查确认 VS Code 是否真正退出最开始我使用下面的命令检查 VS Code 进程pgrep -a -f code|Code但是输出中除了 VS Code还出现了 Obsidian 和 QQ例如--code-cache-schemesapp这是因为正则中的code也会匹配其他 Electron 程序参数里的code-cache-schemes因此这条命令会产生误报。更准确的检查方法是pgrep -a -f ^/usr/share/code/code或者ps -eo pid,comm,args \ | grep -E [C]ode|[/]code \ | grep -vE obsidian|QQ|code-cache在关闭全部 VS Code 窗口后可以执行pgrep -a -f ^/usr/share/code/code \ || echo VS Code 已完全退出如果仍然能看到/usr/share/code/code进程说明 VS Code 并没有真正退出。这一步非常重要因为 VS Code 通常会复用已经存在的主进程。即使在新终端中执行ulimit -Sn 65536 code --new-window只要之前的低限制 VS Code 主进程仍然运行新窗口仍可能由旧主进程创建。此时新终端中的ulimit设置不会真正应用到旧进程。五、关键线索Linux 文件描述符限制执行下面的命令printf soft nofile: ; ulimit -Sn printf hard nofile: ; ulimit -Hn得到结果soft nofile: 1024 hard nofile: 1048576这是本次问题中最关键的线索。5.1 什么是文件描述符Linux 中程序访问某个系统资源时通常会获得一个编号这个编号叫做文件描述符 File Descriptor FD虽然名字中包含“文件”但文件描述符不仅代表普通文件还包括打开的代码文件JavaScript、CSS、图片和字体网络连接本地 Socket进程通信管道Remote-SSH 通道日志文件Webview 资源插件后台进程通信。可以将文件描述符理解为程序访问系统资源时需要使用的“资源通行证”。每打开一个文件、建立一个网络连接或者创建一条进程通信通道都可能占用一个文件描述符。5.2 soft nofile 和 hard nofile 的区别我的系统显示soft nofile: 1024 hard nofile: 1048576其中soft nofile当前进程默认实际执行的限制hard nofile普通用户能够将软限制提高到的最大值。可以类比为系统仓库最多可以容纳 1,048,576 件物品但默认只给当前程序开放了 1,024 个货位。当某个相关进程需要打开第 1025 个资源时系统就可能拒绝它。对于简单命令行程序1024 通常足够。但 VS Code 是一个复杂的 Electron 应用其中包含VS Code 主进程 ├── Renderer 渲染进程 ├── Zygote 进程 ├── GPU 进程 ├── Network Service ├── Extension Host ├── Remote-SSH ├── Codex 后台服务 └── Codex Webview当同时打开多个窗口、多个插件、Remote-SSH 和 Codex Webview 时1024 可能过低。六、对照实验临时提高限制后问题消失首先确保全部 VS Code 进程完全退出。然后在终端执行ulimit -Sn 65536 printf new soft nofile: ; ulimit -Sn输出new soft nofile: 65536接着必须在同一个终端中启动 VS Codecode --new-window测试结果为第一个 VS Code 窗口中的 Codex 正常第二个窗口中的 Codex 正常第三个窗口中的 Codex 也正常。而此前从 Ubuntu 侧边栏直接打开时第二个或第三个窗口经常加载失败。这个对照实验说明提高 VS Code 启动环境中的文件描述符软限制后Codex 多窗口加载问题可以稳定消失。七、为什么有些进程是 1048576有些仍然是 1024为了查看 VS Code 实际进程的限制可以执行for pid in $(pgrep -f ^/usr/share/code/code); do printf PID %-8s $pid grep Max open files /proc/$pid/limits 2/dev/null done实际观察到了类似结果PID 857309 Max open files 1048576 1048576 files PID 857313 Max open files 1024 1048576 files PID 857314 Max open files 1024 1048576 files PID 857349 Max open files 16384 1048576 files PID 857351 Max open files 1048576 1048576 files这说明不同 VS Code 子进程的限制并不完全相同。某些进程可能在启动后主动提高自己的软限制但某些zygoterendererutilityextension host仍然可能继承图形桌面会话的默认值1024。因此不能只看到 VS Code 主进程是 1048576就认为所有相关进程都没有限制问题。真正应该关注的是参与 Codex Webview 资源加载的 Renderer、Utility 和扩展宿主进程。只要其中的关键进程仍然是1024Codex 页面仍然可能加载失败。八、最终定位终端启动正常侧边栏启动失败进一步测试两种启动方式。方式一终端启动ulimit -Sn 65536 code --new-window结果Codex 正常方式二Ubuntu 侧边栏启动直接点击 Ubuntu Dock 中的 VS Code 图标。结果Codex 仍然卡在加载页面这说明问题和 VS Code 的启动来源有关。8.1 为什么终端和侧边栏启动不同在终端执行ulimit -Sn 65536只会影响当前 Shell以及从当前 Shell 启动的子进程。因此从这个终端启动的 VS Code 会继承65536。但是 Ubuntu 侧边栏中的应用由 GNOME 图形桌面启动。它不是当前终端的子进程也不会执行当前终端中的ulimit -Sn 65536所以侧边栏启动的 VS Code 仍可能继承soft nofile 1024整个问题链条可以表示为终端启动 VS Code ↓ 继承 soft nofile65536 ↓ Codex 正常 Ubuntu Dock 启动 VS Code ↓ 部分子进程继承 soft nofile1024 ↓ Codex Webview 部分资源无法加载 ↓ Codex 一直停留在加载页面到这里问题根因已经基本确定。九、最终解决方案最终采用的方案是创建一个专门的 VS Code 启动脚本在脚本中先执行ulimit -Sn 65536再启动真正的 VS Code创建用户级code.desktop文件让 Ubuntu 侧边栏通过这个脚本启动 VS Code。这个方案具有以下优点只影响 VS Code不需要修改全系统限制不影响其他应用普通 VS Code 更新后通常仍然有效不依赖 GNOME 是否读取 Shell 配置比只修改.bashrc更可靠。十、创建高文件描述符启动脚本执行mkdir -p ~/.local/bin cat ~/.local/bin/code-highfd EOF #!/usr/bin/env bash # 避免 VS Code 从图形桌面继承 soft nofile1024 ulimit -Sn 65536 exec /usr/bin/code $ EOF chmod x ~/.local/bin/code-highfd测试脚本~/.local/bin/code-highfd --version如果能够正常输出 VS Code 版本说明启动脚本工作正常。这里使用/usr/bin/code而不是直接使用/usr/share/code/code原因是/usr/bin/code通常是更加稳定的命令入口。十一、创建用户级 VS Code 桌面入口系统级 VS Code 桌面文件通常位于/usr/share/applications/code.desktop将它复制到用户目录mkdir -p ~/.local/share/applications cp /usr/share/applications/code.desktop \ ~/.local/share/applications/code.desktop然后将桌面文件中的启动命令替换为刚才创建的脚本sed -i \ s#^Exec/usr/share/code/code#Exec$HOME/.local/bin/code-highfd# \ ~/.local/share/applications/code.desktop为了同时兼容/usr/share/code/code和/usr/bin/code两种写法也可以直接使用sed -E \ s#^Exec(/usr/share/code/code|/usr/bin/code)#Exec$HOME/.local/bin/code-highfd# \ /usr/share/applications/code.desktop \ ~/.local/share/applications/code.desktop刷新桌面应用数据库update-desktop-database ~/.local/share/applications \ 2/dev/null || true检查修改结果grep ^Exec ~/.local/share/applications/code.desktop预期看到类似Exec/home/用户名/.local/bin/code-highfd %F Exec/home/用户名/.local/bin/code-highfd --new-window %F只要所有主要Exec项已经指向~/.local/bin/code-highfd就说明修改成功。十二、完全退出旧的 VS Code 进程修改 desktop 文件后必须完全关闭旧的 VS Code。否则新窗口可能继续复用原来继承1024限制的主进程。先保存全部文件然后正常退出 VS Code。检查是否还有进程pgrep -a -f ^/usr/share/code/code如果确认文件已经保存但进程仍未退出可以执行pkill -TERM -f ^/usr/share/code/code sleep 3 pgrep -a -f ^/usr/share/code/code \ || echo VS Code 已完全退出检查 Codex 后台进程pgrep -a -f /openai\.chatgpt-.*/codex如果存在明显残留可以执行pkill -TERM -f /openai\.chatgpt-.*/codex不建议一开始直接使用kill -9优先使用TERM让程序有机会正常保存状态并释放资源。十三、清理一次旧的 Webview 缓存此前 Codex 已经多次在低文件描述符限制下加载失败因此建议在 VS Code 完全退出后备份并重建一次缓存。执行timestamp$(date %Y%m%d_%H%M%S) for dir in \ $HOME/.config/Code/Service Worker \ $HOME/.config/Code/Cache \ $HOME/.config/Code/CachedData \ $HOME/.config/Code/GPUCache do if [ -e $dir ]; then mv $dir ${dir}.bak.${timestamp} fi done这里使用“改名备份”而不是直接删除。不要删除以下目录~/.config/Code/User ~/.codex ~/.vscode ~/.vscode-server ~/.ssh这些目录中可能包含VS Code 用户设置Codex 配置和登录状态本地插件Remote-SSH 服务端插件SSH 密钥和连接配置。本次问题不需要通过删除这些目录解决。十四、重新固定 Ubuntu 侧边栏图标Ubuntu Dock 可能仍然缓存旧的系统级 desktop 文件。建议执行以下操作右键侧边栏中的 VS Code选择“从收藏夹中移除”打开“显示应用程序”搜索 Visual Studio Code启动一次再将新图标固定到侧边栏。也可以直接测试用户级 desktop 文件gio launch ~/.local/share/applications/code.desktop如果通过gio launch启动后 Codex 正常而从 Dock 启动仍然异常说明 Dock 仍然缓存了旧入口。此时可以注销当前用户后重新登录gnome-session-quit --logout注销前务必保存当前工作。十五、验证修复是否生效从 Ubuntu 侧边栏重新打开 VS Code 后执行for pid in $(pgrep -f ^/usr/share/code/code); do cmd$(tr \0 /proc/$pid/cmdline 2/dev/null) type$(printf %s $cmd \ | sed -n s/.*--type\([^ ]*\).*/\1/p) [ -n $type ] || typemain-or-helper soft$(awk /Max open files/{print $4} \ /proc/$pid/limits 2/dev/null) printf PID%-8s soft%-8s type%s\n \ $pid $soft $type done重点观察typerenderer typeutility typemain-or-helper理想结果为soft65536或者soft1048576两者都可以。关键是参与 Codex Webview 加载的进程不应继续显示soft1024查看实际使用的文件描述符数量可以执行for pid in $(pgrep -f /usr/share/code/code --typerenderer); do fd_count$( find /proc/$pid/fd \ -mindepth 1 \ -maxdepth 1 \ 2/dev/null \ | wc -l ) printf Renderer PID%-8s open_fd%s\n \ $pid $fd_count done需要说明的是将上限设置为 65536并不代表 VS Code 会立即占用 65536 个文件描述符。这只是允许 VS Code 在需要时最多使用这么多。实际使用数量通常远小于限制值。十六、为什么不直接修改.bashrc有些教程建议在~/.bashrc中加入ulimit -Sn 65536这种方式只对以下情况有效打开 Bash 终端从该终端启动程序。但是 Ubuntu Dock 启动的 VS Code 不是 Bash 的子进程因此它通常不会读取交互式.bashrc中的ulimit。最终可能仍然出现终端启动正常 侧边栏启动失败使用code-highfd启动脚本的优点是无论从终端还是桌面入口启动都会先主动设置限制。因此更稳定。十七、为什么本地问题会影响 Remote-SSH在 Remote-SSH 场景中VS Code 可以简单分成两部分本地 Ubuntu ├── VS Code 主界面 ├── Codex 侧边栏 Webview ├── Electron Renderer └── Remote-SSH 客户端 远程服务器 ├── ~/.vscode-server ├── 远程扩展宿主 └── 远程工作区进程即使代码和终端运行在远程服务器上Codex 面板仍然需要由本地 VS Code 进行渲染。因此本地 Renderer 或 Webview 存在资源限制时会同时导致本地窗口中的 Codex 卡住Remote-SSH 窗口中的 Codex也卡住。这也说明当本地和远程都出现相同加载问题时不应该首先删除服务器端.vscode-server。如果 Remote-SSH 可以正常连接远程文件和终端也能正常使用那么 SSH 配置通常不是 Codex 加载失败的首要原因。十八、什么时候需要检查服务器端只有在本地高限制启动已经正常但 Remote-SSH 窗口仍单独失败时才继续检查服务器。可以执行ls -ld ~/.vscode-server ls -ld ~/.codex ls -ld /tmp ls -ld /tmp/codex-ipc 2/dev/null重点检查文件夹所有者是否正确是否被其他用户创建是否存在Permission denied/tmp/codex-ipc是否可写远程扩展宿主是否反复退出。如果怀疑远程 VS Code Server可以先在命令面板中执行Remote-SSH: Kill VS Code Server on Host...不建议一开始就执行rm -rf ~/.vscode-server因为这会同时删除远程 VS Code Server所有远程扩展扩展运行数据有价值的诊断日志。十九、VS Code 更新后如何处理本次修复使用的是~/.local/bin/code-highfd ~/.local/share/applications/code.desktop这两个文件位于用户目录中。正常使用以下命令更新 VS Codesudo apt update sudo apt upgrade一般不会删除这两个文件。因此普通更新后通常不需要重新配置。不过大版本更新后系统级 desktop 文件可能增加新的启动参数。可以重新同步一次mkdir -p ~/.local/share/applications sed -E \ s#^Exec(/usr/share/code/code|/usr/bin/code)#Exec$HOME/.local/bin/code-highfd# \ /usr/share/applications/code.desktop \ ~/.local/share/applications/code.desktop chmod 644 ~/.local/share/applications/code.desktop update-desktop-database ~/.local/share/applications \ 2/dev/null || true更新后应完全退出旧版本 VS Code再重新启动。否则新窗口可能继续复用旧版本进程新 desktop 文件不会立即生效新的文件描述符限制也不会重新继承。二十、Codex 插件更新后再次卡住怎么办如果以后更新 Codex 插件后再次卡在加载页面可以按照以下顺序处理。第一步查看进程限制for pid in $(pgrep -f ^/usr/share/code/code); do printf PID %-8s $pid grep Max open files /proc/$pid/limits 2/dev/null done第二步完全退出 VS Codepkill -TERM -f ^/usr/share/code/code第三步备份清理 Webview 缓存timestamp$(date %Y%m%d_%H%M%S) for dir in \ $HOME/.config/Code/Service Worker \ $HOME/.config/Code/Cache \ $HOME/.config/Code/CachedData \ $HOME/.config/Code/GPUCache do if [ -e $dir ]; then mv $dir ${dir}.bak.${timestamp} fi done第四步从修复后的桌面入口启动gio launch ~/.local/share/applications/code.desktop不要直接删除~/.codex ~/.vscode ~/.vscode-server ~/.ssh二十一、如何查看 Codex Webview 错误当 Codex 卡在加载页面时可以在 VS Code 中打开帮助 → 切换开发人员工具在 Console 中搜索ERR_INSUFFICIENT_RESOURCES net::ERR_FAILED service worker openai.chatgpt codex ERR_FILE_NOT_FOUND还可以在终端中搜索最近日志find ~/.config/Code/logs \ -type f \ -mmin -10 \ -print0 \ | xargs -0 grep -InaE \ ERR_INSUFFICIENT_RESOURCES|net::ERR_FAILED|service.?worker|openai\.chatgpt|codex|ERR_FILE_NOT_FOUND \ 2/dev/null \ | tail -n 300如果日志中存在大量资源加载失败同时关键 Renderer 的Max open files又是1024那么文件描述符限制仍然应作为优先排查方向。二十二、一键检查脚本可以将下面的内容保存为check-vscode-codex.sh#!/usr/bin/env bash echo 当前 Shell 限制 printf soft nofile: ulimit -Sn printf hard nofile: ulimit -Hn echo echo VS Code 进程 mapfile -t pids ( pgrep -f ^/usr/share/code/code 2/dev/null ) if [ ${#pids[]} -eq 0 ]; then echo 未发现 VS Code 进程 exit 0 fi for pid in ${pids[]}; do cmd$( tr \0 \ /proc/$pid/cmdline \ 2/dev/null ) type$( printf %s $cmd \ | sed -n s/.*--type\([^ ]*\).*/\1/p ) [ -n $type ] || typemain-or-helper soft$( awk /Max open files/{print $4} \ /proc/$pid/limits \ 2/dev/null ) hard$( awk /Max open files/{print $5} \ /proc/$pid/limits \ 2/dev/null ) fd_count$( find /proc/$pid/fd \ -mindepth 1 \ -maxdepth 1 \ 2/dev/null \ | wc -l ) printf \ PID%-8s soft%-8s hard%-8s fd%-6s type%s\n \ $pid \ $soft \ $hard \ $fd_count \ $type done echo echo Codex 后台进程 pgrep -a -f /openai\.chatgpt-.*/codex \ || echo 未发现 Codex 后台进程赋予执行权限chmod x check-vscode-codex.sh运行./check-vscode-codex.sh二十三、回滚方法如果不希望继续使用用户级启动器可以执行回滚。删除用户 desktop 文件rm -f ~/.local/share/applications/code.desktop删除启动脚本rm -f ~/.local/bin/code-highfd刷新桌面应用数据库update-desktop-database ~/.local/share/applications \ 2/dev/null || true然后从 Ubuntu Dock 移除 VS Code注销并重新登录从应用程序列表中重新固定系统默认 VS Code。此前备份的缓存目录名称类似Service Worker.bak.时间 Cache.bak.时间 CachedData.bak.时间 GPUCache.bak.时间确认新缓存长期正常后可以手动删除旧备份。二十四、本次排查中的关键经验1. 本地和远程同时异常不一定是 SSH如果本地 VS Code 和 Remote-SSH 都会卡住而 SSH 本身连接正常应优先排查本地 Webview、Renderer 和桌面启动环境。2. 删除缓存后恢复不代表缓存是唯一根因删除 Service Worker 只能证明缓存参与了故障不代表底层资源限制已经解决。3.ulimit只影响当前 Shell 和子进程在终端执行ulimit -Sn 65536不会自动改变 Ubuntu Dock 启动的应用。4. 新窗口可能仍然复用旧进程如果旧 VS Code 没有退出即使在高限制终端执行code --new-window新窗口也可能继续属于旧的低限制进程。5. 不能只检查 VS Code 主进程VS Code 是多进程应用。主进程显示1048576并不代表 Renderer、zygote 和 utility 进程也相同。6. 不要一开始就删除全部配置直接删除以下目录风险很大~/.vscode ~/.vscode-server ~/.codex ~/.ssh应先查看进程限制、日志、权限和缓存状态再逐层排查。二十五、最终结论本次故障的完整因果链可以总结为Ubuntu 图形桌面启动 VS Code ↓ 部分 VS Code/Electron 子进程继承 soft nofile1024 ↓ Codex Webview 加载文件、网络连接和通信通道 ↓ 部分资源无法继续打开 ↓ Codex 页面停留在加载动画 ↓ 删除 Service Worker 后暂时恢复 ↓ 继续多开窗口后再次失败最终解决流程为创建 code-highfd 启动脚本 ↓ 启动前执行 ulimit -Sn 65536 ↓ 用户级 code.desktop 指向该脚本 ↓ 完全退出旧 VS Code ↓ 备份清理一次 Webview 缓存 ↓ 重新固定 Ubuntu Dock 图标 ↓ Codex 本地与 Remote-SSH 多窗口恢复正常一句话总结问题不是 Codex 登录失败也不是 SSH 配置损坏而是 Ubuntu 侧边栏启动的部分 VS Code 子进程仍受soft nofile1024限制。通过为 VS Code 单独建立高文件描述符启动入口可以解决 Codex 随机卡在加载页面的问题。