Общая ошибка 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

<..>

Остальная часть вашего приложения может использовать стандартную библиотеку как есть.

Другие вопросы по тегам