Использование os.forkpty () для создания псевдо-терминала для ssh на удаленном сервере и связи с ним - PullRequest
5 голосов
/ 24 августа 2011

Я пытаюсь написать скрипт на python, который может использовать ssh на удаленном сервере и выполнять простые команды, такие как ls, cd, из клиента python. Тем не менее, я не могу прочитать вывод с псевдо-терминала после успешного ssh'ing на сервер. Может ли кто-нибудь помочь мне здесь, чтобы я мог выполнить некоторые команды на сервере.

Вот пример кода:

#!/usr/bin/python2.6
import os,sys,time,thread
pid,fd = os.forkpty()
if pid == 0:
    os.execv('/usr/bin/ssh',['/usr/bin/ssh','user@host',])
    sys.exit(0)
else:
    output = os.read(fd,1024)
    print output
    data = output
    os.write(fd,'password\n')
    time.sleep(1)
    output = os.read(fd,1024)
    print output
    os.write(fd,'ls\n')
    output = os.read(fd,1024)
    print output

Пример вывода:

user@host's password: 

Last login: Wed Aug 24 03:16:57 2011 from 1x.x.x.xxxx

-bash: ulimit: open files: cannot modify limit: Operation not permitted
host: /home/user>ls

Ответы [ 2 ]

3 голосов
/ 24 августа 2011

Я бы предложил попробовать модуль pexpect, который создан именно для такого рода вещей (взаимодействие с другими приложениями через псевдо-TTY), или Fabric, который создан для такого рода вещей более абстрактно (автоматизация задач системного администрирования). на удаленных серверах, использующих SSH).

pexpect: http://pypi.python.org/pypi/pexpect/

Ткань: http://docs.fabfile.org/en/1.11/

2 голосов
/ 24 августа 2011

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

#!/usr/bin/python2.6
import os,sys,time,thread
pid,fd = os.forkpty()
if pid == 0:
    os.execv('/usr/bin/ssh',['/usr/bin/ssh','localhost',])
    sys.exit(0)
else:
    output = os.read(fd,1024)
    print output
    os.write(fd,'ls\n')
    time.sleep(1) # this is new!
    output = os.read(fd,1024)
    print output

С добавленным sleep(1) я даю удаленный хост (или, в моем случае, не очень удаленный)host) время для обработки команды ls и выдачи ее результата.

Если вы отправите ls и сразу прочитаете, вы только прочитаете то, что присутствует в данный момент.Может быть, вы должны прочитать в цикле или около того.

Или вы просто должны сделать это следующим образом:

import subprocess
sp = subprocess.Popen(("ssh", "localhost", "ls"), stdout=subprocess.PIPE)
print sp.stdout.read()
...