Может ли кто-нибудь порекомендовать что-то для создания ssh-соединения в python?
Мне нужно, чтобы он был совместим с любой ОС.
Я уже пробовал pyssh только для получения ошибки с SIGCHLD, которую я прочитал, потому что Windows этого не хватает.
Я попытался заставить paramiko работать, но у меня были ошибки между paramiko и Crypto до такой степени, что последние версии каждого из них не будут работать вместе.
Python 2.6.1 в настоящее время на компьютере под управлением Windows.
Ответ 1
Модуль pxssh выполняет именно то, что вы хотите.
Например, чтобы запустить 'ls -l' и распечатать вывод, вам нужно сделать что-то вроде этого:
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()
Некоторые ссылки:
Pxssh docs: http://dsnra.jpl.nasa.gov/software/Python/site-packages/Contrib/pxssh.html
Pexpect (pxssh основан на pexpect): http://www.noah.org/wiki/pexpect
Ответ 2
У Twisted есть поддержка SSH: http://www.devshed.com/c/a/Python/SSH-with-Twisted/
В пакете twisted.conch добавлена поддержка SSH для Twisted. В этой главе показано, как вы можете использовать модули в twisted.conch для сборки серверов и клиентов SSH.
Настройка настраиваемого SSH-сервера
Командная строка - это невероятно эффективный интерфейс для определенных задач. Системным администраторам нравится управлять приложениями, введя команды без необходимости щелчка по графическому интерфейсу пользователя. Оболочка SSH еще лучше, так как она доступна из любого места в Интернете.
Вы можете использовать twisted.conch для создания SSH-сервера, который обеспечивает доступ к пользовательской оболочке с помощью команд, которые вы определяете. Эта оболочка будет поддерживать некоторые дополнительные функции, такие как история команд, чтобы вы могли прокручивать уже введенные команды.
Как мне это сделать? Напишите подкласс twisted.conch.recvline.HistoricRecvLine, который реализует ваш протокол оболочки. HistoricRecvLine похож на twisted.protocols.basic.LineReceiver, но с функциями более высокого уровня для управления терминалом.
Напишите подкласс twisted.conch.recvline.HistoricRecvLine, который реализует ваш протокол оболочки. HistoricRecvLine похож на twisted.protocols.basic.LineReceiver, но с функциями более высокого уровня для управления терминалом.
Чтобы сделать вашу оболочку доступной через SSH, вам нужно реализовать несколько разных классов, для которых twisted.conch необходимо построить SSH-сервер. Во-первых, вам нужны классы проверки подлинности twisted.cred: портал, учетные данные и область, возвращающая аватары. Используйте twisted.conch.avatar.ConchUser как базовый класс для вашего аватара. Ваш класс аватара также должен реализовать twisted.conch.interfaces.ISession, который включает метод openShell, в котором вы создаете протокол для управления интерактивным сеансом пользователей. Наконец, создайте объект twisted.conch.ssh.factory.SSHFactory и установите его атрибут портала в экземпляр вашего портала.
В примере 10-1 показан пользовательский SSH-сервер, который аутентифицирует пользователей по их имени и паролю. Он дает каждому пользователю оболочку, которая предоставляет несколько команд.
Пример 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 запустит SSH-сервер на порту 2222. Подключитесь к этому серверу с помощью SSH-клиента, используя имя пользователя admin и пароль aaa, и попробуйте ввести несколько команд:
$ ssh [email protected] -p 2222
[email protected]’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.