Получение неконсольного (ish) результата из Python Paramiko - PullRequest
1 голос
/ 14 марта 2019

Я не начинающий программист, но я в основном использую C, а не Python.Я пытаюсь написать скрипт Python, используя Paramiko для доступа к SSH-серверу.

Соединение нормально, но я не могу понять, как ждать возвращаемые данные.

После подписанияна SSH-сервер он запускает приложение на консоли, которое затем требует входа.

Как мне дождаться, пока приложение завершит вывод, а затем отправить требуемый вход и пароль?

Я знаю другие библиотеки, такие как Fabric, но я не могу найти способ сделать это и для них.

import sys
from paramiko import client

class ssh:
    client = None

    def __init__(self, address, username, password):

        print("Connecting to server.")

        self.client = client.SSHClient()

        self.client.set_missing_host_key_policy(client.AutoAddPolicy())

        self.client.connect(address, username=username, password=password, look_for_keys=False)

    def sendCommand(self, command):

        # Check if connection is made previously.
        if(self.client):

            stdin, stdout, stderr = self.client.exec_command(command)

            while not stdout.channel.exit_status_ready():

                # Print data when available.
                if stdout.channel.recv_ready():

                    # Retrieve the first 1024 bytes.
                    alldata = stdout.channel.recv(1024)
                    prevdata = b"1"

                    while prevdata:
                        # Retrieve the next 1024 bytes.
                        prevdata = stdout.channel.recv(1024)
                        alldata += prevdata

                    print(str(alldata, "utf8"))
        else:
            print("Connection not opened.")

def main ():


    connection = ssh("SOME_IP", "USERNAME", "PASSWORD")

    connection.sendCommand("ls") # This works fine 
                                 # (on a system with no application running after login) 
                                 # so I know all is good

    # The problem is that after login an application is run automatically
    # that displays an input screen and waits for a different login and password.

    # I cant find a way to detect this screen has finished loading before I send login details.

    # I cant use "sendCommand" as the application runs straight after login, 
    # there is no command to send.

    # The actual end goal is to scrape the output from the application
    # after logging in and selecting a few options.

if __name__ == '__main__':
    sys.exit(main())

1 Ответ

1 голос
/ 15 марта 2019

Попробуйте:

#!/usr/bin/env python

import sys
import time
import paramiko

SSH_SERVER_IP ="IP_ADDRESS"

def main():

    client = paramiko.SSHClient()

    try:

        print("Establishing a connection to %s.\n" % SSH_SERVER_IP)

        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        client.connect(SSH_SERVER_IP, username="USERNAME", password="PASSWORD", look_for_keys=False)

        print("SSH connection established to %s.\n" % SSH_SERVER_IP)

    except paramiko.ssh_exception.BadHostKeyException:
        print("ERROR: The server's host key could not be verified. Exiting program.")
    except paramiko.ssh_exception.AuthenticationException: 
        print("ERROR: Authentication has failed. Exiting program.")
    except paramiko.ssh_exception.SSHException: 
        print("ERROR: There has been a problem connecting or establishing an SSH session. Exiting program.")
    except paramiko.ssh_exception.socket.error:
        print("ERROR: A socket error has occurred. Exiting program.")

    if(client):

        # A channel is a secure tunnel across an SSH Transport. A Channel is meant to behave like a socket, 
        # and has an API that should be indistinguishable from the Python socket API.

        # Start a shell session on the SSH server.
        # A channel is opened and connected to a pseudo-terminal and the channel ready to execute commands.
        # I used vt100 term with 250X100 terminal size.

        channel = client.invoke_shell(term="vt100", width=250, height=100)
        channel.settimeout(0.0)

        try:

            # wait until channel is ready.
            while not channel.recv_ready() :
                print("Waiting for recv_ready()\n\n")
                time.sleep(1)
                # Maybe add something here to stop infinite loop.

            receive_buffer = channel.recv(1024)

            print(receive_buffer)

            # Send a command to the channel.
            channel.send("SOME_COMMAND_OR_DATA")

        except Exception as ex:
            print("Error: ", ex)

        channel.close()

    else:
        print("No SSHClient connection available.")

    if(client):
        client.close()

if __name__ == '__main__':
    sys.exit(main())
...