[Twisted-Python] Conch: multiple commands
Phil Mayers
p.mayers at imperial.ac.uk
Thu Feb 9 18:33:37 MST 2006
Brendan Simon wrote:
>
> Maybe I just answered my own question. The sshd server runs "login" (or
> something) which in turn looks in /etc/passwd for the user and shell,
> and then invokes that shell (eg. bash). Is that the way it works? i.e.
> the ssh client only sends _one_ command and as far as it is concerned is
> only invoked one program and it doesn't care that the server has fired
> off many apps.
Correct
>
> If that's the case, then maybe I can invoke bash as my command, and just
> write data to the channel and grab the results ???
It might not be quite that simple. Bash and most shells expect to be
attached to a TTY with a VT emulation on top, to provide output,
prompting and so forth. To do it "correctly" you would need some kind of
TTY client attached to the channel that would present you with prompts.
That said for simple commands that don't cause any complex terminal
operations, it works fine. I've done it with SSH logins into firewalls
and routers as an alternative to the (frankly POS) "expect" approach. I
basically did something like this (though I was talking to an SSH
process rathern than Twisted's SSH support as I needed SSHv1 - modify as
appropriate):
class sshSession(TheBases):
# match "[thing]$" or "[foo at bar]# "
PROMPT_RE = re.compile(r'[[][^]]+]. ')
def __init__(self):
self.stdout = stdout
self.stdout_lines = []
self.stderr = stderr
self.stdin = []
self.atprompt = False
self.deferred = None
def sendCmd(cmd):
"""Queue up the command - returns a deferred callbacked with the
command stdout or errbacked with stderr if any"""
d = defer.Deferred()
self.stdin.append((d, cmd))
if self.atprompt:
self.atprompt = False
self.deferred, cmd = self.stdin.pop(0)
self.transport.write(cmd+'\r')
return d
def errReceived(self, data):
self.stderr += data
def outReceived(self, data):
line = None
# accumulate stdout
self.stdout += data
while self.stdout:
# look for an end of line in the buffer
pos = self.stdout.find('\r\n')
if pos==-1:
break
line = self.stdout[:pos]
self.stdout = self.stdout[pos+2:]
self.stdout_lines.append(line)
# ok we've looked at all the complete lines - is whats
# left in the buffer the prompt?
if self.PROMPT_RE.match(self.stdout):
if self.deferred:
if self.stderr:
self.deferred.errback(self.stderr)
self.deferred = None
if self.stdin:
# there's another command waiting
self.atprompt = False
self.deferred, cmd = self.stdin.pop(0)
self.transport.write(cmd+'\r\n')
else:
self.atprompt = True
...and hopefully that makes sense!
> Is that good or bad???
>
> Thanks,
> Brendan.
>
>
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
More information about the Twisted-Python
mailing list