6

By default, pexpect.spawn() would not output anything. But when I specify logfile=sys.stdout it'll also echo the password (e.g. for ssh). So how can I see the real time interaction with the spawned process without the password being echoed (just like the Expect (the Tcl extension) does)?

pexepct example:

# cat expect.py
import pexpect, sys

logfile = sys.stdout if len(sys.argv) == 2 else None

ssh = pexpect.spawn('ssh foo@localhost', logfile=logfile)
ssh.delaybeforesend = 1
ssh.expect('assword:')
ssh.sendline('123456')

ssh.expect('\r\n\\$')
ssh.sendline('exit')
ssh.expect(pexpect.EOF)
ssh.wait()
# python expect.py                 <-- no output
# python expect.py stdout
foo@localhost's password: 123456   <-- the password is visible
Last login: Tue Mar 22 10:32:49 2016 from localhost
$ exit
exit
Connection to localhost closed.
#

Expect example:

# cat ssh.exp
spawn ssh foo@localhost
expect assword:
send "123456\r"
expect {\$}
send "exit\r"
expect eof
wait
# expect ssh.exp
spawn ssh foo@localhost
foo@localhost's password:          <-- the password is invisible
Last login: Tue Mar 22 10:45:03 2016 from localhost
$ exit
Connection to localhost closed.
#
pynexj
  • 19,215
  • 5
  • 38
  • 56
  • Might be related? http://pexpect.readthedocs.org/en/stable/commonissues.html#timing-issue-with-send-and-sendline – Phillip Mar 22 '16 at 08:23
  • Just tried that but it does not work for me. Also added that to my example code. – pynexj Mar 22 '16 at 09:02
  • 3
    `logfile` logs things going both ways. You can use `logfile_read` to capture only what it reads from the child process and not what you send. This isn't a constructor parameter, but you can set `ssh.logfile_read` after you create it. – Thomas K Mar 22 '16 at 11:11
  • @ThomasK - Thanks. This is a partial solution. For most of time I'd like to record both commands and commands' outputs. But you remind me of a workaround: use `logfile_read` before sending the password and `logfile` after sending the password. – pynexj Mar 22 '16 at 15:32
  • Perhaps you need [`sendecho`](http://pexpect.sourceforge.net/pexpect.html#spawn-setecho) – glenn jackman Mar 22 '16 at 15:54
  • 3
    Pexpect does not see a distinction between passwords and commands - it's just sending some bytes to a pty. However, normally when you send a command, the pty echoes it back to you (this is how you see it when you type in a terminal). This is turned off for passwords, so that you don't see them. So `logfile_read` will typically contain commands. – Thomas K Mar 22 '16 at 17:14

1 Answers1

5

Just to make the question answered. The credit goes to Thomas K. See his comments under the question for more details.

[STEP 101] # cat foo.py
#!/usr/bin/env python3

import pexpect, sys

spawn = pexpect.spawnu if sys.version_info[0] >= 3 else pexpect.spawn
ssh = spawn('ssh -t foo@localhost bash --noprofile --norc')
ssh.logfile_read = sys.stdout

ssh.expect('assword:')
ssh.sendline('123456')

ssh.expect('bash-[.0-9]+[$#]')
ssh.sendline('exit')
ssh.expect(pexpect.EOF)
ssh.wait()
[STEP 102] #
[STEP 103] # python2 foo.py
foo@localhost's password:
bash-5.1$ exit
exit
Connection to localhost closed.
[STEP 104] #
[STEP 105] # python3 foo.py
foo@localhost's password:
bash-5.1$ exit
exit
Connection to localhost closed.
[STEP 106] #
pynexj
  • 19,215
  • 5
  • 38
  • 56