python - mensaje - Usa subproceso para enviar una contraseña
encriptar imagenes con python (7)
¿Quizás deberías usar una biblioteca similar a expect ?
Por ejemplo Pexpect ( example ). También hay otras bibliotecas de python similares.
Estoy intentando usar el módulo de subproceso python para iniciar sesión en un sitio ftp seguro y luego capturar un archivo. Sin embargo, me quedo colgado al intentar enviar la contraseña cuando se solicita. Hasta ahora tengo el siguiente código:
from subprocess import Popen, PIPE
proc = Popen([''sftp'',''user@server'', ''stop''], stdin=PIPE)
proc.communicate(''password'')
Esto todavía se detiene en la solicitud de contraseña. Si ingreso la contraseña manualmente, irá al sitio ftp y luego ingresará la contraseña en la línea de comandos. He visto a personas sugerir el uso de pexpect, pero para resumir, necesito una solución de biblioteca estándar. ¿Hay de todos modos con subproceso y / o cualquier otro stdlib? ¿Qué estoy olvidando arriba?
Esta es una solución Python pura que utiliza expect, no pexpect.
Si en Ubuntu primero necesita instalar expect con:
sudo apt install expect
Python 3.6 o posterior:
def sftp_rename(from_name, to_name):
sftp_password = ''abigsecret''
sftp_username = ''foo''
destination_hostname = ''some_hostname''
from_name = ''oldfilename.txt''
to_name = ''newfilename.txt''
commands = f"""
spawn sftp -o "StrictHostKeyChecking no"
{sftp_username}@{destination_hostname}
expect "password:"
send "{sftp_password}/r"
expect "sftp>"
send "rename {from_name} {to_name}/r"
expect "sftp>"
send "bye/r"
expect "#"
"""
sp = subprocess.Popen([''expect'', ''-c'', commands], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
Este mismo problema me acosó durante una semana. Tuve que enviar una contraseña desde la entrada del usuario a través del subproceso de forma segura porque estaba tratando de evitar la introducción de una vulnerabilidad de inyección de comandos. Aquí es cómo resolví el problema con un poco de ayuda de un colega.
import subprocess
command = [''command'', ''option1'', ''--password'']
subprocess.Popen(command, stdin=subprocess.PIPE).wait(timeout=60)
El .wait (timeout = int) fue el componente más importante porque le permite al usuario agregar información a la entrada estándar. De lo contrario, el tiempo de espera se establece de forma predeterminada en 0 y no deja tiempo para que el usuario ingrese una entrada, lo que en consecuencia da como resultado una cadena Ninguna o nula. Me llevó por siempre para resolver esto.
Para los casos de uso repetido en los que sabe que tendrá que hacer esto varias veces, puede anular la función popen y usarla como un método privado que, según el mismo programador, es la mejor práctica si anticipa que alguien más estará interesado al mantener el código más adelante y no quieres que se metan con él.
def _popen(cmd):
proc_h = subprocess.Popen(cmd, stdin=subprocess.PIPE)
proc_h.wait(timeout=60)
return proc_h.poll() == os.EX_OK
Es importante eliminar stdout = subprocess.PIPE si se le solicitará al usuario que ingrese información. De lo contrario, el proceso parece suspenderse durante 60 segundos, y el usuario no recibe un aviso ni se da cuenta de que se espera que proporcione una contraseña. El stdout naturalmente irá a la ventana de la cáscara y permitirá al usuario pasar la entrada a popen ().
Además, solo para explicar por qué devuelve proc_h.poll () == os.EX_OK, es que devuelve 0 si el comando tuvo éxito. Esta es solo la mejor práctica de estilo C para cuando desea devolver códigos de error del sistema en caso de que la función falle, al tiempo que el intérprete considera que el retorno 0 será "falso".
Recomendaría desechar el enfoque de subproceso y usar el paquete paramiko para el acceso sftp.
Tratar
proc.stdin.write(''yourPassword/n'')
proc.stdin.flush()
Eso debería funcionar.
Lo que describe suena como stdin=None
donde el proceso hijo hereda el stdin del padre (su programa Python).
Utilice Paramiko
para SFTP. Para cualquier otra cosa, esto funciona:
import subprocess
args = [''command-that-requires-password'', ''-user'', ''me'']
proc = subprocess.Popen(args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
proc.stdin.write(''mypassword/n'')
proc.stdin.flush()
stdout, stderr = proc.communicate()
print stdout
print stderr
from subprocess import Popen, PIPE
proc = Popen([''sftp'',''user@server'', ''stop''], stdin=PIPE)
proc.communicate(input=''password'')
Pruebe con input = ''password'' en comunicarme, eso funcionó para mí.