• Paramiko模块简单使用


    介绍

    Paramiko 一个第三方包,需要单独安装我们知道远程批量主机管理,比如ansible、Fabric,不需要安装客户端的远程执行命令等,这些都是基于Python原生的SSH,相当于模拟了一个SSH客户端。其实用的就是paramiko。其实想Fabric这种东西你自己也可以写,其实特别简单。paramiko 就是模拟了SSH的客户端,然后通过和SSH服务器交互就可以登录,执行命令等操作。

    代码实例

    简单的SSH登录实现

     1 #!/usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 # Author: rex.cheny
     4 # E-mail: rex.cheny@outlook.com
     5 
     6 
     7 import paramiko
     8 
     9 
    10 def main():
    11     # 实例化SSH客户端
    12     ssh = paramiko.SSHClient()
    13     # 允许连接不在 known_hosts 文件的IP
    14     ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    15     # 连接服务器
    16     ssh.connect(hostname="172.16.42.136", port=22, username="root", password="12qwaszx!")
    17 
    18     # 执行命令,它返回三个结果,stdin 是你输入的,stdout是它返回给你的,stderr是错误信息
    19     stdin, stdout, stderr = ssh.exec_command("ls /")
    20     result = stdout.read()
    21     print(result.decode(encoding="utf-8"))
    22     ssh.close()
    23 
    24 
    25 if __name__ == '__main__':
    26     main()

    简单的SFTP实现

     1 #!/usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 # Author: rex.cheny
     4 # E-mail: rex.cheny@outlook.com
     5 
     6 import paramiko
     7 
     8 
     9 def main():
    10     try:
    11         # 实例化SSH客户端
    12         ssh = paramiko.SSHClient()
    13         # 允许连接不在 known_hosts 文件的IP
    14         ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    15         # 连接服务器
    16         ssh.connect(hostname="172.16.42.136", port=22, username="root", password="12qwaszx!")
    17         transport = ssh.get_transport()
    18 
    19         """
    20         上面代码也可以这样写
    21         transport = paramiko.Transport((host, port))
    22         transport.connect(username=username, password=password)
    23         """
    24 
    25         sftp = paramiko.SFTPClient.from_transport(transport)
    26         sftp.put("./readme", "/tmp")
    27         transport.close()
    28     except Exception as err:
    29         print(err)
    30 
    31 
    32 if __name__ == '__main__':
    33     main()

    包含SFTP和SSH功能的代码实例

      1 #!/usr/bin/env python
      2 # -*- coding: utf-8 -*-
      3 
      4 import sys
      5 import os
      6 import paramiko
      7 import configparser
      8 
      9 
     10 class paramikoTools(object):
     11 
     12     def __init__(self, hostname, port, username, password, privateKeyFile=None, privateKeyFilePwd=None):
     13         """
     14 
     15         :param hostname: SSH服务器地址
     16         :param port: 端口
     17         :param username: 用户名
     18         :param password: 密码
     19         :param privateKeyFile: 私钥路径,如果没有则不用填写
     20         :param privateKeyFilePwd: 私钥解压密码如果私钥加密了请务必输入否则登陆将会失败
     21         :return:
     22         """
     23         self._hostname = hostname
     24         self._port = port
     25         self._username = username
     26         self._password = password
     27         self._privateKeyFile = privateKeyFile
     28         self._privateKeyFilePwd = privateKeyFilePwd
     29 
     30         # 实例化一个SSH客户端对象
     31         self._sshClient = paramiko.SSHClient()
     32         # 第一次SSH登录服务器需要输入一个Yes,这个就是帮你自动输入yes
     33         self._sshClient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
     34         #
     35         self._transport = None
     36         #
     37         self._sftpClient = None
     38 
     39         # 用于记录是否创建了SFTP客户端实例
     40         self._isSftpSessionOpened = False
     41         # 用于记录当前是否已经登录
     42         self._isLogined = False
     43 
     44     def login(self):
     45         if self._privateKeyFile:
     46             if os.path.exists(self._privateKeyFile):
     47                 self._isLogined = self._loginWithPrivateKey()
     48             else:
     49                 print("私钥路径不存在。")
     50         else:
     51             self._isLogined = self._loginWithPassword()
     52 
     53     # 用户名和密码登陆方法
     54     def _loginWithPassword(self):
     55         try:
     56             # 连接远程服务器
     57             self._sshClient.connect(hostname=self._hostname, port=self._port, username=self._username,
     58                                     password=self._password)
     59             print("密码登陆成功。")
     60         except Exception as err:
     61             # print err
     62             print("连接失败,请检查主机名、端口、用户名或者密码是否正确。")
     63             return False
     64         else:
     65             return True
     66 
     67     # 私钥登陆方法
     68     def _loginWithPrivateKey(self):
     69         try:
     70             if self._privateKeyFilePwd:
     71                 # 取出私钥,有时私钥加密了这里就需要设置私钥的密码,用于对私钥解密。
     72                 key = paramiko.RSAKey.from_private_key_file(self._privateKeyFile, password=self._privateKeyFilePwd)
     73             else:
     74                 key = paramiko.RSAKey.from_private_key_file(self._privateKeyFile)
     75 
     76             self._sshClient.connect(hostname=self._hostname, port=self._port, username=self._username,
     77                                     password=self._password, pkey=key)
     78             print("秘钥登陆成功。")
     79         except Exception as err:
     80             # print err
     81             print("连接失败,请检查主机名、端口、用户名、密码、私钥是否正确。")
     82             return False
     83         else:
     84             return True
     85 
     86     @property
     87     def isLogined(self):
     88         return self._isLogined
     89 
     90     # 创建SFTP客户端
     91     def _createSftpSession(self):
     92         """
     93         我这里建立SFTP连接的方式和网上略有不同,我这里是基于现有SSH连接来建立的SFTP会话。网上很多都是单纯的建立SFTP会话
     94         但是即便单纯建立SFTP会话其背后也要建立套接字和身份验证,可能网上的其他形式如下:
     95         t = paramiko.Transport((host, port))
     96         t.connect(username=username, password=password)
     97         sftp = paramiko.SFTPClient.from_transport(t)
     98         """
     99         if self._isLogined:
    100             try:
    101                 # 使用现有SSH连接获取一个 transport
    102                 self._transport = self._sshClient.get_transport()
    103                 # 把 transport 传递进去建立SFTP客户端连接
    104                 self._sftpClient = paramiko.SFTPClient.from_transport(self._transport)
    105             except Exception as err:
    106                 print(err)
    107             else:
    108                 self._isSftpSessionOpened = True
    109         else:
    110             print("ssh会话已经关闭或者没有建立,无法创建SFTP客户端连接。")
    111             self._isSftpSessionOpened = False
    112 
    113     # 路径检查
    114     def _pathChect(self, localPath, remotePath):
    115         # F 表示文件; D 表示目录
    116         CHECK_CODE = {"CODE": "0", "LOCALPATHTYPE": "F", "REMOTEPATHTYPE": "F"}
    117         if os.path.exists(localPath):
    118             return CHECK_CODE
    119         else:
    120             # 本地路径检查失败,不存在。
    121             CHECK_CODE = {"CODE": "101", "LOCALPATHTYPE": "", "REMOTEPATHTYPE": ""}
    122             return CHECK_CODE
    123 
    124     # 获取错误码对信息
    125     def _getCheckCodeDesc(self, temp_code):
    126         CHECK_CODE_DICT= {"0": "检查通过", "101": "本地路径检查失败可能不存在"}
    127         DESC = ""
    128         if CHECK_CODE_DICT.has_key(temp_code):
    129             pass
    130         else:
    131             DESC = "错误码不存在"
    132             return DESC
    133 
    134     # 关闭ssh连接
    135     def sshConnectLogOut(self):
    136         self._sshClient.close()
    137         self._transport.close()
    138         self._isLogined = False
    139         self._isSftpSessionOpened = False
    140 
    141     # 执行命令
    142     def execCommand(self, cmd):
    143         result = ''
    144         if self._isLogined:
    145             try:
    146                 # 远程执行命令,会返回元祖,里面包含输入、输出、错误
    147                 stdin, stdout, stderr = self._sshClient.exec_command(cmd)
    148             except Exception as err:
    149                 print(err)
    150             else:
    151                 # 输出的就是字符串内容
    152                 print(stdout.read())
    153                 # return result
    154         else:
    155             print("当前没有建立SSH的有效连接。")
    156 
    157     # 上传文件
    158     def upLoadFile(self, localPath, remotePath):
    159         count = 0
    160         # 如果SFTP客户端会话没有建立则自动建立,尝试三次
    161         for times in range(3):
    162             if not self._isSftpSessionOpened:
    163                 count = times + 1
    164                 print("第 %d 次尝试建立SFTP客户端会话,如果失败将再尝试 %d 次" % (count, 3 - count))
    165                 self._createSftpSession()
    166                 if count == 3 and not self._isSftpSessionOpened:
    167                     return None
    168                 else:
    169                     continue
    170             else:
    171                 print("SFTP客户端会话建立成功。")
    172                 break
    173 
    174         # 目前这里是直接上传,没有区分文件还是目录,所以默认只能支持文件,本地是文件路径、远程也是文件路径
    175         try:
    176             CODE = self._pathChect(localPath, remotePath)["CODE"]
    177             if CODE == "0":
    178                 # 路径检查都成功后如何处理
    179                 print("开始上传文件。")
    180                 self._sftpClient.put(localPath, remotePath)
    181                 print("上传文件完毕。")
    182             else:
    183                 print(self._getCheckCodeDesc(CODE))
    184         except Exception as err:
    185             print(err)
    186         else:
    187             pass
    188 
    189     # 下载文件
    190     def downLoad(self, remotePath, localPath):
    191         pass
    192 
    193 
    194 def main():
    195     # 建立ini文件读取实例
    196     config = configparser.ConfigParser()
    197     # 设置配置文件路径
    198     config_file_path = '/Users/rex.chen/PycharmProjects/Study/paramikoTest/config'
    199     # 读取文件
    200     config.read(config_file_path)
    201     # 获取内容,第一个参数是区,第二个参数是 键
    202     hostname = config.get("ssh", "hostname")
    203     port = config.getint("ssh", "port")
    204     username = config.get("ssh", "username")
    205     password = config.get("ssh", "password")
    206     private_key_path = config.get("ssh", "private_key_path")
    207 
    208     a = paramikoTools(hostname, port, username, password, private_key_path, password)
    209     a.login()
    210     # a.execCommand("df")
    211     # a.upLoadFile('/Users/rex.chen/Downloads/mapi-webapp.war', '/home/chenyun/update/mapi-webapp.war')
    212     print(a.isLogined)
    213 
    214 
    215 if __name__ == "__main__":
    216     main()

    同目录的配置文件如下:

    # paramiko连接使用的配置文件,不是必须的,只是这样可以避免过多的硬编码
    
    [ssh]
    hostname=
    port=
    username=
    password=
    private_key_path=
  • 相关阅读:
    Scala进阶之路-idea下进行spark编程
    Scala进阶之路-Spark本地模式搭建
    Scala进阶之路-Scala高级语法之隐式(implicit)详解
    Scala进阶之路-Spark底层通信小案例
    Scala进阶之路-并发编程模型Akka入门篇
    Scala进阶之路-统计商家id的标签数以及TopN示例案例分析
    Scala进阶之路-Scala中的泛型介绍
    Scala进阶之路-尾递归优化
    Scala进阶之路-Scala特征类与unapply反向抽取
    Java基础-爬虫实战之爬去校花网网站内容
  • 原文地址:https://www.cnblogs.com/rexcheny/p/9520819.html
Copyright © 2020-2023  润新知