编码代理与终端 · 收录于 2026-08-29 · 适用 1 工具 ✓ 实测验证

PowerShell 里调 wsl 输出乱码(每字符带空字节 / 每字符一行 / 中文变 �)

已验证 2026-08-29PowerShell 调 wsl 输出乱码——脚本开头设 WSL_UTF8=1(或 cmd /c set WSL_UTF8=1 && wsl ...)。

快速修复

# 一键(在 PowerShell 脚本中执行):设置官方 UTF-8 开关,wsl 输出即恢复正常
$env:WSL_UTF8 = "1"

放在脚本开头;或临时 cmd /c "set WSL_UTF8=1 && wsl ..."。

你会遇到什么

PowerShell(5.1 和 7)里调用 wsl.exe ... 时输出乱码:w s l : ... 每个字符中间有空格(UTF-16LE 的 00 字节被当字符显示)、wsl --help | more 每字符一行(microsoft/WSL#13093 官方 issue)、中文内容变成 �。

直接 wsl echo hi > 文件(cmd 重定向)字节正常;坏的是管道/捕获场景:PowerShell 脚本赋值、CI 抓取、| 管道。

本文路径:快速修复(30 秒一段命令)→ 一步步排查(可跳读)→ 原理与变体(症状/原因/证据)。赶时间直接跳到「快速修复」。

为什么会这样

wsl.exe 在管道/非 TTY 场景输出 UTF-16LE(无 BOM),PowerShell 捕获后按自己的 stdout 编码(实测 PS 5.1 与 pwsh 7 的 -Command 链路都是 UTF-16LE 无 BOM)写到下游;下游按 UTF-8/单字节解码 → 每个 ASCII 字符被 00 隔开,中文全变 �。

这是 wsl.exe 的已知行为,2025 年的 #13093(WSL 2.5.7)仍存在。

wsl.exe 是 Windows 程序,它决定输出编码的依据是输出目的地:连到终端时按 UTF-8,连到管道/非 TTY 时按 Windows 原生宽字符 UTF-16LE(无 BOM)输出——这是 wsl.exe 的既定行为,不是 bash 决定的。

PowerShell 捕获后按自己的 stdout 编码继续传递,下游程序(按 UTF-8/单字节假设)解码时把每个 ASCII 字节后面的 00 也当字符,于是「中文字符变 �、ASCII 被 00 隔开」。

确定性推论:管道场景不要依赖 wsl 输出做文本解析,两条正路——wsl.exe -e bash -lc "..." 让 bash 层接管输出编码,或在 PowerShell 里 [Console]::OutputEncoding=[Text.Encoding]::UTF8 显式声明;

写文件用 wsl bash -lc 'cmd > file' 让重定向发生在 Linux 侧,绕开 wsl.exe 的编码判定。

一步步来

1. 设 $env:WSL_UTF8 = "1" — 必做

微软官方开关,实测 pwsh -File 下 wsl 输出变 UTF-8 正常;不想改全局就放在脚本开头。

2. 复杂/长命令别硬拼命令行 — 必做

转义、长度都会炸。把脚本写到 WSL 内文件再执行:

wsl bash /tmp/x.sh

PowerShell 写文件走 UNC:Set-Content \\wsl.localhost\Ubuntu\tmp\x.sh。

3. 超长/特殊字符用 base64 传输 — 必做

wsl bash -lc "echo <base64> | base64 -d | bash"

实测通过,绕开引号/转义/长度三坑。

4. 输出走文件 — 必做

让 wsl 内命令把结果写 /tmp/out.txt,再用 Get-Content \\wsl.localhost\Ubuntu\tmp\out.txt 读——UTF-8 文件直读无编码问题,比管道可靠。

5. 辅助手段 — 必做

[Console]::OutputEncoding = [Text.Encoding]::UTF8 影响 PowerShell 写控制台编码,可配合 1 使用。WSL 启动横幅("检测到 localhost 代理配置...")是 stderr 噪声:设了 WSL_UTF8 后不乱码,仍介意可忽略或加 2>$null。

怎么确认修好了

字节级验证(实测输出形态):

ps1 里 $env:WSL_UTF8="1" 后 & wsl.exe echo hi → 字节 77 73 6C 3A 20 E6 A3 80(UTF-8 正常,中文不丢)

复现基线:pwsh -NoProfile -Command "wsl echo hi" → 字节 77 00 73 00 6C 00 ...(UTF-16LE 无 BOM,实测)。

其它环境的表现

环境说明
cmd 重定向字节正常(UTF-8,实测对照)
PowerShell 管道/捕获UTF-16LE 无 BOM(PS 5.1 与 pwsh 7 均复现,#13093 同款)
base64 通道`wsl bash -lc "echo <b64>base64 -d"` 实测通过
文件中转/tmp/out.txt + UNC 读取,无编码问题(天天在用)
stderr 横幅WSL_UTF8 后不乱码,介意加 2>$null

症状

PowerShell(5.1 和 7)里调用 wsl.exe ... 时输出乱码:

w s l :  �hKm0R ...   # 每个字符中间有空格(UTF-16LE 的 00 字节被当字符显示)
wsl --help | more     # 每字符一行(microsoft/WSL#13093 官方 issue)
中文内容变成 � 一类替换符

特征:直接 wsl echo hi > 文件(cmd 重定向)字节正常(UTF-8); 坏的是管道/捕获场景:PowerShell 脚本赋值、CI 抓取、| 管道; WSL 启动时还会混入一段代理检测横幅(stderr),加剧观感。

原因

wsl.exe 在管道/非 TTY 场景输出 UTF-16LE(无 BOM),PowerShell 捕获后按自己的 stdout 编码 (实测 PS 5.1 与 pwsh 7 的 -Command 链路都是 UTF-16LE 无 BOM)写到下游; 下游按 UTF-8/单字节解码 → 每个 ASCII 字符被 00 隔开,中文全变 �。 这是 wsl.exe 的已知行为,2025 年的 #13093(WSL 2.5.7)仍存在。

解法

  1. 脚本里设 $env:WSL_UTF8 = "1" 再调 wsl(微软官方开关,实测 pwsh -File 下 wsl 输出变 UTF-8 正常);

不想改全局就放在脚本开头,或临时 cmd /c "set WSL_UTF8=1 && wsl ..."。

  1. 复杂/长命令别硬拼命令行(转义、长度都会炸):把脚本写到 WSL 内文件再执行:

wsl bash /tmp/x.sh;PowerShell 写文件走 UNC:Set-Content \\wsl.localhost\Ubuntu\tmp\x.sh。

  1. 超长/特殊字符用 base64 传输:wsl bash -lc "echo <base64> | base64 -d | bash"(实测通过,绕开引号/转义/长度三坑)。
  2. 输出走文件:让 wsl 内命令把结果写 /tmp/out.txt,再用 Get-Content \\wsl.localhost\Ubuntu\tmp\out.txt 读——

UTF-8 文件直读无编码问题,比管道可靠。

  1. 辅助手段:[Console]::OutputEncoding = [Text.Encoding]::UTF8 影响 PowerShell 写控制台编码,可配合 1 使用。
  2. WSL 启动横幅("检测到 localhost 代理配置...")是 stderr 噪声:设了 WSL_UTF8 后不乱码,仍介意可忽略或加 2>$null。
验证证据
  • 本地实测(2026-08-29,Windows 11 + WSL Ubuntu,PowerShell 5.1 与 pwsh 7):
  • 对照:cmd 直调 wsl.exe echo hi > 文件 → 字节 68 69 0A(UTF-8,正常);
  • 复现:pwsh -NoProfile -Command "wsl echo hi" > 文件 → 字节 77 00 73 00 6C 00 ...(UTF-16LE 无 BOM),

下游按 UTF-8 显示即 "w s l :" 乱码——与本条目开头截图同款,#13093 同款;PowerShell 5.1 同样复现;

  • 修复:ps1 里 $env:WSL_UTF8="1" 后 & wsl.exe echo hi → 字节 77 73 6C 3A 20 E6 A3 80(UTF-8 正常,中文不丢);
  • base64 通道:wsl bash -lc "echo dGVzdA== | base64 -d" → test(exit 0);
  • 文件中转:WSL 内写 /tmp/out.txt 后 UNC 读取,无编码问题(实践天天在用)。
  • 实测复现日志(2026-08-29)

适用工具 (1)

本问题方案已挂到下列工具的方案页——从工具页也能回到这里,双向可达。

wsl · 外部工具

来源与证据

收录 验证 ✓ 实测验证适用 1 工具
方案含本地实测或来源可复核的解法;未实测项已在文中如实标注。

素材来源:https://github.com/microsoft/WSL/issues/13093

← 编码代理与终端 问题域 | 问题货架 | 遇到其它问题?去 问题空间 提交求助卡