Общая ошибка SSH - Ошибка чтения баннера протокола SSH
Я пишу пользовательский интерфейс Python в kivy для управления некоторыми удаленными машинами с фабрикой. Поскольку я не могу использовать параллельную реализацию Fabric в Windows 10 (см. Здесь), я надеялся использовать параллельный-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>)
Приведенный выше код работает, если я импортирую 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, могло бы иметь такую же проблему), или вручную запустить поток для каждого хоста, чтобы в противном случае выполнить параллельную операцию (которая, вероятно, имеет свой собственный список головных болей), но я ' Я предпочел бы просто использовать библиотеку Parallels-SSH, если есть работоспособное решение.
Я использую Parallels-SSH 0.92.2 на Python 3 и Windows 10.
1 ответ
Из документов -
Параллельное-ssh использует патч Gevent для обеспечения асинхронного использования сетевого ввода-вывода стандартной библиотеки Python.
Убедитесь, что импорт ParallelSSH предшествует любому другому импорту в вашем коде. В противном случае исправление может быть не выполнено до загрузки стандартной библиотеки, что приведет к блокировке ParallelSSH.
Если вы видите такие сообщения, как эта операция будет заблокирована навсегда, это причина.
Патч-обезьяна выполняется только для клиентов в папках pssh.pssh_client и pssh.ssh_client для клиентов с параллельным и одиночным хостом соответственно.
Новые клиенты, основанные на собственных библиотеках в папках pssh.pssh2_client и pssh.ssh2_client, не выполняют исправление обезьян и являются опцией, если исправление обезьян не подходит. Эти клиенты станут стандартными в будущем выпуске 2.0.0.
Так как патч обезьяны используется для клиента, которого вы используете, другие применения threading
, socket
Модули etc в вашем приложении также будут исправлены для использования gevent, что означает, что они больше не работают в собственном потоке, а в подпрограмме / greenlet.
Это причина того, что ваши фоновые операции потока блокируются, поскольку они выполняются в гринлете в том же потоке, а не в новом потоке.
По состоянию на 1.2.0
новый клиент на основе libssh2
вместо paramiko доступно, которое не использует исправления обезьян:
from pssh.pssh2_client import ParallelSSHClient
<..>
Остальная часть вашего приложения может использовать стандартную библиотеку как есть.