当前位置:   article > 正文

python使用paramiko实现SSH的应用_modulenotfounderror: no module named 'cryptography

modulenotfounderror: no module named 'cryptography

一、说明

        Paramiko是Python编程语言的一个SSH客户端。它在Python中实现了SSHv2协议,支持使用加密和认证的方式登录SSH服务器、上传和下载文件,以及执行SSH命令等功能。本文记录实验:在python下调用paramiko实现ssh功能后,出错和恢复。

二、Paramiko的特点 

  • 支持SSHv2协议和SFTP协议
  • 支持密码和密钥认证
  • 提供高级的加密和身份验证选项
  • 可以执行远程命令和传输文件
  • 支持多种认证方式,如用户名密码、公钥、密钥等
  • 允许通过Shell、SFTP或SCP等通道访问远程服务器

        由于Paramiko的功能强大,易于使用,因此在自动化管理、配置管理和任务调度等方面得到了广泛的应用。

三、python使用paramiko实现ssh的功能详解

        个人认为python的paramiko模块是运维人员必学模块之一,其ssh登录功能是旅行居家必备工具。

        安装paramiko很简单,pip install paramiko就搞定了,其依赖库会被一并安装。

        paramiko的官方站点在这里:http://www.paramiko.org/。有需要深入研究的可以阅读官方文档。

        paramiko模块提供了ssh及sft进行远程登录服务器执行命令和上传下载文件的功能。

3.1 基于用户名和密码的 sshclient 方式登录

  1. # 建立一个sshclient对象
  2. ssh = paramiko.SSHClient()
  3. # 允许将信任的主机自动加入到host_allow 列表,此方法必须放在connect方法的前面
  4. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  5. # 调用connect方法连接服务器
  6. ssh.connect(hostname='192.168.2.129', port=22, username='super', password='super')
  7. # 执行命令
  8. stdin, stdout, stderr = ssh.exec_command('df -hl')
  9. # 结果放到stdout中,如果有错误将放到stderr中
  10. print(stdout.read().decode())
  11. # 关闭连接
  12. ssh.close()

 

3.2 基于用户名和密码的 transport 方式登录

        方法1是传统的连接服务器、执行命令、关闭的一个操作,有时候需要登录上服务器执行多个操作,比如执行命令、上传/下载文件,方法1则无法实现,可以通过如下方式来操作

  1. # 实例化一个transport对象
  2. trans = paramiko.Transport(('192.168.2.129', 22))
  3. # 建立连接
  4. trans.connect(username='super', password='super')
  5. # 将sshclient的对象的transport指定为以上的trans
  6. ssh = paramiko.SSHClient()
  7. ssh._transport = trans
  8. # 执行命令,和传统方法一样
  9. stdin, stdout, stderr = ssh.exec_command('df -hl')
  10. print(stdout.read().decode())
  11. # 关闭连接
  12. trans.close()

 

3.3 基于公钥密钥的 SSHClient 方式登录

  1. # 指定本地的RSA私钥文件,如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数
  2. pkey = paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa', password='12345')
  3. # 建立连接
  4. ssh = paramiko.SSHClient()
  5. ssh.connect(hostname='192.168.2.129',
  6. port=22,
  7. username='super',
  8. pkey=pkey)
  9. # 执行命令
  10. stdin, stdout, stderr = ssh.exec_command('df -hl')
  11. # 结果放到stdout中,如果有错误将放到stderr中
  12. print(stdout.read().decode())
  13. # 关闭连接
  14. ssh.close()

 

        以上需要确保被访问的服务器对应用户.ssh目录下有authorized_keys文件,也就是将服务器上生成的公钥文件保存为authorized_keys。并将私钥文件作为paramiko的登陆密钥

3.4 基于密钥的 Transport 方式登录

  1. # 指定本地的RSA私钥文件,如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数
  2. pkey = paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa', password='12345')
  3. # 建立连接
  4. trans = paramiko.Transport(('192.168.2.129', 22))
  5. trans.connect(username='super', pkey=pkey)
  6. # 将sshclient的对象的transport指定为以上的trans
  7. ssh = paramiko.SSHClient()
  8. ssh._transport = trans
  9. # 执行命令,和传统方法一样
  10. stdin, stdout, stderr = ssh.exec_command('df -hl')
  11. print(stdout.read().decode())
  12. # 关闭连接
  13. trans.close()

 

3.5 传文件 SFTP

  1. # 实例化一个trans对象# 实例化一个transport对象
  2. trans = paramiko.Transport(('192.168.2.129', 22))
  3. # 建立连接
  4. trans.connect(username='super', password='super')
  5. # 实例化一个 sftp对象,指定连接的通道
  6. sftp = paramiko.SFTPClient.from_transport(trans)
  7. # 发送文件
  8. sftp.put(localpath='/tmp/11.txt', remotepath='/tmp/22.txt')
  9. # 下载文件
  10. # sftp.get(remotepath, localpath)
  11. trans.close()

 

3.6  实现输入命令立马返回结果的功能

        以上操作都是基本的连接,如果我们想实现一个类似xshell工具的功能,登录以后可以输入命令回车后就返回结果:

  1. import paramiko
  2. import os
  3. import select
  4. import sys
  5. # 建立一个socket
  6. trans = paramiko.Transport(('192.168.2.129', 22))
  7. # 启动一个客户端
  8. trans.start_client()
  9. # 如果使用rsa密钥登录的话
  10. '''
  11. default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')
  12. prikey = paramiko.RSAKey.from_private_key_file(default_key_file)
  13. trans.auth_publickey(username='super', key=prikey)
  14. '''
  15. # 如果使用用户名和密码登录
  16. trans.auth_password(username='super', password='super')
  17. # 打开一个通道
  18. channel = trans.open_session()
  19. # 获取终端
  20. channel.get_pty()
  21. # 激活终端,这样就可以登录到终端了,就和我们用类似于xshell登录系统一样
  22. channel.invoke_shell()
  23. # 下面就可以执行你所有的操作,用select实现
  24. # 对输入终端sys.stdin和 通道进行监控,
  25. # 当用户在终端输入命令后,将命令交给channel通道,这个时候sys.stdin就发生变化,select就可以感知
  26. # channel的发送命令、获取结果过程其实就是一个socket的发送和接受信息的过程
  27. while True:
  28. readlist, writelist, errlist = select.select([channel, sys.stdin,], [], [])
  29. # 如果是用户输入命令了,sys.stdin发生变化
  30. if sys.stdin in readlist:
  31. # 获取输入的内容
  32. input_cmd = sys.stdin.read(1)
  33. # 将命令发送给服务器
  34. channel.sendall(input_cmd)
  35. # 服务器返回了结果,channel通道接受到结果,发生变化 select感知到
  36. if channel in readlist:
  37. # 获取结果
  38. result = channel.recv(1024)
  39. # 断开连接后退出
  40. if len(result) == 0:
  41. print("\r\n**** EOF **** \r\n")
  42. break
  43. # 输出到屏幕
  44. sys.stdout.write(result.decode())
  45. sys.stdout.flush()
  46. # 关闭通道
  47. channel.close()
  48. # 关闭链接
  49. trans.close()

 

注意:在windows中,sys.stdin不是一个socket或者file-like对象,而是一个PseudoOutputFile对象,不能被select处理。所以上面的脚本不能在windows中运行,只能用于linux。

3.7 上例支持tab自动补全

  1. import paramiko
  2. import os
  3. import select
  4. import sys
  5. import tty
  6. import termios
  7. '''
  8. 实现一个xshell登录系统的效果,登录到系统就不断输入命令同时返回结果
  9. 支持自动补全,直接调用服务器终端
  10. '''
  11. # 建立一个socket
  12. trans = paramiko.Transport(('192.168.2.129', 22))
  13. # 启动一个客户端
  14. trans.start_client()
  15. # 如果使用rsa密钥登录的话
  16. '''
  17. default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')
  18. prikey = paramiko.RSAKey.from_private_key_file(default_key_file)
  19. trans.auth_publickey(username='super', key=prikey)
  20. '''
  21. # 如果使用用户名和密码登录
  22. trans.auth_password(username='super', password='super')
  23. # 打开一个通道
  24. channel = trans.open_session()
  25. # 获取终端
  26. channel.get_pty()
  27. # 激活终端,这样就可以登录到终端了,就和我们用类似于xshell登录系统一样
  28. channel.invoke_shell()
  29. # 获取原操作终端属性
  30. oldtty = termios.tcgetattr(sys.stdin)
  31. try:
  32. # 将现在的操作终端属性设置为服务器上的原生终端属性,可以支持tab了
  33. tty.setraw(sys.stdin)
  34. channel.settimeout(0)
  35. while True:
  36. readlist, writelist, errlist = select.select([channel, sys.stdin,], [], [])
  37. # 如果是用户输入命令了,sys.stdin发生变化
  38. if sys.stdin in readlist:
  39. # 获取输入的内容,输入一个字符发送1个字符
  40. input_cmd = sys.stdin.read(1)
  41. # 将命令发送给服务器
  42. channel.sendall(input_cmd)
  43. # 服务器返回了结果,channel通道接受到结果,发生变化 select感知到
  44. if channel in readlist:
  45. # 获取结果
  46. result = channel.recv(1024)
  47. # 断开连接后退出
  48. if len(result) == 0:
  49. print("\r\n**** EOF **** \r\n")
  50. break
  51. # 输出到屏幕
  52. sys.stdout.write(result.decode())
  53. sys.stdout.flush()
  54. finally:
  55. # 执行完后将现在的终端属性恢复为原操作终端属性
  56. termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
  57. # 关闭通道
  58. channel.close()
  59. # 关闭链接
  60. trans.close()

 

3.8  SSH服务端的实现

实现SSH服务端必须继承ServerInterface,并实现里面相应的方法。具体代码如下:

  1. import socket
  2. import sys
  3. import threading
  4. import paramiko
  5. host_key = paramiko.RSAKey(filename='private_key.key')
  6. class Server(paramiko.ServerInterface):
  7. def __init__(self):
  8. #执行start_server()方法首先会触发Event,如果返回成功,is_active返回True
  9. self.event = threading.Event()
  10. #当is_active返回True,进入到认证阶段
  11. def check_auth_password(self, username, password):
  12. if (username == 'root') and (password == '123456'):
  13. return paramiko.AUTH_SUCCESSFUL
  14. return paramiko.AUTH_FAILED
  15. #当认证成功,client会请求打开一个Channel
  16. def check_channel_request(self, kind, chanid):
  17. if kind == 'session':
  18. return paramiko.OPEN_SUCCEEDED
  19. #命令行接收ip与port
  20. server = sys.argv[1]
  21. ssh_port = int(sys.argv[2])
  22. #建立socket
  23. try:
  24. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP socket
  25. sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  26. sock.bind((server, ssh_port))
  27. sock.listen(100)
  28. print '[+] Listening for connection ...'
  29. client, addr = sock.accept()
  30. except Exception, e:
  31. print '[-] Listen failed: ' + str(e)
  32. sys.exit(1)
  33. print '[+] Got a connection!'
  34. try:
  35. #用sock.accept()返回的socket实例化Transport
  36. bhSession = paramiko.Transport(client)
  37. #添加一个RSA密钥加密会话
  38. bhSession.add_server_key(host_key)
  39. server = Server()
  40. try:
  41. #启动SSH服务端
  42. bhSession.start_server(server=server)
  43. except paramiko.SSHException, x:
  44. print '[-] SSH negotiation failed'
  45. chan = bhSession.accept(20)
  46. print '[+] Authenticated!'
  47. print chan.recv(1024)
  48. chan.send("Welcome to my ssh")
  49. while True:
  50. try:
  51. command = raw_input("Enter command:").strip("\n")
  52. if command != 'exit':
  53. chan.send(command)
  54. print chan.recv(1024) + '\n'
  55. else:
  56. chan.send('exit')
  57. print 'exiting'
  58. bhSession.close()
  59. raise Exception('exit')
  60. except KeyboardInterrupt:
  61. bhSession.close()
  62. except Exception, e:
  63. print '[-] Caught exception: ' + str(e)
  64. try:
  65. bhSession.close()
  66. except:
  67. pass
  68. sys.exit(1)

 

        到此这篇关于python使用paramiko实现ssh的功能详解的文章就介绍到这了,更多相关python paramiko实现ssh内容请搜索ZaLou.Cn以前的文章或继续浏览下面的相关文章希望大家以后多多支持ZaLou.Cn!

四、执行时某些错误和排除

4.1 python实现ssh的编程如下 

  1. import paramiko
  2. ssh = paramiko.SSHClient()
  3. key = paramiko.AutoAddPolicy()
  4. ssh.set_missing_host_key_policy(key)
  5. ssh.connect('192.168.3.164', 22, 'huatec', 'huatec123' ,timeout=5)
  6. while(True):
  7. cmdline = input("command: ")
  8. stdin, stdout, stderr = ssh.exec_command( cmdline )
  9. for row in stdout.readlines():
  10. row = row.replace('\r', '').replace('\n', '').replace('\t', '')
  11. print( row )

        远方服务器名称: 'huatec', 密码:'huatec123',IP地址:'192.168.3.164'

4.2 错误产生

        运行后,有时发生错误:

ModuleNotFoundError: No module named 'cryptography'

4.3 错误原因和恢复

        这是因为cryptography模块陈旧,恢复办法是:

  1. python -m pip uninstall cryptography
  2. python -m pip install cryptography

        再次实验,OK了!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/562004
推荐阅读
相关标签
  

闽ICP备14008679号