Pexpect, запуск ssh-copy-id зависает при попытке запустить второй процесс

Я делаю скрипт на 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.

10.12.2008 17:16:31
@DanialMagliola У вас есть идеальное решение для этого?
Nilesh 21.12.2011 10:31:57
Следуя советам от linux.byexamples.com/archives/346/… , это работает для меня, добавив child.expect(pexpect.EOF)после отправки пароля
Stéphane 22.09.2016 13:07:40
4 ОТВЕТА

Читая документацию 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 будет зависать до тех пор, пока команда не завершится.

0
10.12.2008 18:10:05

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

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

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

0
10.12.2008 18:43:21
Возможно ли, что выполнение команды просто занимает много времени? Как насчет запуска нового потока для каждой команды?
rob 10.12.2008 18:54:34
Это определенно не проблема. Если мы запустим его через командную строку, он заканчивается почти сразу после ввода пароля.
Daniel Magliola 10.12.2008 19:51:09
Затем я попытался бы использовать обычные методы отладки, такие как установка child.logfile = sys.stdout
rob 10.12.2008 21:37:19
Я попытался установить лог-файл на стандартный вывод. Я получаю тот же вывод, что и при запуске из командной строки, за исключением того, что он не заканчивается.
Daniel Magliola 10.12.2008 22:00:54

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

У меня есть другой клиент 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-agent). Но использовать dssh-agent проще и безопаснее.

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

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

1
18.01.2012 16:59:00

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

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

3
2.11.2009 18:49:35