Automatice la conexión ssh y la ejecución del programa con Paramiko de Python
(1)
Quiero automatizar una tarea específica usando python.
Esta tarea incluye, entre otras cosas, conectarse con ssh a un servidor remoto y ejecutar un programa específico (llamarlo
prog.out
) que
puede o no solicitar la entrada del usuario
.
Después de investigar un poco y después de ponderar mis opciones, decidí usar el Paramiko de Python (que puede resultar incorrecto, teniendo en cuenta lo siguiente ...).
Comencemos con la posibilidad fácil de
prog.out
pedir ninguna entrada, sino que solo imprime alguna información en la consola:
int main(int argc, char* argv[]) {
printf("Hey there, fella/n");
printf("How are you this morning?/n");
printf("See ya.../n");
return 0;
}
que se compila en:
prog.out
, y se encuentra en
server_name
, esperando ser ejecutado.
Entonces en ese caso:
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect("server_name")
sin, sout, serr = client.exec_command(''./prog.out'')
for line in sout.readlines():
print(line, end = '''')
prog.out
perfectamente bien e imprimirá lo que produzca
prog.out
.
Pero si en cambio
prog.out
es:
int main(int argc, char* argv[]) {
printf("Hey there, fella/n");
printf("How are you this morning?/n");
printf("please enter an integer.../n");
int a;
scanf("%d", &a);
printf("you entered %d/n", a);
printf("see ya.../n");
return 0;
}
entonces el código de Python anterior se bloqueará en
sout.readlines()
(¿esperando eof?) ...
La forma de evitar el bloqueo en
sout.readlines()
es proporcionar información a
prog.out
escribiendo en su canalización estándar:
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect("server_name")
sin, sout, serr = client.exec_command(''./prog.out'')
sin.write(''55/n'')
for line in sout.readlines():
print(line, end = '''')
Pero no puedo saber de antemano si
prog.out
requerirá la entrada del usuario o no ...
Estoy buscando una forma sólida de ejecutar
prog.out
y dejar que el usuario interactúe con él durante el tiempo que sea necesario.
¿Hay alguna indicación cuando
prog.out
espera entrada?
EDITAR
Bien, experimenté un poco y descubrí que cualquier intento de leer () desde el canal se bloqueará, siempre que no haya salido
prog.out
, pero
prog.out
no puede salir mientras no se haya proporcionado con entrada ...
¿Cómo es que no puedo leer los bytes que ya fueron enviados por
prog.out
incluso cuando aún no está terminado?
Realmente me encantaría simular al usuario como si él o ella interactúen directamente con
prog.out
...
Hay una biblioteca construida sobre Paramiko que quizás sea más adecuada para sus necesidades.
Estoy hablando de la tela python (de la cual no tengo asociación)
Fabric es una biblioteca de Python (2.5-2.7) y una herramienta de línea de comandos para simplificar el uso de SSH para la implementación de aplicaciones o tareas de administración de sistemas.
Proporciona un conjunto básico de operaciones para ejecutar comandos de shell locales o remotos (normalmente o mediante sudo) y cargar / descargar archivos, así como funciones auxiliares, como solicitar al usuario en ejecución que ingrese o cancelar la ejecución.
Si he entendido su requisito correctamente, su código podría verse así.
from fabric.api import run
@task
def run_a_out()
run(''echo "some input for a.out" | ./a.out'')
Y ejecutarías el programa remoto con
fab --hosts=someserver run_a_out
Si desea controlar dinámicamente lo que se pasa a a.out, puede agregar un parámetro a
run_a_out
() y pasarlo desde la línea de comandos.
En resumen, Fabric proporciona una API de nivel superior para paramiko con la mayor parte de su complejidad oculta.