Search code examples
python-2.xexpectpexpect

How to prevent pexpect from echoing the password?


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.
#

Solution

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

    # cat foo.py
    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()
    
    # python2 foo.py
    foo@localhost's password:
    bash-5.1$ exit
    exit
    Connection to localhost closed.
    
    # python3 foo.py
    foo@localhost's password:
    bash-5.1$ exit
    exit
    Connection to localhost closed.