如何配置Paramiko的exec_command默认使用PowerShell执行命令?
Paramiko SSH连接Windows默认使用PowerShell的实现方案
方案一:修改Windows OpenSSH服务端默认Shell(一劳永逸,优先推荐)
Windows自带的OpenSSH服务默认将cmd.exe作为执行shell,这是所有转义问题、前缀问题的根源,直接修改注册表将默认shell改为PowerShell后,Paramiko的exec_command会直接在PowerShell环境执行,无需添加任何前缀,也不需要处理cmd的转义规则。
操作步骤:
- 登录目标Windows机器,以管理员权限打开PowerShell
- 执行以下注册表修改命令:
# 配置默认使用Windows PowerShell(系统自带,无需额外安装) New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force # 如果要使用PowerShell 7+(pwsh),将上面的Value替换为pwsh的实际安装路径,通常为: # "C:\Program Files\PowerShell\7\pwsh.exe"
- 执行命令重启SSH服务生效:
Restart-Service sshd
配置完成后,所有通过SSH下发到该机器的命令都会默认在PowerShell环境执行,Paramiko调用exec_command时直接写PowerShell命令即可,完全兼容多行命令、顺次执行逻辑,不需要额外拼接&&或cmd转义符。
方案二:无服务端修改权限时的客户端封装方案
如果没有权限修改目标机器的SSH服务配置,可以在Paramiko客户端侧做统一封装,利用PowerShell原生的EncodedCommand参数彻底解决多层转义问题,不需要手动处理引号、换行的转义逻辑。
核心逻辑:
- PowerShell的
-EncodedCommand参数支持接收UTF-16LE编码的Base64字符串作为执行内容,全程不需要对命令内的引号、特殊字符、换行做任何转义,从根源上避免cmd、PowerShell、Python三层转义规则冲突 - 封装通用执行函数,自动完成命令编码和前缀拼接,业务代码调用时不需要感知前缀存在
参考实现代码:
import base64 import paramiko def exec_pwsh(ssh_client: paramiko.SSHClient, ps_command: str): # 编码命令为EncodedCommand要求的格式,无转义问题 encoded_cmd = base64.b64encode(ps_command.encode("utf-16-le")).decode("ascii") stdin, stdout, stderr = ssh_client.exec_command( f"pwsh -NoProfile -NonInteractive -EncodedCommand {encoded_cmd}" ) exit_code = stdout.channel.recv_exit_status() return { "exit_code": exit_code, "stdout": stdout.read().decode("utf-8", errors="ignore"), "stderr": stderr.read().decode("utf-8", errors="ignore") } # 调用示例 if __name__ == "__main__": ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(hostname="你的Windows主机IP", username="用户名", password="密码") # 直接写多行命令、嵌套Python调用,不需要任何额外转义 test_command = """ Write-Host "当前PowerShell环境执行命令" python -c 'print("hello") print("world")' Get-Service sshd """ result = exec_pwsh(ssh, test_command) print("执行输出:", result["stdout"]) print("错误输出:", result["stderr"]) ssh.close()
避坑提示
- 不要手动拼接
pwsh -c "待执行命令"的格式,嵌套双引号、单引号时的转义逻辑会随着命令复杂度提升完全失控 - 切换到PowerShell环境后,直接用换行或
;分隔多条顺次执行的命令即可,不需要使用cmd的^转义符和&&连接符
内容的提问来源于stack exchange,提问作者Alex Deft
相关产品推荐
相关产品推荐

