अनुवर्ती - खुशी से, नीचे उल्लिखित टिकट अब हल हो गया है। सरल एपीआई ट्विस्ट की अगली रिलीज में शामिल किया जाएगा। मूल उत्तर अभी भी कॉन्च का उपयोग करने का एक वैध तरीका है और क्या हो रहा है, इसके बारे में कुछ रोचक विवरण बता सकता है, लेकिन ट्विस्ट 13.1 और इससे, यदि आप केवल एक कमांड चलाने के लिए और I/O, this simpler interface will work को संभालना चाहते हैं।
कॉन्च क्लाइंट एपीआई का उपयोग करके एसएसएच पर कमांड निष्पादित करने के लिए दुर्भाग्य से बड़ी मात्रा में कोड लेता है। कॉंच आपको कई अलग-अलग परतों से निपटने में मदद करता है, भले ही आप समझदार उबाऊ डिफ़ॉल्ट व्यवहार चाहते हों। हालांकि, यह निश्चित रूप से संभव है।
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()
कुछ बातें इसके बारे में गौर करने योग्य:
- यह मुड़ 10.1 में शुरू की गई नई endpoint API का उपयोग करता यहाँ कुछ कोड है जो मैं समाप्त करने और मुड़ में जोड़ने के लिए इस मामले को आसान बनाने के अर्थ किया गया है । यह सीधे
reactor.connectTCP
पर करना संभव है, लेकिन मैंने इसे और अधिक उपयोगी बनाने के लिए एक एंडपॉइंट के रूप में किया; एंडपॉइंट्स को कोड के बिना आसानी से बदला जा सकता है जो वास्तव में एक कनेक्शन जानने के लिए पूछता है।
- यह कोई होस्ट कुंजी सत्यापन बिल्कुल नहीं है!
_CommandTransport.verifyHostKey
वह जगह है जहां आप इसे लागू करेंगे। कुछ संकेतों के लिए आप किस प्रकार की चीजें करना चाहते हैं, इसके लिए twisted/conch/client/default.py
पर एक नज़र डालें।
- यह दूरस्थ उपयोगकर्ता नाम होने के लिए
$USER
लेता है, जिसे आप पैरामीटर बनना चाहते हैं।
- यह शायद कुंजी प्रमाणीकरण के साथ ही काम करता है। यदि आप पासवर्ड प्रमाणीकरण सक्षम करना चाहते हैं, तो आपको शायद कुछ करने के लिए
SSHUserAuthClient
उपclass करना होगा और getPassword
ओवरराइड करना होगा।
- लगभग सभी SSH और शंख की परतों के यहां दिखाई दे रहे हैं:
_CommandTransport
नीचे, एक सादे पुराने प्रोटोकॉल SSH परिवहन प्रोटोकॉल लागू करता है। यह एक बनाता है ...
_CommandConnection
जो प्रोटोकॉल के एसएसएच कनेक्शन वार्ता भागों को लागू करता है। एक बार यह पूरा हो जाने पर, ...
_CommandChannel
का उपयोग नए खुले एसएसएच चैनल से बात करने के लिए किया जाता है। _CommandChannel
आपके आदेश को लॉन्च करने के लिए वास्तविक निष्पादन करता है। एक बार चैनल खोला जाने के बाद यह एक उदाहरण बनाता है ...
StdoutEcho
, या जो भी अन्य प्रोटोकॉल आप आपूर्ति करते हैं। यह प्रोटोकॉल आपके द्वारा निष्पादित आदेश से आउटपुट प्राप्त करेगा, और कमांड के stdin पर लिख सकता है।
कम कोड के साथ इस समर्थन पर मुड़ में प्रगति के लिए http://twistedmatrix.com/trac/ticket/4698 देखें।
धन्यवाद बहुत बहुत धन्यवाद! इसने मुझे वास्तव में अजीब मारा क्योंकि, जैसा कि आपने सही तरीके से उल्लेख किया है, इस छोटी सी चीज के सरल, आउट-ऑफ-बॉक्स समाधान होना चाहिए। खुशी है कि उस दिशा में पहले से ही काम कर रहा है। तत्काल प्रतिक्रिया के लिए फिर से धन्यवाद। –