2008-12-10 5 views
7

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

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

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

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

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

И код висит на втором «отродье»

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

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

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

Спасибо!


UPDATE: Это, безусловно, связано с SSH-копия-ID, потому что с другими процессами, икру работает хорошо, даже если они не вернутся. Кроме того, очевидно, что ssh-copy-id никогда не возвращает EOF.

+1

@ DanialMagliola У вас есть идеальное решение для этого? – Nilesh 2011-12-21 10:31:57

+0

Следуя советам http://linux.byexamples.com/archives/346/python-how-to-access-ssh-with-pexpect/, он работает для меня, добавляя `` `` child.expect (pexpect.EOF) `` `после отправки пароля – 2016-09-22 13:07:40

ответ

0

Чтение pexpect documentation for 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()  

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

0

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

  • Вызов близко() или прекратить() виснет (как с истинным и ложным в качестве параметров)
  • Вызова ожидания() или читать (-1) или ожидать (pexpect.EOF) висит
  • призывающей икры снова, не заботясь о предыдущей команде пояса, висит

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

1

Я думаю, проблема в том, что 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. Run dssh-агента, добавьте пароль, то нужно так:

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

      echo "name-of-server;22;root;password;" | dssh-add -l 
      
    • password файл будет что-то вроде:

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

    dssh [email protected] -- 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-копия-идентификатор очень требователен, где пароль приходит от ...

3

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

Вы можете попробовать использовать Paramiko Python SSH2 library. Вот простой example how to use it with password authentication, затем выполните некоторые команды оболочки (echo "..." >> $HOME/.ssh/authorized_keys, являющиеся простейшими), чтобы добавить ваш открытый ключ на удаленный хост.