python paramiko 远程调用 常见问题总结
问题1: b'Unable to execute command or shell on remote system: Failed to Execute process.\r\n’
解决方法:
这是因为在远程执行Windows命令的时候,需要添加上cmd /c,如下所示:
问题2: 执行rmdir命令时报告错误: b'Invalid switch -
解决方法:
这是因为远程调用rmdir命令删除目录时,目录的路径需要注意使用Windows路径,但又由于Python对于Windows的反斜杠路径支持不友好,需要在路径字符串的处理时添加r作为前缀处理。如下提供的解决方法 r’E:\tsss':
问题3:执行远程命令时报告 Permission denied
解决方法:
可能情况1: 通常该问题是由于远程文件夹或文件的权限问题导致。比如目录只读权限,比如文件的用户归属问题。这里只能说提供一个供参考的解决方式:使用freeSSHD搭建服务的时候添加远程机器的管理员作为ssh的远程访问登录用户进行操作。(通常使用sftp容易出现问题,可以直接使用Windows系统命令处理,Unix/Linux也可以使用对应的系统命令)
可能情况2: 使用sftp上传或下载文件时,包括删除文件或目录时,需要注意:
a. sftp只能删除空目录,所以如果要删除目录,先必须循环迭代删除目录中的文件(sftp.remove),再删除目录(sftp.rmdir)。
b. sftp的使用需要配合ssh服务设置的共享根目录,比如如果使用了freesshd搭建了远程机器的ssh服务,在配置了sftp的根目录后,sftp对于远程目录路径的操作需要使用相对路径(相对于根目录),而不是使用绝对路径。
问题4: paramiko.ssh_exception.AuthenticationException: Authentication failed.
解决方法:
这是由于ssh远程登录的账号或密码不正确导致。
问题5:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa8 in position 54: invalid start byte
解决方法:
这通常是由于字符编码导致的问题,根本原因是Paramiko的字符编码写的很死,在paramiko的py3compat.py包中存在一个u方法,其中将字符编码写死了,必须是’utf-8’,如果遇到中文之类的字符就会报错。u方法如下所示:
可以将该u方法进行重写,重写如下所示:
1 def u(s, encoding="utf8"): 2 """cast bytes or unicode to unicode""" 3 if isinstance(s, bytes): 4 try: 5 return s.decode(encoding) 6 except UnicodeDecodeError: 7 return s.decode('ISO-8859-1') 8 elif isinstance(s, str): 9 return s 10 else: 11 raise TypeError("Expected unicode or bytes, got {!r}".format(s))
问题6: ssh_client.exec_command执行很长时间卡住,没有任何输出
解决方法:这可能是因为执行的命令返回的输出内容很大,导致无法及时打印。解决方法可以使用channel轮回查询的方式,代码参考如下:
1 import sys 2 import time 3 import select 4 import paramiko 5 6 host = 'test.example.com' 7 i = 1 8 9 # 10 # Try to connect to the host. 11 # Retry a few times if it fails. 12 # 13 while True: 14 print "Trying to connect to %s (%i/30)" % (host, i) 15 16 try: 17 ssh = paramiko.SSHClient() 18 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 19 ssh.connect(host) 20 print "Connected to %s" % host 21 break 22 except paramiko.AuthenticationException: 23 print "Authentication failed when connecting to %s" % host 24 sys.exit(1) 25 except: 26 print "Could not SSH to %s, waiting for it to start" % host 27 i += 1 28 time.sleep(2) 29 30 # If we could not connect within time limit 31 if i == 30: 32 print "Could not connect to %s. Giving up" % host 33 sys.exit(1) 34 35 # Send the command (non-blocking) 36 stdin, stdout, stderr = ssh.exec_command("my_long_command --arg 1 --arg 2") 37 38 # Wait for the command to terminate 39 while not stdout.channel.exit_status_ready(): 40 # Only print data if there is data to read in the channel 41 if stdout.channel.recv_ready(): 42 rl, wl, xl = select.select([stdout.channel], [], [], 0.0) 43 if len(rl) > 0: 44 # Print data from stdout 45 print stdout.channel.recv(1024), 46 47 # 48 # Disconnect from the host 49 # 50 print "Command done, closing SSH connection" 51 ssh.close()
该方案转自:http://sebastiandahlgren.se/2012/10/11/using-paramiko-to-send-ssh-commands/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步