Windows 配 SSH key 三连坑

在 Windows 10/11(PowerShell 5.1)上写脚本自动生成 ed25519 key、配 ~/.ssh/config 别名时连撞三个坑,记一下下次别再趟。

操作机的中文 Windows 用户名触发了其中两个。

坑 1:执行策略禁脚本

.\setup.ps1 直接报:

.\setup.ps1 : 无法加载文件 ...\setup.ps1,因为在此系统上禁止运行脚本。
有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 ...
SecurityError: ... UnauthorizedAccess

Windows 默认 Restricted,不让跑任何 .ps1。三档解法:

方案命令范围何时用
A 临时(当前会话)Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass关窗就失效推荐,一次性脚本
B 单次调用powershell -ExecutionPolicy Bypass -NoExit -File .\setup.ps1仅本次双击 / 自动化调用
C 长期(当前用户)Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned永久经常写本地脚本

RemoteSignedBypass 安全:本地脚本随便跑,网上下的 .ps1 要签名。

坑 2:UTF-8 无 BOM + 中文 / 框线字符 → PowerShell 5.1 解析炸

第一版脚本写了中文注释 + ════ 双线字符做装饰。文件存的是 UTF-8 无 BOM(VSCode 默认),PowerShell 5.1 按系统 ANSI 代码页(中文 Windows 是 GBK / CP936)读文件。

结果:

所在位置 ...\setup.ps1:5 字符: 1
+ )
+ ~
表达式或语句中包含意外的标记")"。
所在位置 ...\setup.ps1:13 字符: 1
+ }
+ ~
...
Write-Host "鈺愨晲鈺愨晲鈺愨晲鈺愨晲 鍏挜锛堝凡鎷峰埌鍓创鏉匡級鈺愨晲鈺愨晲鈺愨晲鈺愨晲"

鈺愨晲 就是 ════ 的 UTF-8 字节被 GBK 错读出来的样子。乱码字节里夹了引号 / 大括号变体,把整个脚本结构搞崩——错误显示在第 5 行的 ),其实是文件开头某处编码错位导致解析器迷路。

两种修法

  1. 存 UTF-8 with BOM(PowerShell 5.1 看到 BOM 就用 UTF-8)——但 VSCode 默认不加 BOM
  2. 改成纯 ASCII(去中文、去框线字符,用 ----- 代替 ════)——最稳,跟编辑器编码无关

我选了 2,纯 ASCII。

PowerShell 7+pwsh)默认按 UTF-8 读,没这问题。但 Windows 自带的是 5.1,写跨用户的脚本必须按 5.1 兜底。

坑 3:含中文用户名的 IdentityFile 绝对路径,OpenSSH for Windows 找不到

脚本里 $key = "$sshDir\my_ed25519" 展开成 C:\Users\<中文用户名>\.ssh\my_ed25519,写进 ~/.ssh/configIdentityFile

然后 ssh myhost 报:

no such identity: C:\\Users\\\NNN\NNN\NNN\NNN\NNN\NNN\\.ssh\\my_ed25519: No such file or directory
ubuntu@<server-ip>'s password:

\NNN\NNN\NNN\NNN\NNN\NNN 是 GBK 编码的中文用户名被 ssh 客户端按 octal escape 显示出来。文件真的存在,OpenSSH for Windows 拼路径时编码处理不对,找不到。

修法:把 IdentityFile 改成 ~ 展开形式:

IdentityFile ~/.ssh/my_ed25519

OpenSSH 看到 ~ 会用 Windows wide-char API(SHGetFolderPathW)自取家目录,绕开 ANSI/GBK 路径转换。

一行修复 config

(Get-Content "$env:USERPROFILE\.ssh\config" -Raw) -replace 'IdentityFile [^\r\n]*my_ed25519', 'IdentityFile ~/.ssh/my_ed25519' | Set-Content "$env:USERPROFILE\.ssh\config" -NoNewline

一般化原则

中文 Windows 用户名是大量”看起来不该坏”的工具的坑源。写跨设备脚本时:

  1. .ps1 文件强制纯 ASCII(或加 BOM),不假设编辑器编码
  2. SSH config 用 ~ 不用绝对路径,让 OpenSSH 自己展开家目录
  3. 执行策略第一次跑 .ps1 都要 Bypass / RemoteSigned,是 Windows 默认安全策略,不是 bug

PowerShell 7(pwsh)解决了 1,但默认还是 5.1,所以兼容性写法还是 ASCII。