我正在用kivy编写一个python来管理一些使用fabric的远程机器。由于我不能在Windows10上使用fabric的并行实现(请参阅这里),所以我希望使用并行ssh来实际执行并行远程操作。这个问题似乎是由库之间的交互引起的,而不是任何一个库之间的问题。
我尝试按建议的这里手动加载我的私钥
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>)
如果我在fabric之前导入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的任何东西都会有相同的问题),或者手动启动每个主机的线程以实现并行操作(否则可能会有它自己的头痛列表),但如果有可行的解决方案,我更愿意使用并行-ssh库。
我在Python 3和Windows 10上使用并行ssh 0.92.2。
发布于 2017-11-23 13:09:46
来自文档 -
并行ssh使用gevent的猴子补丁来支持异步使用Python标准库的网络I/O。 确保ParallelSSH导入在代码中的任何其他导入之前。否则,在加载标准库之前可能不会进行修补,这将导致ParallelSSH阻塞。 如果您看到这样的消息将永远阻塞,这就是原因。 猴子补丁只适用于pssh.pssh_client下的客户端和pssh.ssh_client下的并行和单主机客户端。 pssh.pssh2_client和pssh.ssh2_client下新的基于本机库的客户端不执行猴子修补,如果猴子修补不合适,则是一种选择。这些客户端将成为未来主要发行版的默认版本- 2.0.0。
由于猴子补丁用于您正在使用的客户端,应用程序中的threading
、socket
等模块的其他用途也将被修补为使用gevent,这意味着它们不再在本地线程中运行,而是在共同例程/绿色环境中运行。
这就是为什么后台线程操作在同一个线程上运行,而不是在新线程上运行时阻塞的原因。
在1.2.0
中,一个基于libssh2
而不是paramiko的新客户机是可用的,它不使用猴子补丁:
from pssh.pssh2_client import ParallelSSHClient
<..>
然后,应用程序的其余部分可以按原样使用标准库。
https://stackoverflow.com/questions/43833641
复制相似问题