• Python3之paramiko模块


    一. 简介

      paramiko是一个基于SSH用于连接远程服务器并执行相关操作(SSHClient和SFTPClinet,即一个是远程连接,一个是上传下载服务),使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来现实。

    二. 使用

    1. 下载安装

    pycrypto,由于 paramiko 模块内部依赖pycrypto,所以先下载安装pycrypto
    pip3 install pycrypto
    pip3 install paramiko

    2. 模块使用

    SSHClient:

    远程连接分为两种:(1)基于用户名密码连接 (2)基于公钥秘钥连接

    通过是用paramiko远程操作,其实本质也分为两种:(1)只用SSHClient (2)自己创建一个transport

    (1)基于用户名和密码的连接

    复制代码
     1 import paramiko
     2  
     3 # 创建SSH对象
     4 ssh = paramiko.SSHClient()
     5 # 允许连接不在know_hosts文件中的主机
     6 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
     7 # 连接服务器
     8 ssh.connect(hostname='c1.salt.com', port=22, username='GSuser', password='123')
     9 # 执行命令
    10 stdin, stdout, stderr = ssh.exec_command('ls')
    11 # 获取命令结果
    12 result = stdout.read()
    13 # 关闭连接
    14 ssh.close()
    复制代码

      SSHClient 封装 Transport

    复制代码
     1 import paramiko
     2  
     3 transport = paramiko.Transport(('hostname', 22))
     4 transport.connect(username='GSuser', password='123')
     5  
     6 ssh = paramiko.SSHClient()
     7 ssh._transport = transport
     8  
     9 stdin, stdout, stderr = ssh.exec_command('df')
    10 print(stdout.read())
    11  
    12 transport.close()
    复制代码

      (2)基于公钥秘钥连接

    复制代码
     1 import paramiko
     2  
     3 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
     4 # 创建SSH对象
     5 ssh = paramiko.SSHClient()
     6 # 允许连接不在know_hosts文件中的主机
     7 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
     8 # 连接服务器
     9 ssh.connect(hostname='c1.salt.com', port=22, username='wupeiqi', key=private_key)
    10 # 执行命令
    11 stdin, stdout, stderr = ssh.exec_command('df')
    12 # 获取命令结果
    13 result = stdout.read()
    14 # 关闭连接
    15 ssh.close()
    复制代码

      SSHClient 封装Transport

    复制代码
    1 import paramiko
    2  
    3 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
    4 transport = paramiko.Transport(('hostname', 22))
    5 transport.connect(username='wupeiqi', pkey=private_key)
    6 ssh = paramiko.SSHClient()
    7 ssh._transport = transport
    8 stdin, stdout, stderr = ssh.exec_command('df')
    9 transport.close()
    复制代码

    SFTPClient:

      用于连接远程服务器并进行上传下载功能。

    (1)基于用户名密码上传下载

    复制代码
     1 import paramiko
     2  
     3 transport = paramiko.Transport(('hostname',22))
     4 transport.connect(username='GSuser',password='123')
     5  
     6 sftp = paramiko.SFTPClient.from_transport(transport)
     7 # 将location.py 上传至服务器 /tmp/test.py
     8 sftp.put('/tmp/location.py', '/tmp/test.py')
     9 # 将remove_path 下载到本地 local_path
    10 sftp.get('remove_path', 'local_path')
    11  
    12 transport.close()
    复制代码

    (2)基于公钥秘钥上传下载

    复制代码
     1 import paramiko
     2  
     3 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
     4  
     5 transport = paramiko.Transport(('hostname', 22))
     6 transport.connect(username='GSuser', pkey=private_key )
     7  
     8 sftp = paramiko.SFTPClient.from_transport(transport)
     9 # 将location.py 上传至服务器 /tmp/test.py
    10 sftp.put('/tmp/location.py', '/tmp/test.py')
    11 # 将remove_path 下载到本地 local_path
    12 sftp.get('remove_path', 'local_path')
    13  
    14 transport.close()
    复制代码

      Demo: 实现远程命令执行和文件上传

    复制代码
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 import paramiko
     4  
     5 class SSHConnection(object):
     6  
     7     def __init__(self, host='192.168.12.68', port=22, username='locojoy',pwd='123321QQ!'):
     8         self.host = host
     9         self.port = port
    10         self.username = username
    11         self.pwd = pwd
    12         self.__k = None
    13  
    14     def run(self):
    15         self.connect()  # 连接远程服务器
    16         self.upload('db.py','/tmp/1.py')  # 将本地的db.py文件上传到远端服务器的/tmp/目录下并改名为1.py
    17         self.cmd('df')  # 执行df 命令
    18         self.close()    # 关闭连接
    19  
    20     def connect(self):
    21         transport = paramiko.Transport((self.host, self.port))
    22         transport.connect(username=self.username, password=self.pwd)
    23         self.__transport = transport
    24  
    25     def close(self):
    26         self.__transport.close()
    27  
    28     def upload(self,local_path,target_path):
    29         sftp = paramiko.SFTPClient.from_transport(self.__transport)
    30         sftp.put(local_path,target_path)
    31  
    32     def cmd(self, command):
    33         ssh = paramiko.SSHClient()
    34         ssh._transport = self.__transport
    35         # 执行命令
    36         stdin, stdout, stderr = ssh.exec_command(command)
    37         # 获取命令结果
    38         result = stdout.read()
    39         print(result)
    40         return result
    41  
    42 obj = SSHConnection()
    43 obj.run()
    复制代码

      paramiko在堡垒机中的应用

    (1)简单实例:远程连接一台主机,操作命令,linux版本,输入终端为回车则发送命令。不支持tab补全功能。

    复制代码
     1 import paramiko, sys, os, socket, select, getpass
     2 from paramiko.py3compat import u   # 在python3中是这样使用的,如果在Python2中则注释这行
     3  
     4 # 这个程序依赖于终端,只能在Liunx下运行,windows用其他的方式
     5  
     6 tran = paramiko.Transport(('192.168.12.68', 22,))
     7 tran.start_client()
     8 tran.auth_password('locojoy', '123321QQ!')
     9  
    10 # 打开一个通道
    11 chan = tran.open_session()
    12 # 获取一个终端
    13 chan.get_pty()
    14 # 激活器
    15 chan.invoke_shell()
    16  
    17 # 原始的方法利用终端进行收发消息
    18 # 利用sys.stdin,肆意妄为执行操作
    19 # 用户在终端输入内容,并将内容发送至远程服务器
    20 # 远程服务器执行命令,并将结果返回
    21 # 用户终端显示内容
    22  
    23 while True:
    24     # 监视用户输入和服务器返回数据
    25     # sys.stdin 处理用户输入
    26     # chan 是之前创建的通道,用于接收服务器返回信息
    27     # 通过select监听终端(输入输出),一旦变化,就将拿到的数据发送给服务器
    28     # 通过监听socket句柄,如果有变化表示服务器要给我发消息
    29     readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1)
    30     # 通过select.select 监听chan(打开的通道(和远程服务器连接的状态)), sys.stdin(输入),一旦变化就写入readable
    31     # 当chan变化时,加入到readable,远程服务器发送内容过来
    32     if chan in readable:
    33         try:
    34             x = u(chan.recv(1024))  # Python3用这个
    35             # x = chan.recv(1024)  Python2使用这个
    36             if len(x) == 0:
    37                 print('
    *** EOF
    ')
    38                 break
    39             sys.stdout.write(x)   # 写入缓冲区
    40             sys.stdout.flush()    # 刷新,将缓冲区内容显示出来
    41         except socket.timeout:
    42             pass
    43     # 当sys.stdin 放入readable中时,将获取到的内容发送到远程服务器
    44     if sys.stdin in readable:
    45         inp = sys.stdin.readline()
    46         chan.sendall(inp)
    47  
    48 chan.close()
    49 tran.close()
    复制代码

    (2)每按一个键就发送记录,并支持tab自动补全

    复制代码
     1 import paramiko, sys, os, socket, select, getpass, termios, tty
     2 from paramiko.py3compat import u
     3  
     4 tran = paramiko.Transport(('10.211.55.4', 22,))
     5 tran.start_client()
     6 tran.auth_password('wupeiqi', '123')
     7 # 打开一个通道
     8 chan = tran.open_session()
     9 # 获取一个终端
    10 chan.get_pty()
    11 # 激活器
    12 chan.invoke_shell()
    13  
    14 # 获取原tty属性
    15 oldtty = termios.tcgetattr(sys.stdin)
    16 try:
    17     # 为tty设置新属性
    18     # 默认当前tty设备属性:
    19     #   输入一行回车,执行
    20     #   CTRL+C 进程退出,遇到特殊字符,特殊处理。
    21     # 这是为原始模式,不认识所有特殊符号
    22     # 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器
    23     tty.setraw(sys.stdin.fileno())  # 恢复终端原始状态,每按一个键就发送
    24     chan.settimeout(0.0)
    25  
    26     while True:
    27         # 监视 用户输入 和 远程服务器返回数据(socket)
    28         # 阻塞,直到句柄可读
    29         r, w, e = select.select([chan, sys.stdin], [], [], 1)
    30         if chan in r:  # 获取服务返回的内容
    31             try:
    32                 x = u(chan.recv(1024))
    33                 if len(x) == 0:
    34                     print('
    *** EOF
    ')
    35                     break
    36                 sys.stdout.write(x)
    37                 sys.stdout.flush()
    38             except socket.timeout:
    39                 pass
    40         if sys.stdin in r: # 发送命令
    41             x = sys.stdin.read(1) # 读取一个字符
    42             if len(x) == 0:
    43                 break
    44             chan.send(x) # 发送一个字符
    45  
    46 finally:
    47     # 重新设置终端属性,将终端状态还原
    48     termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
    49  
    50 chan.close()
    51 tran.close()
    复制代码
     
    分类: python
  • 相关阅读:
    Python range 函数 Python零基础入门教程
    Python eval 与 exec 函数的区别 Python零基础入门教程
    Python callable 函数 Python零基础入门教程
    Python bytes 函数 Python零基础入门教程
    Python ord 函数 Python零基础入门教程
    Python len函数 Python零基础入门教程
    第十二课 通过URL api拿到接送数据并做页面展示
    第十三课 axios请求数据
    网络编程学习路线计划
    erlang学习笔记本【不断更新】
  • 原文地址:https://www.cnblogs.com/lgj8/p/12981803.html
Copyright © 2020-2023  润新知