python中paramiko模块祥解

一 paramiko模块
paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,基于linux中的ssh服务
paramiko属于第三方模块,需要安装导入

pip install paramiko

1) 远程密码连接

import paramiko
#创建一个ssh对象
client=paramiko.SSHClient()
#如果之前没有连接过的ip,会出现 Are you sure you want to continue connecting (yes/no)? yes
#自动选择yes
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#连接服务器
client.connect(hostname='172.25.254.169',
               port=22,
               username='root',
               password='redhat')
#执行操作
stdin,stdout,stderr=client.exec_command('hostname')  #exec_command返回的为一个元组
#获取命令的执行结果
# result=stdout.read() 为2进制的对象,因此
result=stdout.read().decode('utf-8')  #decode('utf-8') 对2进制的对象进行转换
print(result)
#关闭连接
client.close()

这里写图片描述
2) 批量远程密码连接

def conn(cmd,host,port=22,user='root',passwd='westos'):
    #基于ssh命令用于连接远程服务器作操作:远程执行命令 上传 下载
    import paramiko
    #创建一个ssh对象
    client=paramiko.SSHClient()
    #如果之前没有连接过的ip,会出现 Are you sure you want to continue connecting (yes/no)? yes
    #自动选择yes
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        #连接服务器
        client.connect(hostname=host,
                       port=port,
                       username=user,
                       password=passwd)
    except :
        print('连接%s\tip失败'%(host))
    else:
        print('连接%s\tip成功'%(host))
        #执行操作
        stdin,stdout,stderr=client.exec_command(cmd)  #exec_command返回的为一个元组
        #获取命令的执行结果
        # result=stdout.read() 为2进制的对象,因此
        result=stdout.read().decode('utf-8')  #decode('utf-8') 对2进制的对象进行转换
        print(result)
    finally:
        #关闭连接
        client.close()
if __name__=='__main__':
    with open('ip.txt')as f:
        for line in f:
            line=line.strip()
            host,port,user,passwd=line.split(':')
            print(host.center(50,'*'))
            conn('hostname',host,port,user,passwd)

这里写图片描述
3) 基于公钥密钥的连接

from paramiko.ssh_exception import NoValidConnectionsError


def conn(cmd,host,port=22,user='root'):
    #基于ssh命令用于连接远程服务器作操作:远程执行命令 上传 下载
    import paramiko
    #创建一个ssh对象
    client=paramiko.SSHClient()
    #如果之前没有连接过的ip,会出现 Are you sure you want to continue connecting (yes/no)? yes
    #自动选择yes
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    #创建一个私钥
    private_key=paramiko.RSAKey.from_private_key_file('id_rsa.txt')
    try:
        #连接服务器
        client.connect(hostname=host,
                       port=port,
                       username=user,
                       pkey=private_key)
    except NoValidConnectionsError as e:
        print('连接%s失败'%(host))
    else:
        #执行操作
        stdin,stdout,stderr=client.exec_command(cmd)  #exec_command返回的为一个元组
        #获取命令的执行结果
        # result=stdout.read() 为2进制的对象,因此
        result=stdout.read().decode('utf-8')  #decode('utf-8') 对2进制的对象进行转换
        print(result)
    finally:
        #关闭连接
        client.close()

host='172.25.254.169'
print(host.center(50,'*'))
conn('uname',host)

这里写图片描述
4) 基于密码的上传,下载
注意:上传,下载这里还有个默认的ftplib模块定义了FTP类

import paramiko
transport=paramiko.Transport('172.25.254.169',22)
transport.connect(username='root',password='redhat')
sftp=paramiko.SFTPClient.from_transport(transport)
#上传,下载文件  包含文件名
sftp.put('/mnt/passwd','/mnt/put_passwd')
sftp.get('/mnt/put_passwd','/home/kiosk/Desktop/get_passwd')
transport.close()

上传:
这里写图片描述
下载:
这里写图片描述
5) 基于密钥的上传下载

import  paramiko

# 返回一个私钥对象
private_key = paramiko.RSAKey.from_private_key_file('id_rsa')

transport = paramiko.Transport(('172.25.254.169', 22))
transport.connect(username='root',pkey=private_key)
sftp = paramiko.SFTPClient.from_transport(transport)
# 上传文件, 包含文件名
sftp.put('/mnt/passwd','/mnt/put_passwd')
sftp.get('/mnt/put_passwd','/home/kiosk/Desktop/get_passwd')
transport.close()

二 paramiko再次封装
先选择不同的机组,再对机组里面的主机进行操作
这里写图片描述
不同的机组文件里面,存储着不同的主机信息

import paramiko
from paramiko import SSHException


class SshRemoteHost(object):
    def __init__(self, hostname, port, user, passwd, cmd):
        self.hostname = hostname
        self.port = port
        self.user = user
        self.passwd = passwd
        self.cmd = cmd

    def run(self):
        """默认调用的内容"""
        # cmd hostname
        cmd_str = self.cmd.split()[0]  # cmd
        if hasattr(self, 'do_' + cmd_str):  # do_cmd
            getattr(self, 'do_' + cmd_str)()
        else:
            print('不支持此命令...')

    def do_cmd(self):
        """执行指定的命令"""
        # 创建一个ssh对象
        client = paramiko.SSHClient()
        # 如果之前没有连接过的ip,会出现 Are you sure you want to continue connecting (yes/no)? yes
        # 自动选择yes
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            # 连接服务器
            client.connect(hostname=self.hostname,
                           port=self.port,
                           username=self.user,
                           password=self.passwd)
        except:
            print('连接%s\tip失败' % (self.hostname))
        else:
            print('连接%s\tip成功' % (self.hostname))
            # 执行操作
            cmd = ''.join(self.cmd.split()[1:])
            stdin, stdout, stderr = client.exec_command(cmd)  # exec_command返回的为一个元组
            # 获取命令的执行结果
            # result=stdout.read() 为2进制的对象,因此
            result = stdout.read().decode('utf-8')  # decode('utf-8') 对2进制的对象进行转换
            print(result)
        finally:
            # 关闭连接
            client.close()

    def do_put(self):
        print('正在上传...')
        try:
            transport = paramiko.Transport(self.hostname, int(self.port))
            transport.connect(username=self.user, password=self.passwd)
        except SSHException as e:
            print('%s主机连接失败...'%(self.hostname))
        else:
            sftp = paramiko.SFTPClient.from_transport(transport)
            newCmd = self.cmd.split()[1:]
            if len(newCmd) == 2:
                sftp.put(newCmd[0], newCmd[1])
                print('%s文件上传到%s主机的%s文件成功!' % (newCmd[0], self.hostname, newCmd[1]))
            else:
                print('上传文件信息错误')
            transport.close()

    def do_get(self):
        print('正在下载...')
        try:
            transport = paramiko.Transport(self.hostname, int(self.port))
            transport.connect(username=self.user, password=self.passwd)
        except SSHException as e:
            print('连接失败...')
        else:
            sftp = paramiko.SFTPClient.from_transport(transport)
            newCmd = self.cmd.split()[1:]
            if len(newCmd) == 2:
                sftp.put(newCmd[0], newCmd[1])
                print('从%s主机下载的%s文件到本主机的%s文件成功!' % (self.hostname, newCmd[0], newCmd[1]))
            else:
                print('下载文件信息错误')
            transport.close()
            # 1)选择操作的主机组:web,mysql,ftp
            # 主机信息的存储:将不同的主机信息存放到不同的文件中
            # 2)根据选择的主机组,显示包含的主机IP/主机名
            # 3)让用户确认信息,选择需要批量执行的命令:
            # cmd shell命令
            # put 命令
            # get 命令


import os
def main():
    # 1)选择操作的主机组:web,mysql,ftp
    groups = [file.rstrip('.conf') for file in os.listdir('conf')]
    print('主机组显示:'.center(50, '*'))
    for group in groups: print('\t', group)
    choiceGroup = input('请选择批量操作的主机组: ')
    # 2)根据选择的主机组,显示包含的主机IP/主机名
    # 打开文件/home/kiosk/PycharmProjects/python/conf
    # 依次读取文件每一行
    # 拿出IP
    print('主机组包含的主机: '.center(50, '*'))
    with open('conf/%s.conf' % (choiceGroup))as f:
        for line in f:
            print(line.split(':')[0])
        f.seek(0, 0)
        hostinfos = [line.strip() for line in f.readlines()]
    # 3)让用户确认信息,选择需要批量执行的命令
    print('批量执行命令中...'.center(50, '*'))
    while True:
        cmd = input('>>:').strip()  # cmd uname
        if cmd:
            if cmd == 'exit' or cmd == 'quit':
                print('执行结束,退出中...')
                break
            # 依次让该主机组的所有主机执行
            for info in hostinfos:
                host, port, user, passwd = info.split(':')
                clientObj = SshRemoteHost(host, port, user, passwd, cmd)
                clientObj.run()
if __name__ == '__main__':
    main()

这里写图片描述
封装后的代码支持远程批量的命令操作,以及上传与下载

猜你喜欢

转载自blog.csdn.net/weixin_42668123/article/details/82686386