it-swarm.com.de

Implementieren Sie eine interaktive Shell über ssh in Python mit Paramiko?

Ich möchte ein Programm schreiben (in Python 3.x unter Windows 7), das mehrere Befehle auf einer Remote-Shell über ssh ausführt. Nachdem ich mir die exec_command () - Funktion von paramikos angesehen hatte, stellte ich fest, dass sie für meinen Anwendungsfall nicht geeignet ist (da der Kanal geschlossen wird, nachdem der Befehl ausgeführt wurde), da die Befehle von Umgebungsvariablen abhängen (durch vorherige Befehle festgelegt) und nicht sein können zu einem exec_command () - Aufruf verkettet, da sie zu verschiedenen Zeitpunkten im Programm ausgeführt werden sollen.

Ich möchte also Befehle im selben Kanal ausführen. Die nächste Option, die ich untersuchte, war die Implementierung einer interaktiven Shell mit der invoke_Shell () - Funktion von paramikos:

ssh = paramiko.SSHClient()
ssh.set_missing_Host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(Host, username=user, password=psw, port=22)

channel = ssh.invoke_Shell()

out = channel.recv(9999)

channel.send('cd mivne_final\n')
channel.send('ls\n')

while not channel.recv_ready():
    time.sleep(3)

out = channel.recv(9999)
print(out.decode("ascii"))

channel.send('cd ..\n')
channel.send('cd or_fail\n')
channel.send('ls\n')

while not channel.recv_ready():
    time.sleep(3)

out = channel.recv(9999)
print(out.decode("ascii"))

channel.send('cd ..\n')
channel.send('cd simulator\n')
channel.send('ls\n')

while not channel.recv_ready():
    time.sleep(3)

out = channel.recv(9999)
print(out.decode("ascii"))

ssh.close() 

Es gibt einige Probleme mit diesem Code:

  1. Beim ersten 'Druck' wird nicht immer die 'ls'-Ausgabe gedruckt (manchmal wird nur der zweite' Druck 'gedruckt).
  2. Die ersten 'cd' und 'ls' Befehle sind immer in der Ausgabe vorhanden (ich bekomme sie über den 'recv' Befehl als Teil der Ausgabe), während die folgenden 'cd' und 'ls' Befehle manchmal gedruckt werden. und manchmal sind sie nicht.
  3. Die zweiten und dritten 'cd'- und' ls'-Befehle (beim Drucken) erscheinen immer vor der ersten 'ls'-Ausgabe.

Ich bin mit diesem "Nicht-Determinismus" verwirrt und würde Ihre Hilfe sehr schätzen.

13
misha
import paramiko
import re


class ShellHandler:

    def __init__(self, Host, user, psw):
        self.ssh = paramiko.SSHClient()
        self.ssh.set_missing_Host_key_policy(paramiko.AutoAddPolicy())
        self.ssh.connect(Host, username=user, password=psw, port=22)

        channel = self.ssh.invoke_Shell()
        self.stdin = channel.makefile('wb')
        self.stdout = channel.makefile('r')

    def __del__(self):
        self.ssh.close()

    def execute(self, cmd):
        """

        :param cmd: the command to be executed on the remote computer
        :examples:  execute('ls')
                    execute('finger')
                    execute('cd folder_name')
        """
        cmd = cmd.strip('\n')
        self.stdin.write(cmd + '\n')
        finish = 'end of stdOUT buffer. finished with exit status'
        echo_cmd = 'echo {} $?'.format(finish)
        self.stdin.write(echo_cmd + '\n')
        shin = self.stdin
        self.stdin.flush()

        shout = []
        sherr = []
        exit_status = 0
        for line in self.stdout:
            if str(line).startswith(cmd) or str(line).startswith(echo_cmd):
                # up for now filled with Shell junk from stdin
                shout = []
            Elif str(line).startswith(finish):
                # our finish command ends with the exit status
                exit_status = int(str(line).rsplit(maxsplit=1)[1])
                if exit_status:
                    # stderr is combined with stdout.
                    # thus, swap sherr with shout in a case of failure.
                    sherr = shout
                    shout = []
                break
            else:
                # get rid of 'coloring and formatting' special characters
                shout.append(re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]').sub('', line).
                             replace('\b', '').replace('\r', ''))

        # first and last lines of shout/sherr contain a Prompt
        if shout and echo_cmd in shout[-1]:
            shout.pop()
        if shout and cmd in shout[0]:
            shout.pop(0)
        if sherr and echo_cmd in sherr[-1]:
            sherr.pop()
        if sherr and cmd in sherr[0]:
            sherr.pop(0)

        return shin, shout, sherr
14
misha

Im Grunde verwende ich Ihren gesamten Code und füge nur eine for-Schleife hinzu:

commands = ["ls","command2","command3"]
conn_one = ShellHandler(Host,name,pwd)
for command in commands:
      conn_one.execute(command)

Er führt zwei der Befehle mit der richtigen Ausgabe aus, sitzt dann aber nur dort. Ich frage mich, ob ich del irgendwo im Code anrufen muss. 

0
magicsword