2015-07-17 7 views
9

Я использую этот код для выполнения команды на удаленном сервере.Подпроцесс на удаленном сервере

import subprocess 
import sys 
COMMAND="ls" 

ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND], 
        shell=False, 
        stdout=subprocess.PIPE, 
        stderr=subprocess.PIPE) 
result = ssh.stdout.readlines() 
if result == []: 
    error = ssh.stderr.readlines() 
    print >>sys.stderr, "ERROR: %s" % error 
else: 
    print result 

Когда я пытаюсь выполнить этот скрипт, я получаю запрос на ввод пароля. Есть ли способ избежать этого, например, можно каким-то образом ввести пароль в скрипт? Кроме того, пароль должен быть зашифрован так, чтобы люди, имеющие доступ к скрипту, не могли его увидеть.

+1

Вы задумывались над использованием схемы аутентификации, отличной от ввода пароля? –

ответ

4

Одним из способов является создание открытого ключа, поставить его на сервере, и сделать ssh -i /path/to/pub/key [email protected] или использовать paramiko вроде этого:

import paramiko 
import getpass 

ssh = paramiko.SSHClient() 

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 

p = getpass.getpass() 

ssh.connect('hostname', username='user', password=p) 

stdin, stdout, stderr = ssh.exec_command('ls') 
print stdout.readlines() 
ssh.close() 
+0

tnx. Есть ли способ маскировать пароль? –

+0

@ ZvonimirPeran да, дайте мне второй, чтобы изменить мой ответ – heinst

+0

@ZvonimirPeran проверить сейчас, это работает на большинстве терминальных версий, 'getpass' даст предупреждение на некоторых терминалах, что он не может скрыть пароль – heinst

2

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

1

Хотя subprocess.Popen может работать для упаковки ssh доступа, это не является предпочтительным способом для этого.

Я рекомендую использовать paramiko.

import paramiko 
ssh_client = paramiko.SSHClient() 
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
ssh_client.connect(server, username=user,password=password) 
... 
ssh_client.close() 

И если вы хотите, чтобы имитировать терминал, как если бы пользователь печатал:

chan=ssh_client.invoke_shell() 

def exec_cmd(cmd): 
    """Gets ssh command(s), execute them, and returns the output""" 
    prompt='bash $' # the command line prompt in the ssh terminal 
    buff='' 
    chan.send(str(cmd)+'\n') 
    while not chan.recv_ready(): 
     time.sleep(1) 
    while not buff.endswith(prompt): 
     buff+=ssh_client.chan.recv(1024) 
    return buff[:len(prompt)] 

Пример использования: exec_cmd('pwd')

Если вы не знаете, приглашение заранее, вы может установить его с:

chan.send('PS1="python-ssh:"\n') 
+1

'paramiko', вероятно, слишком низкоуровневый, чтобы запустить команду через ssh. Здесь проще использовать ['fabric'] (http://fabfile.org) или [' pexpect'] (https://pexpect.readthedocs.org) здесь. В любом случае правильное решение будет использовать ключи ssh. – jfs

+0

Да, ssh ключи наверняка, если это не по какой-то причине. – binarysubstrate

2

Вот что я сделал, когда сталкивался с этой проблемой раньше:

  1. Настройте свои ключи ssh для доступа к серверу.
  2. Set up an alias for the server you're accessing. Ниже я назову это remote_server.
  3. Поместите следующие две строки в конце ~/.bash_profile.

    eval $(ssh-agent -s) 
    ssh-add 
    

Теперь каждый раз при запуске оболочки, вам будет предложено ввести ключевую фразу. Введя его, вы будете аутентифицировать свои ключи ssh и поместить их «в руки» в начале вашей сессии bash. На оставшуюся часть вашей сессии вы сможете запускать команды, такие как

ssh remote_server ls 

без запроса кодовой фразы. Здесь ls будет запускаться на удаленном сервере и возвращать вам результаты. Аналогично, ваш скрипт python должен запускаться без прерывания запроса пароля, если вы выполните его из оболочки.

Вы также сможете отправить ssh на сервер, просто набрав ssh remote_server без необходимости вводить свое имя пользователя или пароль каждый раз.

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

1

Вам не нужно что-то вроде pexpect, чтобы справиться с этим. Ключи SSH уже обеспечивают очень хорошее и безопасное решение этой проблемы.

Самый простой способ получить желаемые результаты, вероятно, состоял бы в создании ключа ssh и поместить его в папку .ssh вашего устройства. Я считаю, что github имеет довольно хорошее руководство для этого, если вы посмотрите на него. Как только вы правильно настроите ключи в обеих системах, вам фактически не нужно будет добавлять одну строчку в свой код. Если вы не укажете пароль, он автоматически использует ключ для аутентификации.

1

Почему это так сложно? Вот что я предлагаю:

1) Создайте конфигурационный раздел SSH в файле ~/.ssh/конфигурации:

Host myserver 
    HostName 50.50.50.12 (fill in with your server's ip) 
    Port xxxx (optional) 
    User me (your username for server) 

2) Если вы сгенерировали ваш SSH ключей сделать это сейчас (с SSH-серийник). Затем загрузите с помощью:

$ ssh-copy-id myserver 

3) Теперь вы можете использовать подпроцесс с помощью ssh. Например, чтобы захватить выход, я называю:

result = subprocess.check_output(['ssh', 'myserver', 'cat', 'somefile']) 

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

BTW, вы, вероятно, будете работать с кодом, используя эти шаги.

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