I've got a Twisted Conch/SSH script that I inherited which I'm using to
run commands remotely on some servers. I'd like to add a timeout for
servers that are down, etc (the script currently hangs on these), but
I'm not sure where to add that functionality.<br>
<br>Any help would be appreciated.<br>Thanks,<br>-Ray<br><br>=========Script Follows=========<br><br>#!/usr/bin/python<br><br>from twisted.conch import error<br>from twisted.conch.ssh import transport, connection, keys, userauth, channel, common<br>
from twisted.internet import defer, protocol, reactor<br><br>#a class to store the data returned from the ssh client code<br>class SSHData():<br> data = ''<br><br>class ClientCommandTransport(<div id=":xg" class="ArwC7c ckChnd">
transport.SSHClientTransport):<br>
def __init__(self, username, password, command):<br> self.username = username<br> self.password = password<br> self.command = command<br><br> def verifyHostKey(self, pubKey, fingerprint):<br> # in a real app, you should verify that the fingerprint matches<br>
# the one you expected to get from this server<br> return defer.succeed(True)<br><br> def connectionSecure(self):<br> self.requestService(<br> PasswordAuth(self.username, self.password,<br> ClientConnection(self.command)))<br>
<br>class PasswordAuth(userauth.SSHUserAuthClient):<br> def __init__(self, user, password, connection):<br> userauth.SSHUserAuthClient.__init__(self, user, connection)<br> self.password = password<br><br> def getPassword(self, prompt=None):<br>
return defer.succeed(self.password)<br><br>class ClientConnection(connection.SSHConnection):<br> def __init__(self, cmd, *args, **kwargs):<br> connection.SSHConnection.__init__(self)<br> self.command = cmd<br>
<br> def serviceStarted(self):<br> self.openChannel(CommandChannel(self.command, conn=self))<br><br>class CommandChannel(channel.SSHChannel):<br> name = 'session'<br><br> def __init__(self, command, *args, **kwargs):<br>
channel.SSHChannel.__init__(self, *args, **kwargs)<br> self.command = command<br><br> def channelOpen(self, data):<br> self.conn.sendRequest(<br> self, 'exec', common.NS(self.command), wantReply=True).addCallback(<br>
self._gotResponse)<br><br> def _gotResponse(self, _):<br> self.conn.sendEOF(self)<br><br> def dataReceived(self, data):<br> SSHData.data = data<br><br> def closed(self):<br> reactor.stop()<br>
<br>class ClientCommandFactory(protocol.ClientFactory):<br> def __init__(self, username, password, command):<br> self.username = username<br> self.password = password<br> self.command = command<br> self.deferred = defer.Deferred()<br>
<br> def buildProtocol(self, addr):<br> protocol = ClientCommandTransport(<br> self.username, self.password, self.command)<br> return protocol<br><br>def testConnect(username, password, command, server):<br>
testFactory = ClientCommandFactory(username, password, command)<br> reactor.connectTCP(server, 22, testFactory)<br> return testFactory.deferred<br><br>def handleSuccess(result, port):<br> print "Connected to port %i" % port<br>
reactor.stop()<br><br>def handleFailure(failure, port):<br> print "Error connecting to port %i: %s" % (<br> port, failure.getErrorMessage())<br> reactor.stop()<br><br>if __name__ == "__main__":<br>
import sys, getpass<br><br> server = sys.argv[1]<br> command = sys.argv[2]<br> username = raw_input("Username: ")<br> password = getpass.getpass("Password: ")<br><br> connecting = testConnect(username, password, command, server)<br>
#connecting.addCallback(handleSuccess, server)<br> #connecting.addErrback(handleFailure, server)<br> connecting.setTimeout(1, handleError)<br> reactor.run()<br><br> print "The data I got back from the ssh client is " + SSHData.data</div>