Verifique que exista un archivo sobre ssh

Estoy tratando de probar si existe un archivo a través de SSH usando pexpect. Tengo la mayoría del código funcionando pero necesito capturar el valor para poder afirmar si el archivo existe. El código que he hecho está abajo:

def VersionID(): ssh_newkey = 'Are you sure you want to continue connecting' # my ssh command line p=pexpect.spawn('ssh service@10.10.0.0') i=p.expect([ssh_newkey,'password:',pexpect.EOF]) if i==0: p.sendline('yes') i=p.expect([ssh_newkey,'password:',pexpect.EOF]) if i==1: p.sendline("word") i=p.expect('service@main-:') p.sendline("cd /opt/ad/bin") i=p.expect('service@main-:') p.sendline('[ -f email_tidyup.sh ] && echo "File exists" || echo "File does not exists"') i=p.expect('File Exists') i=p.expect('service@main-:') assert True elif i==2: print "I either got key or connection timeout" assert False results = p.before # print out the result VersionID() 

Gracias por cualquier ayuda.

Si el servidor acepta sesiones sftp, no me molestaría con pexpect, sino que usaría el módulo paramiko SSH2 para Python:

 import paramiko transport=paramiko.Transport("10.10.0.0") transport.connect(username="service",password="word") sftp=paramiko.SFTPClient.from_transport(transport) filestat=sftp.stat("/opt/ad/bin/email_tidyup.sh") 

El código abre una conexión SFTPClient al servidor, en la que puede usar stat () para verificar la existencia de archivos y directorios.

sftp.stat generará un IOError (‘No existe ese archivo’) cuando el archivo no exista.

Si el servidor no soporta sftp, esto funcionaría:

 import paramiko client=paramiko.SSHClient() client.load_system_host_keys() client.connect("10.10.0.0",username="service",password="word") _,stdout,_=client.exec_command("[ -f /opt/ad/bin/email_tidyup.sh ] && echo OK") assert stdout.read() 

SSHClient.exec_command devuelve un triple (stdin, stdout, stderr). Aquí solo comprobamos la presencia de cualquier salida. En su lugar, puede variar el comando o revisar stderr para ver si hay algún mensaje de error.

¿Por qué no aprovechar el hecho de que el código de retorno del comando se devuelve a través de SSH?

 $ ssh victory 'test -f .bash_history' $ echo $? 0 $ ssh victory 'test -f .csh_history' $ echo $? 1 $ ssh hostdoesntexist 'test -f .csh_history' ssh: Could not resolve hostname hostdoesntexist: Name or service not known $ echo $? 255 

De esta manera, solo puede verificar el código de retorno sin necesidad de capturar la salida.

Estaba teniendo algunos problemas con esto donde cada vez que ejecutaba mi progtwig, cambiaba la salida. Por ejemplo, si estuviera buscando /bin/bash , a veces devolvería el mensaje y otras veces devolvería si faltaba.

Obtuve el siguiente código para trabajar de forma coherente con los archivos y carpetas antes de lo que esperaba con \r\n

 # returns 0 if the file is missing and 1 if the file exists # if ( hostFileExists( host, '/bin/sh/' ) == 1 ): echo "File exists!" def hostFileExists( host, theFile ): host.sendline( '[ ! -e %r ] && echo NO || echo YES' % theFile ) return host.expect( ["\r\nNO", "\r\nYES"] ) 

o

 # provide the host, the command, and the expectation # command = '[ ! -e "/bin/sh" ] && echo NO || echo YES' # expecting = ['NO', 'YES'] # i = hostExpect( host, command, expecting ) # if ( i == 1 ): echo "File exists!" def hostExpect( host, command, expect ): newExpect = [] for e in expect: newExpect.append( "\r\n%s" % e ) host.sendline( command ) return host.expect( newExpect ) 

Espero que esto te ayude.

Edición: También noté que cuando se está ejecutando en Windows (cygwin) y tratando de ver si existe un archivo, se debe citar el archivo. En Linux, esto es opcional. Así que el %s en host.sendline se cambió a %r .

No tengo ninguna experiencia previa, pero al mirar su página web parece que puedes llamar al método expect con múltiples valores y devuelve el índice de la que coincide (esto se basa únicamente en mí, solo mirando este ejemplo) .

 child.expect('password:') child.sendline (my_secret_password) # We expect any of these three patterns... i = child.expect (['Permission denied', 'Terminal type', '[#\$] ']) if i==0: print 'Permission denied on host. Can't login' child.kill(0) elif i==2: print 'Login OK... need to send terminal type.' child.sendline('vt100') child.expect ('[#\$] ') elif i==3: print 'Login OK.' print 'Shell command prompt', child.after 

En realidad, ya estás usando esa funcionalidad en la parte superior.

¿Así que quieres ver si el archivo existe o no? …

Prueba esto…

  p.sendline('[ -f email_tidyup.sh ] && echo "File exists" || echo "File does not exists"') file_exists = {0: True, 1: False}[p.expect(('File Exists', 'File does not exists'))] 

He trabajado la solución que me hará. El código está abajo:

 def VersionID(): ssh_newkey = 'Are you sure you want to continue connecting' # my ssh command line p=pexpect.spawn('ssh service@10.10.0.0') i=p.expect([ssh_newkey,'password:',pexpect.EOF]) if i==0: p.sendline('yes') i=p.expect([ssh_newkey,'password:',pexpect.EOF]) if i==1: p.sendline("word") i=p.expect('service@main-:') p.sendline("cd /opt/ad/bin") i=p.expect('service@main-:') p.sendline('[ -f email_tidyup.sh ] && echo "File exists" || echo "File does not exists"') i=p.expect('service@main-:') assert True elif i==2: print "I either got key or connection timeout" assert False results = p.before # print out the result print results value = results.split('"')[8] split_value = value.split('\r\n')[1:-1] self.assertEquals(split_value, ['File exists']) 

Esto extrae el valor de ‘p’ en un formato de cadena. Luego divido la cadena para obtener la cadena ‘El archivo existe’ en una lista y la comparo con la respuesta que estoy buscando. Si el archivo no existe, la prueba fallará.

Gracias por toda la ayuda.

Cuando usted, como usuario, escribe algo en ssh, el shell devolverá los caracteres. Eso está sucediendo ahora también.

Entonces, haciendo:

 p.sendline('test -f email_tidyup.sh && echo "File exists" || echo "File does not exist"') 

Resultará en una entrada de:

 service@main-: test -f email_tidy.sh && echo "File exists" || echo "File does not exists" File does not exist 

Obra:

 i = p.expect(['File exists', 'File does not exist']) 

Entonces siempre dará como resultado i == 0, porque “el archivo existe” está presente en la primera línea que se recibe de nuevo.

Una alternativa donde la línea de envío original, no tiene la frase esperada:

 p.sendline('test -f email_tidyup.sh; echo result: $?') i = p.expect('result: 0', 'result: 1') 

O más como el original:

 p.sendline('[ -f email_tidyup.sh ] && echo "File exists" || echo "File does not exist"') i = p.expect(['\nFile exists', '\nFile does not exist'])