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=

 

posted @ 2018-08-22 22:23  昀溪  阅读(696)  评论(0编辑  收藏  举报