美文网首页
python paramiko模块

python paramiko模块

作者: Elvis_zhou | 来源:发表于2019-10-11 16:44 被阅读0次

    1.介绍:

    ssh是一个协议,OpenSSH是其中一个开源实现,paramikoPython的一个库,实现了SSHv2协议(底层使用cryptography)。
    有了Paramiko以后,我们就可以在Python代码中直接使用SSH协议对远程服务器执行操作,而不是通过ssh命令对远程服务器进行操作。
    由于paramiko属于第三方库,所以需要使用如下命令先行安装:
    pip install paramiko

    2.paramiko介绍:

    paramiko包含两个核心组件:SSHClientSFTPClient
    SSHClient的作用类似于Linuxssh命令,是对SSH会话的封装,该类封装了传输(Transport),通道(Channel)及SFTPClient建立的方法(open_sftp),通常用于执行远程命令。
    SFTPClient的作用类似与Linuxsftp命令,是对SFTP客户端的封装,用以实现远程文件操作,如文件上传、下载、修改文件权限等操作。

    转自Python模块学习 - Paramiko

    3.实践:连接多个remote并实现上传下载和运行command

    # -*- coding: utf-8 -*-
    
    import paramiko
    from paramiko import SSHClient as sc
    
    import logging
    import os
    
    # 把接收的stdout转成generator,不然超过3k,程序会被hang住
    class ReceiveGenerator(object):
        def __init__(self, stdout):
            self.output = stdout
            self.out_channel = stdout.channel
    
        def __iter__(self):
            return self
    
        def next(self):
            """
            python2 compatibly
            """
            return self.out_channel.recv(1024)
    
        def __next__(self):
            """
            python3 compatibly
            """
            return self.out_channel.recv(1024)
    
        def exit_code_ready(self):
            return self.out_channel.exit_status_ready()
    
        def exit_code(self):
            return self.out_channel.recv_exit_status()
    
    
    class SSHClient(object):
        def __init__(self, transport, sftp, ssh):
    
            self.transport = transport
            self.sftp = sftp
            self.ssh = ssh
            self.hostname = None
    
        @staticmethod
        def connect(hostname, port, username, key_path):
            try:
                # 私钥的文件路径
                key = paramiko.RSAKey.from_private_key_file(key_path)
                # 创建transport通道
                transport = paramiko.Transport(hostname, port)
                transport.connect(username=username, pkey=key)
    
                # 创建sftp通道
                sftp = paramiko.SFTPClient.from_transport(transport)
                ssh = sc()
                ssh._transport = transport
    
                # logger.info('connection is succeed, hostname: %s', hostname)
    
                return SSHClient(transport, sftp, ssh)
            except:
                raise Exception('connection is failed')
    
        # 执行linux上的命令
        def ssh_command(self, command):
    
            stdin, stdout, stderr = self.ssh.exec_command(command)
    
            return stdin, stdout, stderr
    
         # 上传
        def sftp_upload(self, local_path, remote_path):
    
            self.sftp.put(localpath=local_path, remotepath=remote_path)
    
         # 下载
        def sftp_download(self, local_path, remote_path):
    
            self.sftp.get(localpath=local_path, remotepath=remote_path)
    
        def close(self):
            self.transport.close()
    
        def structure_output(self, command):
            stdin, stdout, stderr = self.ssh_command(command)
    
            # structure a generator class
            return ReceiveGenerator(stdout), stderr
    
        # 如果params是string的话直接上传至指定文件, 如果是路径直接上传并执行commamd
        def script(self, params, remote_path, command=None):
            if os.path.isfile(params):
                self.sftp_upload(params, remote_path)
    
                stdout_iterator, stderr = self.structure_output(command)
                out = ['']
                for i in stdout_iterator:
                    # 返回长度为0通道关闭
                    if not len(i):
                        break
                    out[0] += i
    
                return {
                    'stdout': out[0],
                    'stderr': stderr.read().decode('utf-8'),
                    'exitcode': stdout_iterator.exit_code()
                }
    
            ftp_file = self.sftp.file(remote_path, 'w', -1)
            ftp_file.write(params)
            ftp_file.flush()
    
            stdout_iterator, stderr = self.structure_output(command)
    
            return {
                'stdout': stdout_iterator,
                'stderr': stderr.read().decode('utf-8'),
                'exitcode': stdout_iterator.exit_code()
            }
    
    
    if __name__ == '__main__':
    
        logger = logging.getLogger(__name__)
        logger.setLevel(level=logging.INFO)
        handler = logging.StreamHandler()
        logger.addHandler(handler)
    
    
        def main(hostname_list, port, username, pkey_path, input_params, remote_path, command):
            """
            :param hostname_list: list, of hostname
            :param port: int, port
            :param username: string
            :param pkey_path: string, path
            :param input_params: string, it can be path in local or string
            :param remote_path: string, path of remote
            :param command: string
            :return: a generator class
            """
    
            for hostname in hostname_list:
                ssh_client = SSHClient.connect(hostname, port, username, pkey_path)
    
                generator_outputs = ssh_client.script(params=input_params, remote_path=remote_path, command=command)
                yield generator_outputs
    
                ssh_client.close()
    
    
        test_hostname_list = ['52.82.7.121']
        test_port = 22
        test_username = 'ubuntu'
        test_pkey = '/home/python/Desktop/fastone-demo.pem'
    
        test_input_params = '/home/python/Desktop/cb-aws-vmtypes.json'
        test_remote_path = 'test.txt'
        test_command = 'cat test.txt'
        test_outputs_list = main(test_hostname_list,
                                 test_port,
                                 test_username,
                                 test_pkey,
                                 test_input_params,
                                 test_remote_path,
                                 test_command
                                 )
        for outputs in test_outputs_list:
            for output in outputs:
                print('output : ', output)
    
    

    这里不熟悉的朋友可以先把每个函数拆开实现,再抽象成类。
    以上!

    附带链接:
    官方文档
    python模块之 paramiko
    Python模块学习 - Paramiko

    相关文章

      网友评论

          本文标题:python paramiko模块

          本文链接:https://www.haomeiwen.com/subject/mmtxmctx.html