Question

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
Était-ce utile?

La solution

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top