2008-12-10 19 views
7

Estoy haciendo un script de Python donde necesito generar varios procesos de ssh-copy-id, y necesitan que escriba una contraseña Así que estoy usando PExpect.Pexpect, ejecutar ssh-copy-id se bloquea cuando intenta generar un segundo proceso

que tienen básicamente la siguiente:

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

y luego quiero para desovar otro proceso, no me importa acerca de esto nunca más, si se terminó o no.

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

Y el código está colgando en la segunda "engendro"

Sin embargo, si comento hacia fuera la primera, la segunda funciona, así que supongo que el hecho de que el primero es sigue corriendo o algo impide que funcione.

Ahora, la otra cosa que no he podido hacer es esperar hasta que se detenga la primera. que he probado:
child.close() - Se cuelga (ambos con verdadero y falso como parámetros) child.read (-1) - Se cuelga
child.expect (pexpect.EOF) - se cuelga.
child.terminate() - se cuelga (ambos con verdadero y falso como parámetros)

¿Alguna idea sobre qué podría estar pasando?
NOTA: No soy un experto en Python, y nunca he usado pexpect antes, por lo que CUALQUIER idea es más que bienvenida.

Gracias!


ACTUALIZACIÓN: Este es, sin duda relacionada con ssh-copy-id, ya que con otros procesos, engendro funciona bien incluso si no vuelven. Además, aparentemente ssh-copy-id nunca devuelve un EOF.

+1

@DanialMagliola ¿Tiene alguna solución perfecta para esto? – Nilesh

+0

Siguiendo los consejos de http://linux.byexamples.com/archives/346/python-how-to-access-ssh-with- pexpect/, funciona para mí agregando '' 'child.expect (pexpect.EOF) '' 'después de enviar la contraseña –

Respuesta

0

Lectura pexpect documentation for spawn, creo que está esperando a que finalice el comando.

que sugeriría un par de posibilidades diferentes, dependiendo de sus necesidades:

1) Mata al proceso generado. Sin embargo, esto puede provocar corrupción en su operación, por lo que no sé si es lo que desea.

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

2) Esperar a la finalización de la tarea inicial antes de pasar a la siguiente

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

3) Utilice una instancia diferente para todos los niños, y luego esperar en todos ellos al final - y esto sería muy probablemente la mejor solución

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()  

Nota: todo el código que aquí no se ha probado, y escrito bajo el supuesto de que el script está colgando debido a la supresión de un objeto de desove se bloqueará hasta que t El comando terminará.

0

En realidad, probé muchas de estas alternativas, y ninguna funcionó.

  • Invocar close() o terminar() se bloquea (ambos con verdadero y falso como parámetros)
  • Llamada de espera() o leer (-1) o espera (pexpect.EOF) cuelga
  • desove llamando de nuevo sin preocuparse por el comando spawn anterior cuelga

Hice algunas pruebas con otros comandos (como 'ftp', y funcionan como esperaba, por ejemplo, si llama a .expect ('algo') , y algo no se encuentra antes de EOF, no esperan para siempre, arrojan una excepción, así que creo que esto está relacionado con el ssh-copy-id comando específicamente.

+0

¿Es posible que el comando simplemente esté tardando mucho tiempo en ejecutarse? ¿Qué tal comenzar un nuevo hilo para cada comando? –

+0

Definitivamente ese no es el problema. Si lo ejecutamos a través de la línea de comando, termina casi inmediatamente una vez que se ingresa la contraseña. –

+0

Entonces probaría con las técnicas normales de depuración, como establecer child.logfile = sys.stdout –

1

Creo que el problema es que SSH intenta abrir PTY y no funciona en cualquier cosa que no sea PTY por razones de seguridad. Esto no funcionará bien con pexpect.

tengo otro cliente ssh:

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

Es de código abierto, que se puede utilizar. Lo que está tratando de hacer sería tener más comandos, pero no necesita esperar nada.

  1. instala por primera vez de acuerdo con el manual, a continuación, hacer algo como esto:

  2. Run dssh-agente, añadir la contraseña que necesita de esta manera:

    dssh-add -l < passwordfile 
    
    • o si es una máquina segura, es decir, nadie más puede iniciar sesión allí, esto es muy importante, de lo contrario, esto sería una gran seguridad h ole:

      echo "name-of-server;22;root;password;" | dssh-add -l 
      
    • password archivo sería algo así como:

      name-of-server;22;root;password; 
      
  3. Y el hacer algo como (reemplace CONTENTS OF ... con contenido real de ese archivo):

    dssh [email protected] -- echo "CONTENTS OF ~/.ssh/identity.pub" > .ssh/authorized_keys \; chmod og-w .ssh .ssh/authorized_keys 
    
    • Usted puede (opcionalmente) hacer

      dssh-add -f passwords 
      

    (asegurarse de que nadie más está haciendo todo esto, de lo contrario sería tener una condición de carrera).

Además, pexpect probablemente debería trabajar con dssh en sí (por lo que no es necesario utilizar dssh-agente). Pero usar dssh-agent es más simple y seguro.

El manual de instalación para DSSH se encuentra en el archivo tarball.

no sé de ninguna manera más simple de hacer esto, OpenSSH ssh-copy-id es muy exigente con la contraseña viene de ...

3

Afortunadamente o no, pero el cliente OpenSSH parece ser muy exigente con las contraseñas y de dónde vienen.

Puede probar el uso de Paramiko biblioteca Python SSH2. Aquí hay un simple example how to use it with password authentication, luego emita algunos comandos de shell (el más simple es echo "..." >> $HOME/.ssh/authorized_keys) para agregar su clave pública en el host remoto.

Cuestiones relacionadas