2017-05-07 2 views
0

Ich schreibe eine Python-Benutzerschnittstelle in kivy, um einige entfernte Maschinen mit Fabric zu verwalten. Da ich die parallele Implementierung von Fabric unter Windows 10 nicht verwenden kann (siehe here), hoffte ich, parallel-ssh zu verwenden, um die parallelen Remote-Operationen tatsächlich auszuführen. Dieses Problem scheint eher durch die Interaktionen zwischen den Bibliotheken als durch ein Problem mit einem einzelnen verursacht zu werden.Allgemeiner SSH-Fehler - Fehler beim Lesen des SSH-Protokoll-Banners

Ich habe versucht, manuell meine privaten Schlüssel Laden als here vorgeschlagen:

from fabric.api import execute 
import pssh 
from pssh.utils import load_private_key 

hosts = ['192.168.0.2'] 
private_key = load_private_key('C:/Users/democracy/.ssh/id_rsa') 
pssh_client = pssh.ParallelSSHClient(hosts, user='XXX', password='YYY', pkey=private_key) 
output = pssh_client.run_command('whoami', sudo=True) 
pssh_client.join(output) 
for host in output: 
    for line in output[host]['stdout']: 
     print("Host %s - output: %s" % (host, line)) 

Der obige Code führt zu folgendem Backtrace:

Exception: Error reading SSH protocol banner('This operation would block forever', <Hub at 0x242566ab9c8 select pending=0 ref=0>) 
Traceback (most recent call last): 
    File "C:\environments\democracy\lib\site-packages\paramiko\transport.py", line 1884, in _check_banner 
buf = self.packetizer.readline(timeout) 
    File "C:\environments\democracy\lib\site-packages\paramiko\packet.py", line 331, in readline 
buf += self._read_timeout(timeout) 
    File "C:\environments\democracy\lib\site-packages\paramiko\packet.py", line 485, in _read_timeout 
x = self.__socket.recv(128) 
    File "C:\environments\democracy\lib\site-packages\gevent\_socket3.py", line 317, in recv 
self._wait(self._read_event) 
    File "C:\environments\democracy\lib\site-packages\gevent\_socket3.py", line 144, in _wait 
self.hub.wait(watcher) 
    File "C:\environments\democracy\lib\site-packages\gevent\hub.py", line 630, in wait 
result = waiter.get() 
    File "C:\environments\democracy\lib\site-packages\gevent\hub.py", line 878, in get 
return self.hub.switch() 
    File "C:\environments\democracy\lib\site-packages\gevent\hub.py", line 609, in switch 
return greenlet.switch(self) 
gevent.hub.LoopExit: ('This operation would block forever', <Hub at 0x242566ab9c8 select pending=0 ref=0>) 

During handling of the above exception, another exception occurred: 

Traceback (most recent call last): 
    File "C:\environments\democracy\lib\site-packages\paramiko\transport.py", line 1740, in run 
self._check_banner() 
    File "C:\environments\democracy\lib\site-packages\paramiko\transport.py", line 1888, in _check_banner 
raise SSHException('Error reading SSH protocol banner' + str(e)) 
paramiko.ssh_exception.SSHException: Error reading SSH protocol banner('This operation would block forever', <Hub at 0x242566ab9c8 select pending=0 ref=0>) 

General SSH error - Error reading SSH protocol banner('This operation would block forever', <Hub at 0x242566ab9c8 select pending=0 ref=0>) 

Der obige Code funktioniert, wenn ich pssh vor Stoff importieren . Leider scheint es, wenn ich dies tue, irgendwelche Knöpfe auf meiner Kivy-Schnittstelle (die alle Operationen in einem Hintergrund-Thread starten) blockieren für immer beim Drücken. Wenn ich nach einem Tastendruck auf die Konsole gehe und einen Tastatur-Interrupt sende, hört kivy auf zu blocken und beginnt mit der Säuberung, führt aber den Befehl vom Knopf aus vor dem Beenden aus. Die Stacktrace diese Unterbrechung auf das Senden unter:

[INFO ] [Base  ] Leaving application in progress... 
Traceback (most recent call last): 
    File "machine_control_ui.py", line 7, in <module> 
DemocracyControllerApp().run() 
    File "C:\environments\democracy\lib\site-packages\kivy\app.py", line 828, in run 
runTouchApp() 
    File "C:\environments\democracy\lib\site-packages\kivy\base.py", line 504, in runTouchApp 
EventLoop.window.mainloop() 
    File "C:\environments\democracy\lib\site-packages\kivy\core\window\window_sdl2.py", line 659, in mainloop 
self._mainloop() 
    File "C:\environments\democracy\lib\site-packages\kivy\core\window\window_sdl2.py", line 405, in _mainloop 
EventLoop.idle() 
    File "C:\environments\democracy\lib\site-packages\kivy\base.py", line 339, in idle 
Clock.tick() 
    File "C:\environments\democracy\lib\site-packages\kivy\clock.py", line 553, in tick 
current = self.idle() 
    File "C:\environments\democracy\lib\site-packages\kivy\clock.py", line 533, in idle 
usleep(1000000 * sleeptime) 
    File "C:\environments\democracy\lib\site-packages\kivy\clock.py", line 717, in usleep 
_usleep(microseconds, self._sleep_obj) 
    File "C:\environments\democracy\lib\site-packages\kivy\clock.py", line 395, in _usleep 
_kernel32.WaitForSingleObject(obj, 0xffffffff) 
KeyboardInterrupt 

*** BUTTON PRESS OPERATION OUTPUTS HERE *** 

`` `

Einsicht in warum dies passiert sein könnte und wie ich zu vermeiden, kann es sehr geschätzt werden würde. Ich könnte möglicherweise andere parallele ssh-Lösungen untersuchen (obwohl ich mir vorstelle, dass paramiko dasselbe Problem haben würde), oder manuell einen Thread pro Host starten, um die parallele Operation zu erreichen (was wahrscheinlich eine eigene Liste von Kopfschmerzen hat), aber ich ' d bevorzugen, einfach die Parallel-SSH-Bibliothek zu verwenden, wenn es eine praktikable Lösung gibt.

ich parallel-ssh 0.92.2 auf Python 3 und Windows 10.

Antwort

1

Von docs bin mit -

Parallel-ssh verwendet GEVENT des Affen Patchen asynchrone Verwendung des Python-Standard zu ermöglichen, Netzwerk-I/O der Bibliothek.

Stellen Sie sicher, dass ParallelSSH Importe vor allen anderen Importen in Ihren Code kommen. Anderenfalls kann das Patchen nicht durchgeführt werden, bevor die Standardbibliothek geladen wird, was dazu führt, dass ParallelSSH blockiert.

Wenn Sie sehen, Nachrichten wie Diese Operation würde für immer blockieren, dies ist die Ursache.

Monkey-Patching wird nur für die Clients unter pssh.pssh_client und pssh.ssh_client für parallele bzw. einzelne Host-Clients durchgeführt.

Neue native Bibliothek basierte Clients unter pssh.pssh2_client und pssh.ssh2_client nicht durchführen Affen Patchen und sind eine Option, wenn Affen Patchen nicht geeignet ist. Diese Clients werden in einer zukünftigen Hauptversion 2.0.0 zum Standard .

Da Affe Patchen für den Client verwendet wird, die Sie verwenden, andere Verwendungen der threading, socket etc Module in Ihrer Anwendung auch gepatcht GEVENT zu verwenden, das heißt, sie nicht mehr in einem nativen Thread laufen, aber in eine Co-Routine/Greenlet.

Dies ist der Grund, warum Ihre Hintergrundthreadoperationen blockieren, da sie in einem Greenlet auf demselben Thread statt auf einem neuen Thread ausgeführt werden.

Ab 1.2.0, ein neuer Client basiert auf libssh2 statt paramiko zur Verfügung, die nicht Affe Patchen nicht verwendet:

from pssh.pssh2_client import ParallelSSHClient 

<..> 

Rest der Anwendung kann dann die Standardbibliothek verwenden, wie sie ist.

Verwandte Themen