码迷,mamicode.com
首页 > 其他好文 > 详细

Paramiko实现远程访问配置

时间:2019-06-04 16:12:52      阅读:94      评论:0      收藏:0      [点我收藏+]

标签:pre   sock   command   std   exce   Matter   mes   cee   ssh   

#!/usr/bin/env python
import paramiko
import logging
import socket
import time
import datetime


#=====================#
# class MySSH         #
#=====================#
class MySSH:
    ‘‘‘
    Create an SSH connection to a server and execute commands.
    Here is a typical usage:

        ssh = MySSH()
        ssh.connect(‘host‘, ‘user‘, ‘password‘, port=22)
        if ssh.connected() is False:
            sys.exit(‘Connection failed‘)

        # Run a command that does not require input.
        status, output = ssh.run(‘uname -a‘)
        print ‘status = %d‘ % (status)
        print ‘output (%d):‘ % (len(output))
        print ‘%s‘ % (output)

        # Run a command that does requires input.
        status, output = ssh.run(‘sudo uname -a‘, ‘sudo-password‘)
        print ‘status = %d‘ % (status)
        print ‘output (%d):‘ % (len(output))
        print ‘%s‘ % (output)
    ‘‘‘
    def __init__(self, compress=True, verbose=False):
        ‘‘‘
        Setup the initial verbosity level and the logger.

        @param compress  Enable/disable compression.
        @param verbose   Enable/disable verbose messages.
        ‘‘‘
        self.ssh = None
        self.transport = None
        self.compress = compress
        self.bufsize = 65536

        # Setup the logger
        self.logger = logging.getLogger(MySSH)
        self.set_verbosity(verbose)

        fmt = %(asctime)s MySSH:%(funcName)s:%(lineno)d %(message)s
        format = logging.Formatter(fmt)
        handler = logging.StreamHandler()
        handler.setFormatter(format)
        self.logger.addHandler(handler)
        self.info = self.logger.info

    def __del__(self):
        if self.transport is not None:
            self.transport.close()
            self.transport = None

    def connect(self, hostname, username, password, port=22):
        ‘‘‘
        Connect to the host.

        @param hostname  The hostname.
        @param username  The username.
        @param password  The password.
        @param port      The port (default=22).

        @returns True if the connection succeeded or false otherwise.
        ‘‘‘
        self.info(connecting %s@%s:%d % (username, hostname, port))
        self.hostname = hostname
        self.username = username
        self.port = port
        self.ssh = paramiko.SSHClient()
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            self.ssh.connect(hostname=hostname,
                             port=port,
                             username=username,
                             password=password)
            self.transport = self.ssh.get_transport()
            self.transport.use_compression(self.compress)
            self.info(succeeded: %s@%s:%d % (username,
                                               hostname,
                                               port))
        except socket.error as e:
            self.transport = None
            self.info(failed: %s@%s:%d: %s % (username,
                                                hostname,
                                                port,
                                                str(e)))
        except paramiko.BadAuthenticationType as e:
            self.transport = None
            self.info(failed: %s@%s:%d: %s % (username,
                                                hostname,
                                                port,
                                                str(e)))

        return self.transport is not None

    def run(self, cmd, input_data=None, timeout=10):
        ‘‘‘
        Run a command with optional input data.

        Here is an example that shows how to run commands with no input:

            ssh = MySSH()
            ssh.connect(‘host‘, ‘user‘, ‘password‘)
            status, output = ssh.run(‘uname -a‘)
            status, output = ssh.run(‘uptime‘)

        Here is an example that shows how to run commands that require input:

            ssh = MySSH()
            ssh.connect(‘host‘, ‘user‘, ‘password‘)
            status, output = ssh.run(‘sudo uname -a‘, ‘<sudo-password>‘)

        @param cmd         The command to run.
        @param input_data  The input data (default is None).
        @param timeout     The timeout in seconds (default is 10 seconds).
        @returns The status and the output (stdout and stderr combined).
        ‘‘‘
        self.info(running command: (%d) %s % (timeout, cmd))

        if self.transport is None:
            self.info(no connection to %s@%s:%s % (str(self.username),
                                                     str(self.hostname),
                                                     str(self.port)))
            return -1, ERROR: connection not established\n

        # Fix the input data.
        input_data = self._run_fix_input_data(input_data)

        # Initialize the session.
        self.info(initializing the session)
        session = self.transport.open_session()
        session.set_combine_stderr(True)
        session.get_pty()
        session.exec_command(cmd)
        output = self._run_poll(session, timeout, input_data)
        status = session.recv_exit_status()
        self.info(output size %d % (len(output)))
        self.info(status %d % (status))
        return status, output

    def connected(self):
        ‘‘‘
        Am I connected to a host?

        @returns True if connected or false otherwise.
        ‘‘‘
        return self.transport is not None

    def set_verbosity(self, verbose):
        ‘‘‘
        Turn verbose messages on or off.

        @param verbose  Enable/disable verbose messages.
        ‘‘‘
        if verbose > 0:
            self.logger.setLevel(logging.INFO)
        else:
            self.logger.setLevel(logging.ERROR)

    def _run_fix_input_data(self, input_data):
        ‘‘‘
        Fix the input data supplied by the user for a command.

        @param input_data  The input data (default is None).
        @returns the fixed input data.
        ‘‘‘
        if input_data is not None:
            if len(input_data) > 0:
                if \\n in input_data:
                    # Convert \n in the input into new lines.
                    lines = input_data.split(\\n)
                    input_data = \n.join(lines)
            return input_data.split(\n)
        return []

    def _run_send_input(self, session, stdin, input_data):
        ‘‘‘
        Send the input data.

        @param session     The session.
        @param stdin       The stdin stream for the session.
        @param input_data  The input data (default is None).
        ‘‘‘
        if input_data is not None:
            self.info(session.exit_status_ready() %s % str(session.exit_status_ready()))
            self.info(stdin.channel.closed %s % str(stdin.channel.closed))
            if stdin.channel.closed is False:
                self.info(sending input data)
                stdin.write(input_data)

    def _run_poll(self, session, timeout, input_data):
        ‘‘‘
        Poll until the command completes.

        @param session     The session.
        @param timeout     The timeout in seconds.
        @param input_data  The input data.
        @returns the output
        ‘‘‘
        interval = 0.1
        maxseconds = timeout
        maxcount = maxseconds / interval

        # Poll until completion or timeout
        # Note that we cannot directly use the stdout file descriptor
        # because it stalls at 64K bytes (65536).
        input_idx = 0
        timeout_flag = False
        self.info(polling (%d, %d) % (maxseconds, maxcount))
        start = datetime.datetime.now()
        start_secs = time.mktime(start.timetuple())
        output = ‘‘
        session.setblocking(0)
        while True:
            if session.recv_ready():
                data = session.recv(self.bufsize)
                output += data
                self.info(read %d bytes, total %d % (len(data), len(output)))

                if session.send_ready():
                    # We received a potential prompt.
                    # In the future this could be made to work more like
                    # pexpect with pattern matching.
                    if input_idx < len(input_data):
                        data = input_data[input_idx] + \n
                        input_idx += 1
                        self.info(sending input data %d % (len(data)))
                        session.send(data)

            self.info(session.exit_status_ready() = %s % (str(session.exit_status_ready())))
            if session.exit_status_ready():
                break

            # Timeout check
            now = datetime.datetime.now()
            now_secs = time.mktime(now.timetuple()) 
            et_secs = now_secs - start_secs
            self.info(timeout check %d %d % (et_secs, maxseconds))
            if et_secs > maxseconds:
                self.info(polling finished - timeout)
                timeout_flag = True
                break
            time.sleep(0.200)

        self.info(polling loop ended)
        if session.recv_ready():
            data = session.recv(self.bufsize)
            output += data
            self.info(read %d bytes, total %d % (len(data), len(output)))

        self.info(polling finished - %d output bytes % (len(output)))
        if timeout_flag:
            self.info(appending timeout message)
            output += \nERROR: timeout after %d seconds\n % (timeout)
            session.close()

        return output


# ================================================================
# MAIN
# ================================================================
if __name__ == __main__:
    import sys

    # Access variables.
    hostname = hostname
    port = 22
    username = username
    password = password
    sudo_password = password  # assume that it is the same password

    # Create the SSH connection
    ssh = MySSH()
    ssh.set_verbosity(False)
    ssh.connect(hostname=hostname,
                username=username,
                password=password,
                port=port)
    if ssh.connected() is False:
        print ERROR: connection failed.
        sys.exit(1)

    def run_cmd(cmd, indata=None):
        ‘‘‘
        Run a command with optional input.

        @param cmd    The command to execute.
        @param indata The input data.
        @returns The command exit status and output.
                 Stdout and stderr are combined.
        ‘‘‘
        print
        print = * 64
        print command: %s % (cmd)
        status, output = ssh.run(cmd, indata)
        print status : %d % (status)
        print output : %d bytes % (len(output))
        print = * 64
        print %s % (output)

    run_cmd(uname -a)
    run_cmd(sudo ls -ltrh /var/log | tail, sudo_password)  # sudo command

 

Paramiko实现远程访问配置

标签:pre   sock   command   std   exce   Matter   mes   cee   ssh   

原文地址:https://www.cnblogs.com/bhan5/p/10974013.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!