python ssh paramiko
Realizar comandos sobre ssh con Python (7)
¿Has echado un vistazo a Fabric ? Te permite hacer todo tipo de cosas remotas a través de SSH usando Python.
Estoy escribiendo un script para automatizar algunos comandos de línea de comando en Python. En este momento estoy haciendo llamadas así:
cmd = "some unix command"
retcode = subprocess.call(cmd,shell=True)
Sin embargo, necesito ejecutar algunos comandos en una máquina remota. Manualmente, me conectaba usando ssh y luego ejecutaba los comandos. ¿Cómo automatizaría esto en Python? Necesito iniciar sesión con una contraseña (conocida) para la máquina remota, así que no puedo usar cmd = ssh user@remotehost
, me pregunto si hay un módulo que debería usar.
Eche un vistazo a spurplus
, un envoltorio que desarrollamos alrededor de un spur
que proporciona anotaciones tipo y algunos trucos menores (reconectando SFTP, md5, etc. ): https://pypi.org/project/spurplus/
Encontré el paramiko demasiado bajo, y Fabric no es especialmente adecuado para ser utilizado como biblioteca, así que armé mi propia biblioteca llamada spur que usa paramiko para implementar una interfaz ligeramente más agradable:
import spur
shell = spur.SshShell(hostname="localhost", username="bob", password="password1")
result = shell.run(["echo", "-n", "hello"])
print result.output # prints hello
Si necesita ejecutar dentro de un shell:
shell.run(["sh", "-c", "echo -n hello"])
O simplemente puede usar commands.getstatusoutput :
commands.getstatusoutput("ssh machine 1 ''your script''")
Lo usé extensamente y funciona muy bien.
En Python 2.6+, use subprocess.check_output
.
Te referiré a paramiko
ver esta pregunta
ssh = paramiko.SSHClient()
ssh.connect(server, username=username, password=password)
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(cmd_to_execute)
Todos ya han declarado (recomendado) el uso de paramiko y solo estoy compartiendo un código de python (se puede decir API) que te permitirá ejecutar varios comandos de una vez.
para ejecutar comandos en el uso de diferentes nodos: Commands().run_cmd(host_ip, list_of_commands)
Verá una TODO, que he guardado para detener la ejecución si alguno de los comandos no se ejecuta, no sé cómo hacerlo. por favor comparte tu conocimiento
#!/usr/bin/python
import os
import sys
import select
import paramiko
import time
class Commands:
def __init__(self, retry_time=0):
self.retry_time = retry_time
pass
def run_cmd(self, host_ip, cmd_list):
i = 0
while True:
# print("Trying to connect to %s (%i/%i)" % (self.host, i, self.retry_time))
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host_ip)
break
except paramiko.AuthenticationException:
print("Authentication failed when connecting to %s" % host_ip)
sys.exit(1)
except:
print("Could not SSH to %s, waiting for it to start" % host_ip)
i += 1
time.sleep(2)
# If we could not connect within time limit
if i >= self.retry_time:
print("Could not connect to %s. Giving up" % host_ip)
sys.exit(1)
# After connection is successful
# Send the command
for command in cmd_list:
# print command
print "> " + command
# execute commands
stdin, stdout, stderr = ssh.exec_command(command)
# TODO() : if an error is thrown, stop further rules and revert back changes
# Wait for the command to terminate
while not stdout.channel.exit_status_ready():
# Only print data if there is data to read in the channel
if stdout.channel.recv_ready():
rl, wl, xl = select.select([ stdout.channel ], [ ], [ ], 0.0)
if len(rl) > 0:
tmp = stdout.channel.recv(1024)
output = tmp.decode()
print output
# Close SSH connection
ssh.close()
return
def main(args=None):
if args is None:
print "arguments expected"
else:
# args = {''<ip_address>'', <list_of_commands>}
mytest = Commands()
mytest.run_cmd(host_ip=args[0], cmd_list=args[1])
return
if __name__ == "__main__":
main(sys.argv[1:])
¡Gracias!