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 | 永久 | 经常写本地脚本 |
RemoteSigned 比 Bypass 安全:本地脚本随便跑,网上下的 .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 行的 ),其实是文件开头某处编码错位导致解析器迷路。
两种修法:
- 存 UTF-8 with BOM(PowerShell 5.1 看到 BOM 就用 UTF-8)——但 VSCode 默认不加 BOM
- 改成纯 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/config 的 IdentityFile。
然后 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_ed25519OpenSSH 看到 ~ 会用 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 用户名是大量”看起来不该坏”的工具的坑源。写跨设备脚本时:
.ps1文件强制纯 ASCII(或加 BOM),不假设编辑器编码- SSH config 用
~不用绝对路径,让 OpenSSH 自己展开家目录 - 执行策略第一次跑
.ps1都要Bypass / RemoteSigned,是 Windows 默认安全策略,不是 bug
PowerShell 7(pwsh)解决了 1,但默认还是 5.1,所以兼容性写法还是 ASCII。