Jef*_*ose 12 python ssh twisted
我有一个扭曲的应用程序,现在需要监视在几个盒子上运行的进程.我手动做的方式是'ssh和ps',现在我想要扭曲的应用程序.我有2个选择.
使用paramiko或利用的力量twisted.conch
我真的想用,twisted.conch但我的研究让我相信它主要用于创建SSHServers和SSHClients.但是我的要求很简单remoteExecute(some_cmd)
我能够弄清楚如何使用paramiko但我不想坚持paramiko我的扭曲的应用程序,然后再看看如何使用twisted.conch
twisted关于如何remote_cmds使用ssh 运行的代码片段将受到高度赞赏.谢谢.
Jea*_*one 16
跟进 - 很高兴,我在下面引用的票现已解决.更简单的API将包含在Twisted的下一个版本中.原始答案仍然是使用Conch的有效方式,并且可能会显示一些有关正在发生的事情的有趣细节,但是从Twisted 13.1开始,如果您只想运行命令并处理它的I/O,这个更简单的界面将起作用.
遗憾的是,使用Conch客户端API在SSH上执行命令需要大量代码.Conch让你处理很多不同的层次,即使你只是想要明智无聊的默认行为.但是,这当然是可能的.这里有一些代码,我一直想完成并添加到Twisted以简化这种情况:
import sys, os
from zope.interface import implements
from twisted.python.failure import Failure
from twisted.python.log import err
from twisted.internet.error import ConnectionDone
from twisted.internet.defer import Deferred, succeed, setDebugging
from twisted.internet.interfaces import IStreamClientEndpoint
from twisted.internet.protocol import Factory, Protocol
from twisted.conch.ssh.common import NS
from twisted.conch.ssh.channel import SSHChannel
from twisted.conch.ssh.transport import SSHClientTransport
from twisted.conch.ssh.connection import SSHConnection
from twisted.conch.client.default import SSHUserAuthClient
from twisted.conch.client.options import ConchOptions
# setDebugging(True)
class _CommandTransport(SSHClientTransport):
_secured = False
def verifyHostKey(self, hostKey, fingerprint):
return succeed(True)
def connectionSecure(self):
self._secured = True
command = _CommandConnection(
self.factory.command,
self.factory.commandProtocolFactory,
self.factory.commandConnected)
userauth = SSHUserAuthClient(
os.environ['USER'], ConchOptions(), command)
self.requestService(userauth)
def connectionLost(self, reason):
if not self._secured:
self.factory.commandConnected.errback(reason)
class _CommandConnection(SSHConnection):
def __init__(self, command, protocolFactory, commandConnected):
SSHConnection.__init__(self)
self._command = command
self._protocolFactory = protocolFactory
self._commandConnected = commandConnected
def serviceStarted(self):
channel = _CommandChannel(
self._command, self._protocolFactory, self._commandConnected)
self.openChannel(channel)
class _CommandChannel(SSHChannel):
name = 'session'
def __init__(self, command, protocolFactory, commandConnected):
SSHChannel.__init__(self)
self._command = command
self._protocolFactory = protocolFactory
self._commandConnected = commandConnected
def openFailed(self, reason):
self._commandConnected.errback(reason)
def channelOpen(self, ignored):
self.conn.sendRequest(self, 'exec', NS(self._command))
self._protocol = self._protocolFactory.buildProtocol(None)
self._protocol.makeConnection(self)
def dataReceived(self, bytes):
self._protocol.dataReceived(bytes)
def closed(self):
self._protocol.connectionLost(
Failure(ConnectionDone("ssh channel closed")))
class SSHCommandClientEndpoint(object):
implements(IStreamClientEndpoint)
def __init__(self, command, sshServer):
self._command = command
self._sshServer = sshServer
def connect(self, protocolFactory):
factory = Factory()
factory.protocol = _CommandTransport
factory.command = self._command
factory.commandProtocolFactory = protocolFactory
factory.commandConnected = Deferred()
d = self._sshServer.connect(factory)
d.addErrback(factory.commandConnected.errback)
return factory.commandConnected
class StdoutEcho(Protocol):
def dataReceived(self, bytes):
sys.stdout.write(bytes)
sys.stdout.flush()
def connectionLost(self, reason):
self.factory.finished.callback(None)
def copyToStdout(endpoint):
echoFactory = Factory()
echoFactory.protocol = StdoutEcho
echoFactory.finished = Deferred()
d = endpoint.connect(echoFactory)
d.addErrback(echoFactory.finished.errback)
return echoFactory.finished
def main():
from twisted.python.log import startLogging
from twisted.internet import reactor
from twisted.internet.endpoints import TCP4ClientEndpoint
# startLogging(sys.stdout)
sshServer = TCP4ClientEndpoint(reactor, "localhost", 22)
commandEndpoint = SSHCommandClientEndpoint("/bin/ls", sshServer)
d = copyToStdout(commandEndpoint)
d.addErrback(err, "ssh command / copy to stdout failed")
d.addCallback(lambda ignored: reactor.stop())
reactor.run()
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
有些事情需要注意:
reactor.connectTCP,但我将其作为端点使其更有用; 端点可以轻松交换,而无需实际请求连接的代码._CommandTransport.verifyHostKey是你实现它的地方.看看twisted/conch/client/default.py有关您可能想要做什么事情的一些提示.$USER是远程用户名,您可能希望将其作为参数.SSHUserAuthClient和覆盖getPassword以执行某些操作._CommandTransport在底部,是一个实现SSH传输协议的普通旧协议.它创造了......_CommandConnection它实现协议的SSH连接协商部分.一旦完成,..._CommandChannel用于与新打开的SSH通道通信. _CommandChannel做实际的exec来启动你的命令.打开频道后,它会创建一个......的实例StdoutEcho或者你提供的任何其他协议.该协议将从您执行的命令获得输出,并可以写入命令的stdin.请参阅http://twistedmatrix.com/trac/ticket/4698,了解使用较少代码支持此功能的Twisted进度.
| 归档时间: |
|
| 查看次数: |
7016 次 |
| 最近记录: |