tutorial invoke_shell installing example como python ssh paramiko

invoke_shell - python ssh paramiko tutorial



Anidado sesiĆ³n SSH con Paramiko (5)

Aquí hay un pequeño ejemplo que usa solo paramiko (y reenvío de puertos):

import paramiko as ssh class SSHTool(): def __init__(self, host, user, auth, via=None, via_user=None, via_auth=None): if via: t0 = ssh.Transport(via) t0.start_client() t0.auth_password(via_user, via_auth) # setup forwarding from 127.0.0.1:<free_random_port> to |host| channel = t0.open_channel(''direct-tcpip'', host, (''127.0.0.1'', 0)) self.transport = ssh.Transport(channel) else: self.transport = ssh.Transport(host) self.transport.start_client() self.transport.auth_password(user, auth) def run(self, cmd): ch = self.transport.open_session() ch.set_combine_stderr(True) ch.exec_command(cmd) retcode = ch.recv_exit_status() buf = '''' while ch.recv_ready(): buf += ch.recv(1024) return (buf, retcode) # The example below is equivalent to # $ ssh 10.10.10.10 ssh 192.168.1.1 uname -a # The code above works as if these 2 commands were executed: # $ ssh -L <free_random_port>:192.168.1.1:22 10.10.10.10 # $ ssh 127.0.0.1:<free_random_port> uname -a host = (''192.168.1.1'', 22) via_host = (''10.10.10.10'', 22) ssht = SSHTool(host, ''user1'', ''pass1'', via=via_host, via_user=''user2'', via_auth=''pass2'') print ssht.run(''uname -a'')

Estoy reescribiendo un script de Bash que escribí en Python. El quid de la secuencia de comandos era

ssh -t first.com "ssh second.com very_remote_command"

Tengo un problema con la autenticación anidada con paramiko. No pude encontrar ningún ejemplo relacionado con mi situación exacta, pero pude encontrar ejemplos con sudo en un host remoto.

El primer método escribe en stdin

ssh.connect(''127.0.0.1'', username=''jesse'', password=''lol'') stdin, stdout, stderr = ssh.exec_command("sudo dmesg") stdin.write(''lol/n'') stdin.flush()

El segundo crea un canal y usa el envío y recv tipo socket.

Pude hacer que stdin.write trabajara con sudo , pero no funciona con ssh en el host remoto.

import paramiko ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(''first.com'', username=''luser'', password=''secret'') stdin, stdout, stderr = ssh.exec_command(''ssh [email protected]'') stdin.write(''secret'') stdin.flush() print ''---- out ----'' print stdout.readlines() print ''---- error ----'' print stderr.readlines() ssh.close()

...huellas dactilares...

---- out ---- [] ---- error ---- [''Pseudo-terminal will not be allocated because stdin is not a terminal./r/n'', ''Permission denied, please try again./r/n'', ''Permission denied, please try again./r/n'', ''Permission denied (publickey,password,keyboard-interactive)./r/n'']

El error pseudo-terminal me recordó el indicador -t en mi comando original, así que cambié al segundo método, usando un canal. En lugar de ssh.exec_command y más tarde, tengo:

t = ssh.get_transport() chan = t.open_session() chan.get_pty() print ''---- send ssh cmd ----'' print chan.send(''ssh [email protected]'') print ''---- recv ----'' print chan.recv(9999) chan = t.open_session() print ''---- send password ----'' print chan.send(''secret'') print ''---- recv ----'' print chan.recv(9999)

... pero imprime ''---- send ssh cmd ----'' y simplemente se cuelga hasta que mato el proceso.

Soy nuevo en Python y no tengo conocimientos sobre redes. En el primer caso, ¿por qué el envío de la contraseña funciona con sudo pero no con ssh ? ¿Son las indicaciones diferentes? ¿Paramiko es incluso la biblioteca adecuada para esto?


La respuesta de Sinas funciona bien pero no proporcionó toda la salida de comandos muy largos para mí. Sin embargo, usar chan.makefile () me permite recuperar todo el resultado.

El siguiente funciona en un sistema que requiere tty y también solicita sudo password

ssh = paramiko.SSHClient() ssh.load_system_host_keys() ssh.set_missing_host_key_policy(paramiko.WarningPolicy()) ssh.connect("10.10.10.1", 22, "user", "password") chan=ssh.get_transport().open_session() chan.get_pty() f = chan.makefile() chan.exec_command("sudo dmesg") chan.send("password/n") print f.read() ssh.close()


Logré encontrar una solución, pero requiere un poco de trabajo manual. Si alguien tiene una mejor solución, por favor dígame.

ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(''first.com'', username=''luser'', password=''secret'') chan = ssh.invoke_shell() # Ssh and wait for the password prompt. chan.send(''ssh second.com/n'') buff = '''' while not buff.endswith(''/'s password: ''): resp = chan.recv(9999) buff += resp # Send the password and wait for a prompt. chan.send(''secret/n'') buff = '''' while not buff.endswith(''some-prompt$ ''): resp = chan.recv(9999) buff += resp # Execute whatever command and wait for a prompt again. chan.send(''ls/n'') buff = '''' while not buff.endswith(''some-prompt$ ''): resp = chan.recv(9999) buff += resp # Now buff has the data I need. print ''buff'', buff ssh.close()

Lo que hay que notar es que en lugar de esto

t = ssh.get_transport() chan = t.open_session() chan.get_pty()

...Tu quieres esto

chan = ssh.invoke_shell()

Me recuerda a cuando traté de escribir un guión de TradeWars cuando era un niño y renuncié a la codificación durante diez años. :)



Puede crear una conexión ssh usando el canal de otra conexión ssh. Mira here para más detalles.