paramiko  模块

paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来现实。

它是基于Python实现的 SSH2远程安全连接,支持认证及密钥方式。可以实现远程命令执行、文件传输、中间SSH代理等功能。

官网地址: http://www.paramiko.org

paramiko 安装

paramiko 会依赖第三方的 Crypto 、Ecdsa 包及Python 开发包 python-devel 的支持。
所以先安装依赖包,再安装 paramiko
#  python3.x
yum install python-devel
pip3  install pycrypto
pip3 install ecdsa
pip3  install paramiko
验证安装
import paramiko

没有异常则证明安装成功

 

一般使用流程步骤示例,适用于首次建立 ssh 连接的情况

#/urs/bin/env   python3

import paramiko

# 第一步 定义主机信息,用户信息
hostname = '192.168.56.129'
username = 'root'
import paramiko

# 第一步 定义主机信息,用户信息
hostname = '192.168.56.129'
username = 'root'
password = 'upsa'

# 第二步 (可选)
#发送paramiko日志到 sysloging.log 文件
paramiko.util.log_to_file('sysloging.log')

#  第三步 创建一个 ssh 客户端 client 对象
ssh = paramiko.SSHClient()
#  设置本机和远程主机第一次建立ssh连接是的策略
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# 第四步 创建连接
ssh.connect(hostname=hostname,username=username,password=password)

# 第五步 执行命令( exec_command() )并获取结果
stdin,stdout,stderr = ssh.exec_command('free -m')
# 打印结果
#print(stdout.read())

print('=' * 30)
# 也可以使用 readlines()
print( stdout.readlines() )

# 第六步 关闭连接
ssh.close()

paramiko 核心组件

 

paramiko 包含了两个核心组件:

SSHClient 类  和  SFTPClient 类

SSHClient 类

 

SSHClient 类通常用于执行远程命令,有以下几个方法:

1. connect 方法

实现远程 SSH 连接并校验

使用方式:

connect(self,    # 类的实例化对象本身
            hostname,                    # str 类型,连接的目标主机地址,IP/FQDN;
            port=22,                      # int 类型,连接的目标主机端口号,默认 22;
            username=None,          # str 类型, 校验的用户名,默认是当前本地用户名;
            pasword=None,            # str 类型, 校验的用户名密码,用于校验或解锁私钥;
           pkey=None,                  # PKey 类型,本地私钥,用于使用私钥方式的身份验证;
           key_filename=None,       # str 或 list 类型,一个文件名或文件名的列表;
           timeout=None,              # float 类型,一个可选的超时时间(单位:秒)的TCP链接;
           allow_agent=True,         # bool 类型,设置为 False 时禁止连接到代理;
           look_for_keys=True,      # bool 类型,设置为 False 时禁止在 ~/.ssh 中搜索密钥文件;
           compress=False             # bool 类型,设置为 True 时打开压缩。
           )

 

2. exec_command 方法

用于远程执行命令,该命令的输入与输出流水为:标准输入(stdin),标准输出(stdout),标准错误输出(stderr)的Python对象

方法定义:

exec_command(self,
                      command,   # str 类型,执行的命令串;
                     bufsize=-1   # int 类型,文件缓冲区大小,默认为 -1 (不限制)。
                     )

3. load_system_host_keys

用于加载本地保存的公钥校验文件(这些公钥都是连接的目标主机的公钥,用于加密要发送给目标主机的信息),默认为 ~/.ssh/known_hosts,

非默认路径情况下,要手工指定,方法定义:

load_system_host_keys(self,
                                  filename=None  # str 类型,指定远程主机公钥的记录文件。
                                  )

4. set_missing_host_key_policy

用于在首次建立 SSH 连接的情况下,设置对于收到远程主机的公钥的处理方式;目前支持三种处理方式:AutoAddPolicy,RejectPolicy(默认),

WarningPolicy,仅限于 SSHClient 类,方法定义:

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(self,
                                               paramiko.RejectPolicy   # 自动拒绝未知的主机名和密钥,依赖 load_system_host_keys() 的配置;
                                               paramiko.AutoAddPolicy  # 自动添加一个未知的主机名和主机的公钥到本地 HostKeys 对象,并将其
                                                                                   保存,若默认的 ~/.ssh/known_hosts文件不存在则建立;
                                               paramiko.WarningPolicy   # 同 AutoAddPolicy ,只是会发出警告信息;
                                               )

常用示例

基于公钥密钥连接:

import paramiko,os
print(os.system('id'))

# 指定自己的私钥文件
private_key = paramiko.RSAKey.from_private_key_file('/root/.ssh/id_rsa')

# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())  # 即使known_hosts 文件中没有彼此的公钥也没关系
# 连接服务器
ssh.connect(hostname='192.168.56.129', port=22, username='root', pkey=private_key)

# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
print(result)
# 关闭连接
ssh.close()

 

SFTPClient 类

SFTPClient 用于和远程主机直接的文件上传、下载、创建目录、删除目录等功能,需要注意的是,put 和 get 方法需要指定文件名,不能省略。

有以下几个方法:

首先要创建一个通道对象

t = paramiko.Transport(('192.168.56.128',22))

再进行认证链接

t.connect(username='root',password='upsa')

这时候我们就创建了一个已通过认证的传说对象,接下来可以用这个对象使用以下方法了

1. from_transport 方法

用于创建一个已连通的 SFTP 客户端通道,方法定义:

from_transport(cls,
t,   # 一个开放的已认证的传输对象
window_size=None, #  为sftpclient会话可选的窗口的大小,一般不设置,设置了会影响速度
max_packet_size=None   # 为sftpclient会话可选的最大数据包大小。
)

返回的是一个新的stpfclient 对象,指的是用于传输的SFTP会话通道

用法:

t = paramiko.Transport(('192.168.56.128',22))
t.connect(username='root',password='upsa')
 
sftp = paramiko.SFTPClient.from_transport(t)

 

2. put 方法

用于上传本地文件到远程主机,方法定义:

put(self,
      localpath,            # str 类型,本地文件的路径,最好是绝对路径;
      remotepath,        # str 类型,在目标主机上的目标路径,应该包含文件名。仅指定目录可能报错;
      callback=None,    # 可选的回调函数,(用法:callback(func(int,int)))获取当前已经接收的字节和传输的总字节数
      confirm=True      # bool 类型,文件上传完毕后是否调用stat() 方法,以便确认文件的大小。
      )

用法示例:

localpath='/home/access.log'
remotepath='/backup/log/access.log.back'
sftp.put(localpath,remotepath)
3. get 方法
get(self, remotepath, localpath, callback=None)
参数基本和 put 的参数意思一样,只是刚好相反,这里不再赘述。
用法也一样
4. 其他方法介绍
mkdir      # 在远程主机上创建目录,如: sftp.mkdir('/home/testdir',0o0755) 后面的权限是 八进制的 int 类型
rmdir      # 在远程主机上删除一个空目录, 如: sftp.rmdir('/home/testdir',)
remove     # 在远程主机上移除指定路径下的文件,如: sftp.remove('/home/testdir/testfile')
rename     # 在远程主机上重命名文件或目录,如: sftp.rename('/home/testdir','/home/userdir')
stat       # 获取远程主机上指定文件信息,如: sftp.stat('/home/userdir/testfile.txt')
listdir    # 获取远程主机上指定目录下的文件列表,返回的是Python的列表形式
SFTPClient 类的简单应用
import paramiko
username = 'root'
password = 'upsa'
hostname = '192.168.56.129'
port = 22
try:
    t = paramiko.Transport((hostname,port))
    t.connect(username=username,password=password)
    sftp = paramiko.SFTPClient.from_transport(t)

    sftp.put('/root/anaconda-ks.cfg','/home/anaconda-ks.cfg')
    sftp.get('/home/anaconda-ks.cfg','/root/install.info')
    sftp.mkdir('/home/testdir/',0o755)
    # sftp.rmdir('/home/testdir')
    print(sftp.listdir('/home'))
except Exception as ex:
    print(ex)
封装SSHClient 和 SFTPClient
import paramiko

class SshHelper(object):

    def __init__(self,host,port,username,pwd):
        self.host = host
        self.port = port
        self.username = username
        self.pwd = pwd
        self.transport = None

    def connect(self):
        transport = paramiko.Transport((self.host, self.port,))
        transport.connect(username=self.username, password=self.pwd)
        self.transport = transport

    def upload(self,local,target):
        sftp = paramiko.SFTPClient.from_transport(self.transport)
        # 将location.py 上传至服务器 /tmp/test.py
        sftp.put(local, target)
        # 将remove_path 下载到本地 local_path
        # sftp.get('remove_path', 'local_path')

    def cmd(self,shell):
        ssh = paramiko.SSHClient()
        ssh._transport = self.transport
        stdin, stdout, stderr = ssh.exec_command(shell)
        stdout.read()

    def close(self):
        self.transport.close()

if __name__ == '__main__':

    obj = SshHelper('...')
    obj.connect()
    obj.close()