Создание нескольких SSH-соединений одновременно с помощью Paramiko

Код ниже запускает grep на одной машине через SSH и выводит результаты:

import sys, os, string
import paramiko

cmd = "grep -h 'king' /opt/data/horror_20100810*"

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('10.10.3.10', username='xy', password='xy')
stdin, stdout, stderr = ssh.exec_command(cmd)
stdin.write('xy\n')
stdin.flush()

print stdout.readlines()

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


person Whit3H0rse    schedule 14.08.2010    source источник


Ответы (3)


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

Например:

import sys, os, string, threading
import paramiko

cmd = "grep -h 'king' /opt/data/horror_20100810*"

outlock = threading.Lock()

def workon(host):

    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(host, username='xy', password='xy')
    stdin, stdout, stderr = ssh.exec_command(cmd)
    stdin.write('xy\n')
    stdin.flush()

    with outlock:
        print stdout.readlines()

def main():
    hosts = ['10.10.3.10', '10.10.4.12', '10.10.2.15', ] # etc
    threads = []
    for h in hosts:
        t = threading.Thread(target=workon, args=(h,))
        t.start()
        threads.append(t)
    for t in threads:
        t.join()

main()

Если бы у вас было больше пяти хостов, я бы рекомендовал вместо этого использовать архитектуру «пула потоков» и очередь рабочих единиц. Но всего за пять проще придерживаться модели «выделенный поток» (тем более, что в стандартной библиотеке нет пула потоков, поэтому вам понадобится сторонний пакет, такой как threadpool... или, конечно же, много тонкого пользовательского кода;-).

person Alex Martelli    schedule 14.08.2010
comment
Я исключил 1 машину, поэтому мне нужно только 4. Я забыл упомянуть, что все данные будут обрабатываться позже в сценарии по-разному, и, как я понял ваш код (я использую PyN00b), он будет печатать все данные со всех машин одновременно, но как мне тогда обрабатывать данные только с одного хоста? И все хосты имеют разные проходы, так что могу ли я поместить их всех в workon()? Таю за быстрый повтор Алекс. С Уважением - person Whit3H0rse; 15.08.2010
comment
@konjo, вы можете выполнить обработку данных в потоке, который только что получил данные - вместо этого я print выполнял их только потому, что это то, что вы сделали в своем вопросе. Обработка, конечно, может включать проверки значения host, если вам нужно выполнить различную обработку для разных его значений. Или вы можете написать несколько функций для использования в качестве target= в своих потоках: нет ограничений, что все потоки должны выполнять одну и ту же функцию! - person Alex Martelli; 15.08.2010
comment
Хорошо, я смог собрать все 4 машины, но теперь все данные объединены. Как я могу извлечь данные из каждого отдельного хоста, можете ли вы привести пример, пожалуйста, расширьте пример выше? С Уважением - person Whit3H0rse; 26.08.2010
comment
Ty Alex за это, я думаю, что вы меня неправильно поняли, я принял ваш совет и пример сверху, но я новичок в программировании, поэтому мне нужно немного больше подсказок. Я сделал все, что вы написали выше, с моей модификацией для разных команд cmd. Тай снова. С Уважением - person Whit3H0rse; 26.08.2010
comment
@konjo, на Stack Overflow, для задающего вопрос принять ответ означает щелкнуть значок в виде галочки слева от ответа - это дает задавшему несколько очков репутации, а отвечающему больше. Ваш 0% принятый означает, что вы никогда этого не делали, что сбивает с толку. - person Alex Martelli; 26.08.2010
comment
@AlexMartelli, на что будет похож код, если мы хотим, чтобы одновременно выполнялось более 5 подключений? - person udit kanotra; 05.06.2019

В моем случае я должен выполнять команды на сервере с одним IP-адресом и портом, и после завершения необходимо выполнить sftp для другого ip-адреса и другого порта. Условие: одно соединение должно быть активным при выполнении sftp для другого ip из-за переадресации портов.

Оба соединения работают по отдельности, но при объединении второго sftp-соединения не работает.

person Romita Thakur    schedule 22.07.2020

Просто запустите все в цикле for и не забудьте закрыть стандартный ввод, прежде чем переходить к следующей итерации. То есть после строки stdin.flush() добавить строку stdin.close()

person Rushi Agrawal    schedule 02.09.2016