Reputation: 21269
Using twisted.conch
, I'm working with the following SSHChannel
implementation, which is fed a command to run when instantiated:
class CommandChannel(channel.SSHChannel):
name = 'session'
def __init__(self, command, *args, **kwargs):
channel.SSHChannel.__init__(self, *args, **kwargs)
self.command = command
def channelOpen(self, data):
d = self.conn.sendRequest(
self, 'exec', common.NS(self.command), wantReply=True)
d.addCallback(self._gotResponse)
def _gotResponse(self, _):
self.conn.sendEOF(self)
self.loseConnection()
def dataReceived(self, data):
log.msg('dataReceived: data=%r' % data)
def extReceived(self, dataType, data):
log.msg('extReceived: dataType=%r, data=%r' % (dataType, data))
def closed(self):
reactor.stop()
To this I'm feeding a shell command that should be returning some sort of exit status. Can I read what that exit status is? I had hoped extReceived
might be my way in, but it doesn't look like it.
In my logs I see this, which seems like it should be a hint where to look, but I'm not sure how to follow said hint:
2013-04-05 10:39:37-0400 [SSHChannel session (0) on SSHService ssh-connection
on CommandTransport,client] unhandled request for exit-status
Upvotes: 2
Views: 554
Reputation: 48335
There are two extra callbacks you might want to implement for this. These are callbacks on the channel, so you're pretty close already.
The first is request_exit_status
. Once you implement this, Conch will no longer log that the exit-status
request is unhandled. Here's an example implementation:
def request_exit_status(self, data):
"""
When the server sends the command's exit status, record it for later
delivery to the protocol.
@param data: The network-order four byte representation of the exit
status of the command.
@type data: L{bytes}
"""
(status,) = unpack('>L', data)
if status != 0:
self._reason = ProcessTerminated(status, None, None)
The second is request_exit_signal
. exit-signal
is sent instead of exit-status
if the command is terminated by a signal. Here's an example implementation:
def request_exit_signal(self, data):
"""
When the server sends the command's exit status, record it for later
delivery to the protocol.
@param data: The network-order four byte representation of the exit
signal of the command.
@type data: L{bytes}
"""
(signal,) = unpack('>L', data)
self._reason = ProcessTerminated(None, signal, None)
The general pattern here is that when SSHChannel
receives a request for foo it will try to call request_foo
with the bytes making up the request.
Upvotes: 4