Pexpect, запуск ssh-copy-id зависает при попытке запустить второй процесс - PullRequest
7 голосов
/ 10 декабря 2008

Я делаю скрипт на Python, где мне нужно создать несколько процессов ssh-copy-id, и мне нужно, чтобы я ввел пароль, поэтому я использую PExpect.

У меня в основном это:

child = pexpect.spawn('command')
child.expect('password:')
child.sendline('the password')

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

child = pexpect.spawn('command2')
child.expect('password:')
child.sendline('the password')

А код висит на втором "спавне"

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

Теперь, другая вещь, которую я не смог сделать, это подождать, пока первая остановится. Я пробовал:
child.close () - зависает (как с True, так и с False в качестве параметров) child.read (-1) - висит
child.expect (pexpect.EOF) - зависает.
child.terminate () - зависает (как с True, так и с False в качестве параметров)

Есть идеи о том, что может происходить?
ПРИМЕЧАНИЕ: я не эксперт по Python и никогда раньше не использовал pexpect, поэтому ЛЮБАЯ идея приветствуется.

Спасибо!


ОБНОВЛЕНИЕ: Это определенно связано с ssh-copy-id, потому что с другими процессами spawn работает хорошо, даже если они не возвращаются. Кроме того, очевидно, что ssh-copy-id никогда не возвращает EOF.

Ответы [ 4 ]

3 голосов
/ 02 ноября 2009

К счастью или нет, но клиент OpenSSH, кажется, очень требователен к паролям и откуда они берутся.

Вы можете попробовать использовать Paramiko Библиотека Python SSH2. Вот простой пример того, как использовать его с аутентификацией по паролю , затем введите несколько команд оболочки (echo "..." >> $HOME/.ssh/authorized_keys - самый простой), чтобы добавить ваш открытый ключ на удаленный хост.

1 голос
/ 11 декабря 2008

Я думаю, проблема в том, что SSH пытается открыть PTY, и он не работает на что-либо еще, чем PTY по соображениям безопасности. Это не будет работать хорошо с надеждой.

У меня есть другой ssh-клиент:

http://www.digmia.com/index.php?option=com_content&view=article&id=54:Digmia%20Enterprise%20SSH&Itemid=56

Это с открытым исходным кодом, вы можете использовать его. То, что вы пытаетесь сделать, будет быть больше команд, но вам вообще не нужно ожидать.

  1. Сначала установите его в соответствии с руководством, затем сделайте что-то вроде этого:

  2. Запустите dssh-agent, добавьте нужный вам пароль следующим образом:

    dssh-add -l < passwordfile
    
    • или если это защищенный компьютер, то есть никто другой не может войти туда, это очень важно, иначе это будет огромная дыра в безопасности:

      echo "name-of-server;22;root;password;" | dssh-add -l
      
    • password файл будет выглядеть примерно так:

      name-of-server;22;root;password;
      
  3. И сделать что-то вроде (замените CONTENTS OF ... на фактическое содержимое этого файла):

    dssh root@name-of-server -- echo "CONTENTS OF ~/.ssh/identity.pub" > .ssh/authorized_keys \; chmod og-w .ssh .ssh/authorized_keys
    
    • Вы можете (опционально) сделать

      dssh-add -f passwords
      

    (убедитесь, что никто больше не делает все это, иначе вы бы есть состояние гонки).

Кроме того, pexpect, вероятно, должен работать с самим dssh (так что вам не нужно использовать dssh-агент). Но использовать dssh-agent проще и безопаснее.

Руководство по установке для DSSH содержится в tarball.

Я не знаю более простого способа сделать это, OpenSSH ssh-copy-id очень требователен, откуда взялся пароль ...

0 голосов
/ 10 декабря 2008

На самом деле, я пробовал многие из этих альтернатив, и ни одна из них не работала.

  • Вызов функции close () или terminate () зависает (с параметрами True и False в качестве параметров)
  • Вызов ожидания () или чтения (-1) или ожидания (pexpect.EOF) зависает
  • повторный вызов spawn без заботы о предыдущих зависаниях команды spawn

Я провел несколько тестов с другими командами (например, «ftp»), и они работают так, как я ожидал, например, если вы вызываете .expect («что-то»), а что-то не найдено до EOF, они не т ждать вечно, они выдают исключение, поэтому я считаю, что это связано именно с командой ssh-copy-id.

0 голосов
/ 10 декабря 2008

Чтение pexpect документации для spawn , я думаю, она ожидает завершения команды.

Я бы предложил несколько вариантов, в зависимости от ваших потребностей:

1) Убить порожденного процесса. Однако это может привести к повреждению вашей работы, поэтому я не знаю, хотите ли вы этого.

child = pexpect.spawn('command')
child.expect('password:')
child.sendline('the password')
child.close(True)

2) Дождитесь завершения первоначального задания, прежде чем переходить к следующему

child = pexpect.spawn('command')
child.expect('password:')
child.sendline('the password')
child.wait()
child = pexpect.spawn('command2')
...

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

def exec_command(cmd):
  child = pexpect.spawn(cmd)
  child.expect('password:')
  child.sendline('the password')
  return child

commands = ['command1', 'command2']
childrens = [exec_command(cmd) for cmd in commands]
for child in childrens:
  child.wait()    

Примечание: весь код здесь не протестирован и написан в предположении, что ваш скрипт зависает, потому что удаление объекта spawn будет зависать до тех пор, пока команда не завершится.

...