2011-01-06 13 views
12

मेरे पास एक मुड़ता हुआ एप्लिकेशन है जिसे अब कई बक्से पर चल रही प्रक्रियाओं की निगरानी करने की आवश्यकता है। जिस तरह से मैं मैन्युअल रूप से करता हूं वह 'एसएसएच और पीएस' है, अब मैं अपने मुड़ने वाले आवेदन को करना चाहता हूं। मेरे पास 2 विकल्प हैं।मुड़ते हुए एसएसएच के माध्यम से रिमोट कमांड चलाने के लिए सबसे अच्छा तरीका?

उपयोग paramiko या की twisted.conch

मैं वास्तव में twisted.conch उपयोग करना चाहते हैं शक्ति का लाभ उठाने लेकिन मेरे अनुसंधान मुझे नेतृत्व कि इसके मुख्य रूप से SSHServers और SSHClients पैदा करने का इरादा विश्वास करने के लिए। हालांकि मेरी आवश्यकता एक सरल remoteExecute(some_cmd)

है मैं कैसे paramiko का उपयोग कर ऐसा करने के लिए यह पता लगाने में सक्षम था, लेकिन मैं ऐसा करने के तरीके twisted.conch

कोड का उपयोग कर के टुकड़े का उपयोग कर को देख पहले मेरी मुड़ अनुप्रयोग में paramiko छड़ी नहीं चाहता था एसएसएच का उपयोग करके को चलाने के तरीके पर twisted अत्यधिक सराहना की जाएगी। धन्यवाद।

उत्तर

16

अनुवर्ती - खुशी से, नीचे उल्लिखित टिकट अब हल हो गया है। सरल एपीआई ट्विस्ट की अगली रिलीज में शामिल किया जाएगा। मूल उत्तर अभी भी कॉन्च का उपयोग करने का एक वैध तरीका है और क्या हो रहा है, इसके बारे में कुछ रोचक विवरण बता सकता है, लेकिन ट्विस्ट 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 देखें।

+0

धन्यवाद बहुत बहुत धन्यवाद! इसने मुझे वास्तव में अजीब मारा क्योंकि, जैसा कि आपने सही तरीके से उल्लेख किया है, इस छोटी सी चीज के सरल, आउट-ऑफ-बॉक्स समाधान होना चाहिए। खुशी है कि उस दिशा में पहले से ही काम कर रहा है। तत्काल प्रतिक्रिया के लिए फिर से धन्यवाद। –

संबंधित मुद्दे