Ни один из методов чтения Paramiko не работает для меня?

У меня есть этот класс, который я написал:

class Remote(object):
    def __init__(self, address, username, password):
        self.address  = address
        self.username = username
        self.password = password

    def stdout(self, s):
        print('out: ' + s)

    def stderr(self, s):
        print('err: ' + s)

    def sh(self, s):
        from paramiko  import AutoAddPolicy, SSHClient
        from threading import Thread
        from time      import sleep

        ssh = SSHClient()
        ssh.set_missing_host_key_policy(AutoAddPolicy())
        ssh.connect(self.address, username = self.username, password = self.password)
        stdin, stdout, stderr = ssh.exec_command(s)

        def monitor(channel, method):
            while True:
                for line in channel.readlines():
                    method(line)
                sleep(1)

        Thread(target = monitor, args = (stdout, self.stdout)).start()
        Thread(target = monitor, args = (stderr, self.stderr)).start()

Затем я пытаюсь запустить его так:

>>> from remote import Remote
>>> address  = <removed>
>>> username = 'root'
>>> password = <removed>
>>> r = Remote(address, username, password)
>>> r.sh('echo Hello')

И я не получаю выходной. Если я поменяю метод монитора так вместо:

for line in channel.readlines():
    method(line)

У меня просто method(channel.read()) или же method(channel.readline()), но в этом случае я просто вижу:

out:
err:

Раз в секунду - это никогда не дает мне ожидаемых результатов:

out: Hello

Я знаю, что мой адрес, имя пользователя и пароль в порядке, потому что я могу кормить их в fabric просто хорошо.

>>> from fabric.api        import env
>>> from fabirc.operations import sudo
>>> env.host_string, env.user, env.password = address, username, password
>>> sudo('echo Hello')
[<omitted>]: Hello

Что я делаю не так в своем paramiko основанный класс, который fabric очевидно, в состоянии справиться?

редактировать

Я хочу, чтобы метод был асинхронным. Это должно вернуться немедленно. Например, если я сделаю это:

r1 = Remote(<one set of credentials removed>)
r2 = Remote(<another set of credentials removed>)
r1.sh('echo Hello; sleep 5; echo World')
r2.sh('echo Hello; sleep 5; echo World')

Тогда результаты должны быть:

out: Hello
out: Hello
out: World
out: World

Указывает, что два вызова выполнялись параллельно, а не:

out: Hello
out: World
out: Hello
out: World

Что означало бы, что два вызова выполнялись синхронно.

1 ответ

Проблема в том, что while True зациклиться monitor предотвращает поток до конца. Оставьте первую часть как есть и измените последние строки на:

def monitor(channel, method):
    while True:
        l = channel.readline()
        if l:
            method(l)
        else:
            break
tout = Thread(target = monitor, args = (stdout, self.stdout))
terr = Thread(target = monitor, args = (stderr, self.stderr))
tout.start()
terr.start()
tout.join()
terr.join()
ssh.close()

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

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