PowerShell 5.1通过SSH发送脚本字符串的转义与执行差异问题
问题:通过SSH远程执行PowerShell脚本修改sshd_config时的参数拆分错误
我在PowerShell 5.1中尝试通过SSH将PowerShell脚本以字符串形式发送到远程计算机,目标是修改其sshd_config配置文件。此前已解决特殊字符序列的转义问题,但发现ssh $Username@$ComputerIP $stringScript的执行逻辑与cmd.exe /c $stringScript不同,执行时出现错误。
我的预期代码
$forceOnlyKeysSSH = '`nMatch all`n`tPasswordAuthentication no' $rmtPSAuthOnlyKeys = "powershell Add-Content -Force -Verbose -Path c:\ProgramData\ssh\sshd_config " + "-Value \`"$forceOnlyKeysSSH\`"" ssh -o ConnectTimeout=10 $Username@$ComputerIP $rmtPSAuthOnlyKeys
理想执行结果
向sshd_config文件添加以下内容:
Match all PasswordAuthentication no
实际错误提示
Add-Content : A positional parameter cannot be found that accepts argument 'all PasswordAuthentication'. At line:1 char:1 + Add-Content -Force -Verbose -Path c:\ProgramData\ssh\sshd_config -Val ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (:) [Add-Content], ParameterBindingException + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.AddContentCommand
问题原因
你确实存在字符串转义逻辑的问题,核心差异在于SSH与cmd.exe的命令参数解析逻辑完全不同:
cmd.exe /c会将整个传入的字符串当作单个完整命令处理,它会自行解析内部的引号转义,确保-Value的参数能完整传递给PowerShell,不会被空格拆分。- 而SSH在传递命令时,会将你提供的命令字符串按空格拆分为多个参数发送给远程shell;同时远程shell(Windows下默认是cmd.exe)会再次解析命令,你当前的转义方式无法保留
-Value参数的完整性,导致空格分隔的内容被拆成了多个位置参数,触发PowerShell的参数绑定错误。
解决方案
方案1:调整转义逻辑,用嵌套引号确保参数完整性
$forceOnlyKeysSSH = "`nMatch all`n`tPasswordAuthentication no" # 用单引号包裹外层命令,内部用双引号嵌套,通过重复单引号实现转义 $rmtPSAuthOnlyKeys = 'powershell "Add-Content -Force -Verbose -Path ''c:\ProgramData\ssh\sshd_config'' -Value ''''$forceOnlyKeysSSH''''"' ssh -o ConnectTimeout=10 $Username@$ComputerIP $rmtPSAuthOnlyKeys
方案2:用Base64编码彻底避免转义问题(最可靠)
PowerShell支持通过-EncodedCommand参数执行Base64编码的脚本,完全规避多层转义的问题:
# 构建要执行的脚本内容 $scriptContent = @" Add-Content -Force -Verbose -Path 'c:\ProgramData\ssh\sshd_config' -Value "`nMatch all`n`tPasswordAuthentication no" "@ # 将脚本编码为Unicode格式的Base64字符串 $encodedScript = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($scriptContent)) # 构建远程执行命令 $rmtCommand = "powershell -EncodedCommand $encodedScript" # 执行SSH命令 ssh -o ConnectTimeout=10 $Username@$ComputerIP $rmtCommand
内容的提问来源于stack exchange,提问作者JackOA
相关产品推荐
相关产品推荐

