Python SSH итерация по разным путям - PullRequest
0 голосов
/ 14 января 2019

У меня есть объект JSON, который выглядит так:

{UID_1:{
    jumpboxes:[jump_ip1, jump_ip2,...],
    hosts: [host_ip1, host_ip2,...],
    ...},
UID_2:{...

Аутентификация в полях для переадресации выполняется через Kerberos (без пароля), аутентификация для хостов - с паролем, а хосты видны только через хосты перескоков. Из списка IP-адресов я не знаю, какие из них работают, какие застряли или не отвечают, и т. Д., Поэтому мне нужно найти первый путь, который позволил бы мне открыть сеанс SSH.

Что я могу сделать, это проверить коды выхода при подключении к хостам перехода примерно так:

jumpip = ''
for i in json[uid][jumpboxes]:
    if os.system('ssh {}@{}'.format(username,i))>0:
        continue
    else:
        jumpip = i
        break

Это дает мне первый рабочий IP-адрес Jumpbox без проблем, однако наличие пароля для установки ssh-соединения со вторым хостом не так легко проверить для кода выхода.

Существует несколько способов открыть туннель - либо с помощью os.system (), либо с помощью sshpass с прокси-сервером сеанса (что-то вроде: if os.system('sshpass -p {} ssh -o ProxyCommand="ssh {}@{} nc {} 22" {}@{} -t {}'.format(password, user, jumpip, hosts[j], user, hosts[j], remote_cmd))>0:.... (для контекста давайте предположим, что команда sshpass будет выглядеть примерно так: sshpass -p Password123! -o ProxyCommand="ssh user@jumpbox nc hostip 22" user@hostip -t ll или выполнение pint в подоболочке с чем-то вроде os.system('ssh user@jumpbox -t ping {} -c 5'.format(hosts[j])), и хотя ping возвращает код завершения, ICMP-эхо-ответы не означают, что я ' я могу открыть туннель (например, демон может застрять или мог произойти сбой и т. д.), или я могу сделать блок try-exc-else, который пытается открыть сессию ssh для удаленного хоста с помощью jumpbox с помощью pexpect или с subrpocess.popen и с передачей по каналу stdio, что позволяет мне нажать пароль и, если это не удается вызвать пользовательское исключение, но я не могу понять, как получить код выхода из клиента ssh, поэтому я могу проверить наличие статус ...

Ни один из них не является достаточно надежным для меня, поэтому я бы предпочел правильно перебирать IP-адреса, для которых я открыт для предложений.

Немного предыстории - туннель будет использоваться для запуска команды nohup-ed, а затем будет закрыт. Скрипт использует многопроцессорную обработку и пул для прохождения всей этой группы, поэтому я запустил их, а затем выполнил цикл, чтобы проверить их состояние и получить результат удаленного скрипта, выполненного на хостах. Я знаю, что os.system устарела, и мне следует использовать подпроцесс, но это не обязательно для варианта использования, поэтому меня это не особо волнует. Я ищу умный способ, как перебрать возможные пути, которые будут принимать, учитывая список с прыгуном с длиной n и список с узлами с длиной m и тайм-аут x секунд максимум n*m*x секунд чтобы выяснить, а вместо этого сократить это время.

Я также использую pexpect (который сам использует paramiko) для взаимодействия с удаленными хостами, как только я нашел правильные IP-адреса, с которыми мне нужно открыть туннель.

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 15 января 2019

Я понял - pexpect предлагает код выхода, если есть подсказка, то есть я сделал что-то вроде

host = ''
for i in hosts:
    cmd = 'ssh {}@{} -t ssh {}'.format(user,jumpbox, i)
    try:
        p = pexpect.spawn(cmd)
        if p.expect('.*') == 0:
            host = i
            break
    except:
        someException()
if host != '':
    ...

Спасибо за все комментарии.

0 голосов
/ 14 января 2019

Функция Paramiko exit_status_ready сообщит вам о состоянии выхода.

Вернуть true, если удаленный процесс завершил работу и вернул выход статус. Вы можете использовать это для опроса статуса процесса, если вы не хотите заблокировать в recv_exit_status. Обратите внимание, что сервер может не вернуть статус выхода в некоторых случаях (например, плохие серверы).

Глядя на исходный код pexpect, я не вижу, где он использует Paramiko, поэтому вам может потребоваться заменить весь код pexpect на код Paramiko. Paramiko дает вам большой контроль над всеми низкоуровневыми аспектами установления SSH-соединения, поэтому его может быть немного сложно понять, но он дает вам большой контроль над всем процессом.

...