¿Cómo hacer una conexión ssh con python?

¿Alguien puede recomendar algo para hacer una conexión ssh en python? Necesito que sea compatible con cualquier sistema operativo.

Ya he intentado pyssh solo para obtener un error con SIGCHLD, que he leído es porque Windows carece de esto. He intentado hacer funcionar a paramiko, pero he tenido errores entre paramiko y Crypto hasta el punto en que las últimas versiones de cada uno no funcionan juntas.

Python 2.6.1 actualmente en una máquina con Windows.

Tenga en cuenta que esto no funciona en Windows .
El módulo pxssh hace exactamente lo que quieres:
Por ejemplo, para ejecutar ‘ls -l’ e imprimir el resultado, debe hacer algo como eso:

from pexpect import pxssh s = pxssh.pxssh() if not s.login ('localhost', 'myusername', 'mypassword'): print "SSH session failed on login." print str(s) else: print "SSH session login successful" s.sendline ('ls -l') s.prompt() # match the prompt print s.before # print everything before the prompt. s.logout() 

Algunos enlaces:
Documentos de Pxssh: http://dsnra.jpl.nasa.gov/software/Python/site-packages/Contrib/pxssh.html
Pexpect (pxssh se basa en pexpect): http://pexpect.readthedocs.io/en/stable/

Twisted tiene soporte SSH: http://www.devshed.com/c/a/Python/SSH-with-Twisted/

El paquete twisted.conch agrega soporte SSH a Twisted. Este capítulo muestra cómo puede usar los módulos en twisted.conch para crear servidores y clientes SSH.

Configuración de un servidor SSH personalizado

La línea de comandos es una interfaz increíblemente eficiente para ciertas tareas. A los administradores de sistemas les encanta la capacidad de administrar aplicaciones escribiendo comandos sin tener que hacer clic en una interfaz gráfica de usuario. Un shell SSH es aún mejor, ya que es accesible desde cualquier lugar de Internet.

Puede usar twisted.conch para crear un servidor SSH que brinde acceso a un shell personalizado con los comandos que defina. Este shell incluso admitirá algunas características adicionales como el historial de comandos, para que pueda desplazarse por los comandos que ya ha escrito.

¿Cómo puedo hacer eso? Escribe una subclase de twisted.conch.recvline.HistoricRecvLine que implementa tu protocolo de shell. HistoricRecvLine es similar a twisted.protocols.basic.LineReceiver, pero con características de nivel superior para controlar el terminal.

Escribe una subclase de twisted.conch.recvline.HistoricRecvLine que implementa tu protocolo de shell. HistoricRecvLine es similar a twisted.protocols.basic.LineReceiver, pero con características de nivel superior para controlar el terminal.

Para que su shell esté disponible a través de SSH, necesita implementar algunas clases diferentes que twisted.conch necesita para construir un servidor SSH. Primero, necesita las clases de autenticación twisted.cred: un portal, verificadores de credenciales y un reino que devuelva avatares. Utilice twisted.conch.avatar.ConchUser como la clase base para su avatar. Su clase de avatar también debe implementar twisted.conch.interfaces.ISession, que incluye un método openShell en el que crea un protocolo para administrar la sesión interactiva del usuario. Finalmente, cree un objeto twisted.conch.ssh.factory.SSHFactory y establezca su atributo de portal a una instancia de su portal.

El ejemplo 10-1 muestra un servidor SSH personalizado que autentica a los usuarios por su nombre de usuario y contraseña. Le da a cada usuario un shell que proporciona varios comandos.

Ejemplo 10-1. sshserver.py

 from twisted.cred import portal, checkers, credentials from twisted.conch import error, avatar, recvline, interfaces as conchinterfaces from twisted.conch.ssh import factory, userauth, connection, keys, session, common from twisted.conch.insults import insults from twisted.application import service, internet from zope.interface import implements import os class SSHDemoProtocol(recvline.HistoricRecvLine): def __init__(self, user): self.user = user def connectionMade(self) : recvline.HistoricRecvLine.connectionMade(self) self.terminal.write("Welcome to my test SSH server.") self.terminal.nextLine() self.do_help() self.showPrompt() def showPrompt(self): self.terminal.write("$ ") def getCommandFunc(self, cmd): return getattr(self, 'do_' + cmd, None) def lineReceived(self, line): line = line.strip() if line: cmdAndArgs = line.split() cmd = cmdAndArgs[0] args = cmdAndArgs[1:] func = self.getCommandFunc(cmd) if func: try: func(*args) except Exception, e: self.terminal.write("Error: %s" % e) self.terminal.nextLine() else: self.terminal.write("No such command.") self.terminal.nextLine() self.showPrompt() def do_help(self, cmd=”): "Get help on a command. Usage: help command" if cmd: func = self.getCommandFunc(cmd) if func: self.terminal.write(func.__doc__) self.terminal.nextLine() return publicMethods = filter( lambda funcname: funcname.startswith('do_'), dir(self)) commands = [cmd.replace('do_', ”, 1) for cmd in publicMethods] self.terminal.write("Commands: " + " ".join(commands)) self.terminal.nextLine() def do_echo(self, *args): "Echo a string. Usage: echo my line of text" self.terminal.write(" ".join(args)) self.terminal.nextLine() def do_whoami(self): "Prints your user name. Usage: whoami" self.terminal.write(self.user.username) self.terminal.nextLine() def do_quit(self): "Ends your session. Usage: quit" self.terminal.write("Thanks for playing!") self.terminal.nextLine() self.terminal.loseConnection() def do_clear(self): "Clears the screen. Usage: clear" self.terminal.reset() class SSHDemoAvatar(avatar.ConchUser): implements(conchinterfaces.ISession) def __init__(self, username): avatar.ConchUser.__init__(self) self.username = username self.channelLookup.update({'session':session.SSHSession}) def openShell(self, protocol): serverProtocol = insults.ServerProtocol(SSHDemoProtocol, self) serverProtocol.makeConnection(protocol) protocol.makeConnection(session.wrapProtocol(serverProtocol)) def getPty(self, terminal, windowSize, attrs): return None def execCommand(self, protocol, cmd): raise NotImplementedError def closed(self): pass class SSHDemoRealm: implements(portal.IRealm) def requestAvatar(self, avatarId, mind, *interfaces): if conchinterfaces.IConchUser in interfaces: return interfaces[0], SSHDemoAvatar(avatarId), lambda: None else: raise Exception, "No supported interfaces found." def getRSAKeys(): if not (os.path.exists('public.key') and os.path.exists('private.key')): # generate a RSA keypair print "Generating RSA keypair…" from Crypto.PublicKey import RSA KEY_LENGTH = 1024 rsaKey = RSA.generate(KEY_LENGTH, common.entropy.get_bytes) publicKeyString = keys.makePublicKeyString(rsaKey) privateKeyString = keys.makePrivateKeyString(rsaKey) # save keys for next time file('public.key', 'w+b').write(publicKeyString) file('private.key', 'w+b').write(privateKeyString) print "done." else: publicKeyString = file('public.key').read() privateKeyString = file('private.key').read() return publicKeyString, privateKeyString if __name__ == "__main__": sshFactory = factory.SSHFactory() sshFactory.portal = portal.Portal(SSHDemoRealm()) users = {'admin': 'aaa', 'guest': 'bbb'} sshFactory.portal.registerChecker( checkers.InMemoryUsernamePasswordDatabaseDontUse(**users)) pubKeyString, privKeyString = getRSAKeys() sshFactory.publicKeys = { 'ssh-rsa': keys.getPublicKeyString(data=pubKeyString)} sshFactory.privateKeys = { 'ssh-rsa': keys.getPrivateKeyObject(data=privKeyString)} from twisted.internet import reactor reactor.listenTCP(2222, sshFactory) reactor.run() {mospagebreak title=Setting Up a Custom SSH Server continued} 

sshserver.py ejecutará un servidor SSH en el puerto 2222. Conéctese a este servidor con un cliente SSH utilizando el nombre de usuario admin y la contraseña aaa, e intente escribir algunos comandos:

 $ ssh admin@localhost -p 2222 admin@localhost's password: aaa >>> Welcome to my test SSH server. Commands: clear echo help quit whoami $ whoami admin $ help echo Echo a string. Usage: echo my line of text $ echo hello SSH world! hello SSH world! $ quit Connection to localhost closed.