解决从非Windows设备SSH到WSL2执行单条命令时wsl.exe不支持-c参数的错误
解决从非Windows设备SSH到WSL2执行单条命令时wsl.exe不支持-c参数的错误
我完全懂你的困扰:把Windows 11的OpenSSH默认Shell设为wsl.exe后,交互式SSH登录没问题,但一执行单条命令(比如ssh me@host 'cat file')就报错,因为Windows sshd会给默认Shell传-c参数,而wsl.exe根本不认这个,它只认-e来指定执行的命令。连scp都受影响,这确实挺头疼的。
下面给你一套可行的解决方案,核心是用一个包装脚本来转换sshd传递的参数,让wsl.exe能正确识别:
步骤1:创建参数转换的PowerShell包装脚本
在C:\Program Files\OpenSSH目录下新建一个wsl-wrapper.ps1文件,内容如下:
# 处理sshd传递的参数,适配wsl.exe的参数格式 if ($args.Count -ge 2 -and $args[0] -eq "-c") { $targetCommand = $args[1] # 判断是否是scp命令,若是交给Windows cmd处理(保证scp正常工作) if ($targetCommand -match "^scp") { cmd.exe /c $targetCommand } else { # 把命令传给WSL的bash,用bash的-c参数执行 wsl.exe -e bash -c $targetCommand } } else { # 无命令参数时,直接启动WSL交互式Shell wsl.exe }
步骤2:修改OpenSSH的默认Shell配置
打开管理员权限的PowerShell,执行以下命令,把默认Shell改成PowerShell,并指定用我们的包装脚本处理命令:
# 设置默认Shell为PowerShell New-ItemProperty -Path "HKLM:SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force # 指定PowerShell启动时执行的包装脚本 New-ItemProperty -Path "HKLM:SOFTWARE\OpenSSH" -Name DefaultShellCommandOption -Value "-ExecutionPolicy Bypass -File `"C:\Program Files\OpenSSH\wsl-wrapper.ps1`"" -PropertyType String -Force
步骤3:重启OpenSSH服务
执行命令重启服务,让配置生效:
Restart-Service sshd
为什么这个方案有效?
- Windows的OpenSSH服务在执行远程命令时,默认会给指定的
DefaultShell传递-c "要执行的命令"参数,但wsl.exe不支持-c,只支持-e来指定要运行的可执行程序。 - 我们的包装脚本先接住
-c参数,把后面的命令提取出来,再传给wsl.exe -e bash -c——bash是支持-c参数的,这样就完成了参数格式的转换。 - 额外处理了scp的情况:因为scp依赖Windows环境来处理文件传输,所以当检测到是scp命令时,直接交给cmd.exe执行,避免WSL环境干扰。
测试验证
现在你可以试试之前报错的命令:
ssh me@host 'cat file' > local-file
应该能正常把WSL里的file内容下载到本地了。同时scp命令也能正常使用,比如:
scp me@host:/path/to/wsl/file ./local-dir/
备注:内容来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

