2016-04-21 4 views
2

У меня есть этот класс я написал:Ни один из методов чтения 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() 

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

+0

Я хочу, чтобы методы выполнялись асинхронно. Он не должен ждать, пока команда не вернется. Если пользователь класса заботится о том, что команда выводит, они должны подклассы и использовать методы 'stdout' или' stderr'. – ArtOfWarfare

+0

@ArtOfWarfare Понял, см. Правки – fernandezcuesta

+0

Я не думаю, что вы понимаете - это все равно приводит к синхронному звонку. Я добавил изменение в свой вопрос, чтобы объяснить. Сказав это, ваш код действительно выводит что-то, тогда как мой исходный код ничего не выводит, поэтому +1 для этого. Кроме того, я дам вам знать, что сделать этот синхронный процесс довольно простым. Все, что мне нужно было сделать, это изменить имя 'sh' на' _sh' (указать его личное) и создать новый 'sh', который только начинает поток и запускает' _sh', а затем возвращается без соединения. Не уверен, что это самое элегантное решение или нет, но оно работает. – ArtOfWarfare

 Смежные вопросы

  • Нет связанных вопросов^_^