2017-05-07 97 views
0

我正在用kivy编写一个python用户界面来管理一些具有结构的远程机器。由于我无法在Windows 10上使用光纤并行实现(请参阅here),我一直希望使用parallel-ssh实际执行并行远程操作。这个问题似乎是由这些库之间的交互引起的,而不是其中任何一个问题。一般SSH错误 - 读取SSH协议标题时出错

我已经试过手动加载我的私有密钥的建议here

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)) 

上面的代码导致以下回溯:

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>) 

上面的代码工作,如果我之前面料进口PSSH 。不幸的是,看起来如果我这样做,我的kivy界面上的任何按钮(在后台线程中启动任何操作)都将永久屏蔽。如果我在按下按钮并发送键盘中断后进入控制台,kivy会停止拦截并开始清理,但在退出前按下按钮执行命令。在发送该中断的堆栈跟踪低于:

[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 *** 

```

任何深入了解为什么这可能发生,我怎么能避免它,将不胜感激。我可能会研究其他并行的ssh解决方案(尽管我想象使用paramiko的任何东西都会有相同的问题),或者手动启动每个主机的线程以实现并行操作(可能有其自己的头痛列表),但是,如果有可行的解决方案,我宁愿只使用parallel-ssh库。

我使用的是平行SSH 0.92.2关于Python 3和Windows 10

回答

1

docs -

平行SSH使用GEVENT的猴子补丁,使Python标准的异步使用 库的网络I/O。

确保ParallelSSH导入位于 代码的任何其他导入之前。否则,在加载标准的 库之前,可能无法进行修补,这会导致ParallelSSH阻塞。

如果您看到类似此操作的消息将永远阻止, 这是原因。

猴修补是仅在pssh.pssh_client 和pssh.ssh_client分别做了客户端的并行和单台主机的客户。

新机库基于下pssh.pssh2_client和 pssh.ssh2_client客户不执行猴子打补丁,如果 猴子修补是不适用,有一个选项。这些客户端将在未来的主要版本 - 2.0.0中成为默认的 。

由于猴子补丁用于您正在使用的客户端,则threadingsocket的其他用途等模块在应用程序中也已修补使用GEVENT这意味着他们不再在本地线程,但在运行一个联合程序/ greenlet。

这就是你的后台线程操作阻塞的原因,因为它们在同一个线程而不是新线程的greenlet中运行。

截至1.2.0,基于libssh2代替的paramiko一个新的客户端可用不使用猴子补丁:

您的应用程序则可以使用标准库作为-是
from pssh.pssh2_client import ParallelSSHClient 

<..> 

休息。