使用Paramiko SSH执行命令返回十六进制编码输出的问题排查
Paramiko远程Windows执行命令返回乱码问题
我编写了一段Python脚本,通过Paramiko库SSH连接Windows主机,执行help命令后返回的输出为十六进制编码的字节串,而非正常可读文本。
我的脚本
import paramiko import codecs host = '*******' user = '*****' psw = '****' port = 22 ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(hostname=host, port=port, username=user, password=psw) stdin, stdout, stderr = ssh.exec_command('help') stdin.close() print(stdout.read() + stderr.read()) result = stdout.read().splitlines() ssh.close()
返回结果
b'\x84\xab\xef \xaf\xae\xab\xe3\xe7\xa5\xad\xa8\xef \xe1\xa2\xa5\xa4\xa5\xad\xa8\xa9 \xae\xa1 \xae\xaf\xe0\xa5\xa4\xa5\xab\xa5\xad\xad\xae\xa9 \xaa\xae\xac\xa0\xad\xa4\xeb>\r\nASSOC \x82\xeb\xa2\xae\xa4 \xab\xa8\xa1\xae \xa8\xa7\xac\xa5\xad\xa5\xad\xa8\xa5 \xe1\xae\xaf\xae\xe1\xe2\xa0\xa2\xab\xa5\xad\xa8\xa9 \xaf\xae \xe0\xa0\xe1\xe8\xa8\xe0\xa5\xad\xa8\xef\xac \xa8\xac\xa5\xad \xe4\xa0\xa9\xab\xae\xa2.\r\nATTRIB \x8e\xe2\xae\xa1\xe0\xa0\xa6\xa5\xad\xa8\xa5 \xa8 \xa8\xa7\xac\xa5\xad\xa5\xad\xa8\xa5 \xa0\xe2\xe0\xa8\xa1\xe3\xe2\xae\xa2 \xe4\xa0\xa9\xab\xae\xa2.\r\nBREAK \x82\xaa\xab\xee\xe7\xa5\xad\xa8\xa5 \xa8 \xa2\xeb\xaa\xab\xee\xe7\xa5\xad\xa8\xa5 \xe0\xa5\xa6\xa8\xac\xa0 \xae\xa1\xe0\xa0\xa1\xae\xe2\xaa\xa8 \xaa\xae\xac\xa1\xa8\xad\xa0\xe6\xa8\xa8 \xaa\xab\xa0\xa2\xa8\xe8 CTRL+C.\r\nBCDEDIT \x87\xa0\xa4\xa0\xa5\xe2 \xe1\xa2\xae\xa9\xe1\xe2\xa2\xa0 \xa2 \xa1\xa0\xa7\xa5 \xa4\xad\xad\xeb\xe5 \xa7\xa0\xa3\xe0\xe3\xa7\xaa\xa8 \xa4\xab\xef \xe3\xaf\xe0\xa0\xa2\xab\xa5\xad\xa8\xef \xad\xa0\xe7\xa0\xab\xec\xad\xae\xa9\r\n \xa7\xa0\xa3\xe0\xe3\xa7\xaa\xae\xa9.\r\nCACLS \x8e\xe2\xae\xa1\xe0\xa0\xa6\xa5\xad\xa8\xa5 \xa8 \xe0\xa5\xa4\x00\xaa\xe2\xa8\xe0\xae\xa2\xa0\xad\xa8\xa5 \xe1\xaf\xa8\xe1\xaa\xae\xa2 \xe3\xaf\xe0\xa0\xa2\xab\xa5\xad\xef \xa4\xae\xe1\xe2\xe3\xaf\xae\xac (ACL)\r\n \xaa \xe4\xa0\xa9\xab\x00\xac.\r\nCALL
问题分析与修正
你的代码存在两个核心问题:
1. 未处理Windows控制台编码
Windows默认控制台编码为GBK(或cp936),直接输出字节串而不用对应编码解码,会导致显示为十六进制乱码,需要将字节串解码为对应编码的字符串。
2. 重复读取标准输出流
stdout.read()会一次性读取所有输出内容,流指针会移动到末尾,后续再次调用stdout.read()会返回空值。你先执行了print(stdout.read() + stderr.read()),后续result = stdout.read().splitlines()得到的是空列表。
修正后的代码
import paramiko host = '*******' user = '*****' psw = '****' port = 22 ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(hostname=host, port=port, username=user, password=psw) stdin, stdout, stderr = ssh.exec_command('help') stdin.close() # 一次性读取所有输出,避免重复读取导致数据丢失 output_bytes = stdout.read() + stderr.read() # 使用Windows控制台默认编码cp936解码字节串为可读文本 output_str = output_bytes.decode('cp936') print(output_str) result = output_str.splitlines() ssh.close()
说明
- 用
decode('cp936')适配Windows控制台编码,将字节串转换为可读文本; - 只读取一次输出内容,确保后续处理能拿到完整数据;
- 如果你的Windows系统使用UTF-8等其他编码,可替换
cp936为对应编码。
内容的提问来源于stack exchange,提问作者Dmitriy
相关产品推荐
相关产品推荐

