Codex 在 Windows 原生环境、WSL 与 PowerShell 编码问题排查记录

技术实践18 次阅读17 分钟

背景

在 Codex 桌面端中,Windows原生环境下,Codex在运行终端命令时使用本地powershell出现文件输出乱码,修复时导致文件损坏。

经过排查发现这更可能来自本地编译和终端执行路径:系统是 Windows,当 Codex 通过 PowerShell 终端执行命令时,Codex 和现代工具链通常倾向于使用 UTF-8,但 Windows PowerShell 或部分 Windows 命令链路可能仍然使用 GBK / UTF-16 / ANSI 等编码。这种不一致会导致中文输出乱码;更严重时,如果文件被再次读写,可能造成源码文件编码变化、BOM 变化,甚至文件内容损坏。

基于这个判断,我尝试将 Codex 设置中的智能体运行环境从 Windows 原生环境切换到 WSL,希望借助 Linux 用户空间和更一致的 UTF-8 工具链来规避 Windows PowerShell 编码问题。

切换后出现两个现象:

  • 历史对话 Session 看起来全部丢失。

  • 智能体无法正常对话或执行任务。

切回 Windows 原生环境后,历史 Session 和对话能力恢复正常。随后我继续沿着编码方向排查,确认真正需要处理的是 Windows 原生环境下 PowerShell 运行时和文件写入编码策略。

本文记录这两个问题的排查、处理方法和最终结论。

一、WSL 切换后历史 Session 消失的问题

现象

在 Codex 设置中将智能体运行环境从 Windows 原生环境切换到 WSL 后:

  • 历史对话不可见。

  • 智能体无法正常使用。

  • 切回 Windows 原生环境后,历史对话恢复。

排查

首先检查 WSL 本体版本:

wsl --version

检查结果显示 WSL 本体版本较新:

WSL version: 2.7.3.0
Kernel version: 6.6.114.1-1

这说明问题并不是 WSL 本体版本过低。

继续检查 WSL 发行版:

wsl -l -v

当时返回的信息表明:系统中没有可用的 Linux 发行版。也就是说,虽然 Docker 安装过程中启用了 WSL 相关组件,但并没有配置好一个可供 Codex 作为运行环境使用的 Linux 发行版。

原因

WSL 本体和 Linux 发行版不是一回事。

  • WSL 本体:Windows 提供的 Linux 子系统能力。

  • Linux 发行版:Ubuntu、Debian 等实际的 Linux 用户空间环境。

Docker 安装时可能会启用 WSL2,但这不等价于已经有一个适合 Codex 使用的默认 Linux 发行版。

同时,Codex 的历史 Session 在 Windows 原生环境和 WSL 环境之间大概率是隔离的:

  • Windows 原生环境使用 Windows 用户目录和本地状态。

  • WSL 环境使用 Linux 发行版中的 /home/<user> 和对应状态。

因此,切换到 WSL 后历史 Session 看起来为空,并不代表 Windows 原生环境下的历史被删除。切回 Windows 后历史恢复,就是这一点的直接证据。

处理建议

如果确实需要使用 WSL,可以安装并设置默认发行版:

wsl --list --online
wsl --install -d Ubuntu-24.04
wsl -l -v
wsl --set-default Ubuntu-24.04

首次进入 Ubuntu 后,安装基础工具:

sudo apt update
sudo apt install -y git curl ca-certificates build-essential

如果非常依赖已有历史 Session,建议继续使用 Windows 原生环境;只在确实需要 Linux 工具链时切换到 WSL。

二、Windows PowerShell 5.1 的编码风险

现象

在 Windows 原生环境中运行 Codex 时,PowerShell 命令可能出现:

  • 中文输出乱码。

  • PowerShell 管道输出编码不一致。

  • 文件再次写入后编码被改成 GBK/ANSI。

  • UTF-8 源码文件被破坏。

初始环境

检查当前 PowerShell 版本和编码:

$PSVersionTable.PSVersion
[Console]::InputEncoding
[Console]::OutputEncoding
$OutputEncoding
chcp

最初环境是 Windows PowerShell 5.1:

Major: 5
Minor: 1

同时活动代码页为:

Active code page: 936

936 是简体中文 GBK 代码页。这个组合很容易导致现代 UTF-8 工具链出现乱码和文件编码问题。

此外,PowerShell profile 中还有一行:

fnm env --use-on-cd | Out-String | Invoke-Expression

但当前环境中找不到 fnm,导致每次启动 shell 时都会输出报错,并且报错本身也可能出现乱码。

第一阶段处理:修复 PowerShell profile

对 Windows PowerShell 5.1 的 profile 做了 UTF-8 初始化:

chcp 65001 > $null

$utf8 = New-Object System.Text.UTF8Encoding $false
[Console]::InputEncoding = $utf8
[Console]::OutputEncoding = $utf8
$OutputEncoding = $utf8

if (Get-Command fnm -ErrorAction SilentlyContinue) {
fnm env --use-on-cd | Out-String | Invoke-Expression
}

验证结果:

chcp
[Console]::OutputEncoding.WebName
$OutputEncoding.WebName

得到:

Active code page: 65001
utf-8
utf-8

这说明控制台输入输出已经切换到 UTF-8。

关键发现:显示正常不等于写入安全

虽然 Windows PowerShell 5.1 的控制台输出已经是 UTF-8,但进一步测试发现,默认 Set-Content 写入中文文件时,真实字节仍然是 GBK。

测试字符串:

微信读书 UTF-8 写入测试:中文正常 abc123

Windows PowerShell 5.1 默认写入后的前几个字节:

CE A2 D0 C5 B6 C1 CA E9

这是 GBK 编码下的“微信读书”,不是 UTF-8。

真正的 UTF-8 字节应该是:

E5 BE AE E4 BF A1 E8 AF BB E4 B9 A6

这个发现说明:仅仅把 chcp 和输出编码改成 UTF-8,还不足以保证 Windows PowerShell 5.1 的文件写入安全。

三、切换到 PowerShell 7

安装和验证

安装 PowerShell 7:

winget install Microsoft.PowerShell

进入 PowerShell 7:

pwsh

验证版本:

$PSVersionTable.PSVersion

最终确认版本为:

PowerShell 7.6.1

继续验证编码:

chcp
[Console]::OutputEncoding.WebName
$OutputEncoding.WebName

结果:

Active code page: 65001
utf-8
utf-8

PowerShell 7 写入测试

Codex 重启后,再次测试“微信读书”中文写入。

结果显示 Codex 当前使用:

PowerShell 7.6.1

pwsh.exe 路径为:

C:\Program Files\WindowsApps\Microsoft.PowerShell_7.6.1.0_x64__8wekyb3d8bbwe\pwsh.exe

写入文件后的真实字节:

E5 BE AE E4 BF A1 E8 AF BB E4 B9 A6

并且:

HasUtf8Bom: False

这说明 PowerShell 7 默认写入结果为 UTF-8 no BOM,符合预期。

四、Windows Terminal 默认配置的补充说明

排查过程中还发现,Windows Terminal 的默认 profile 仍然可能指向 Windows PowerShell 5.1:

Name: Windows PowerShell

这不一定影响 Codex,因为 Codex 可以单独找到并使用 PowerShell 7。但如果希望手动打开 Windows Terminal 时也默认进入 PowerShell 7,需要修改 Windows Terminal 的默认 profile。

配置文件位置:

$env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json

defaultProfile 改成 PowerShell 7 对应的 GUID。例如本机 PowerShell 7 profile 是:

"guid": "{574e775e-4f2a-5b96-ac1e-a2962a402336}",
"name": "PowerShell",
"source": "Windows.Terminal.PowershellCore"

则可将:

"defaultProfile": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}"

改成:

"defaultProfile": "{574e775e-4f2a-5b96-ac1e-a2962a402336}"

注意:不同机器上的 GUID 可能不同,应以本机 settings.json 为准。

五、写入 AGENTS.md 作为硬性标准

为了避免后续 Codex 会话再次退回 Windows PowerShell 5.1,在 E:\Project\AGENTS.md 中加入了工作区级约束:

## Local PowerShell Runtime
  • When running local PowerShell commands on Windows, Codex must use PowerShell 7 (pwsh) rather than Windows PowerShell 5.1 (powershell.exe).

  • This is a hard requirement to avoid Windows PowerShell 5.1 encoding issues, including GBK/ANSI file writes, garbled UTF-8 output, BOM changes, and source file corruption.

  • Before any command that writes files through PowerShell, verify the runtime is PowerShell 7 or invoke pwsh explicitly.

  • Avoid rewriting source files through ambiguous PowerShell pipelines or redirection. Prefer patch-based edits; when shell file writes are unavoidable, use explicit UTF-8 no BOM encoding.

写入后验证:

PSVersion: 7.6.1
HasUtf8Bom: False

说明 AGENTS.md 是通过 PowerShell 7 写入,并保持 UTF-8 no BOM。

六、最终结论

1. WSL 问题结论

Codex 切换到 WSL 后历史 Session 消失,并不是历史被删除,也不是 WSL 本体版本过低。

更准确的原因是:

  • 当时没有配置好可用的默认 Linux 发行版。

  • Windows 原生环境和 WSL 环境的用户目录、配置、缓存、Session 索引大概率是隔离的。

因此,切回 Windows 原生环境后历史恢复是正常现象。

2. PowerShell 编码问题结论

Windows PowerShell 5.1 即使配置了:

chcp 65001
[Console]::OutputEncoding = utf-8
$OutputEncoding = utf-8

也仍然可能在默认 Set-Content 写文件时使用 GBK/ANSI,存在破坏 UTF-8 源码文件的风险。

更稳妥的解决方案是:

  • Codex 在 Windows 本地运行 PowerShell 命令时使用 PowerShell 7 pwsh

  • 避免通过 PowerShell 管道或重定向重写源码文件。

  • 需要写文件时明确使用 UTF-8 no BOM。

  • 将该要求写入 AGENTS.md,作为项目级硬性规范。

3. 当前状态

当前 Codex 环境已经确认:

PowerShell: 7.6.1
中文写入: UTF-8
BOM: False

也就是说,Codex 侧的 PowerShell 编码风险已经处理完成。

七、推荐日常规范

后续在 Windows 原生环境下使用 Codex,建议遵循以下规则:

  1. 本地 PowerShell 命令优先使用 pwsh,不要使用 Windows PowerShell 5.1。

  2. 不使用 Get-Content file | Set-Content file 这类读写同一文件的管道操作。

  3. 不用 >>> 重定向生成或覆盖源码文件。

  4. 源码修改优先使用补丁方式或编辑器。

  5. 必须脚本写文件时,显式指定 UTF-8 no BOM。

  6. 对包含中文的文件,必要时检查真实字节,而不只看终端显示是否正常。

附:安全写入 UTF-8 no BOM 的示例

PowerShell 7:

Set-Content .\file.md -Value $text -Encoding utf8NoBOM

Windows PowerShell 5.1:

[System.IO.File]::WriteAllText(
  "C:\path\file.md",
  $text,
  (New-Object System.Text.UTF8Encoding $false)
)
蜀ICP备2026026332号-1