pexpect setecho not working

abarik picture abarik · Nov 20, 2012 · Viewed 7.2k times · Source

I am trying to telnet to Cisco Router and give commands using pexpect. Its working, but the sendline() repeats in the output. even after using setecho to False. Code is:

'''
Created on Nov 19, 2012

@author: Amit Barik
'''

import pexpect

hostname = 'hostname'
login_cmd = 'telnet ' + hostname + '.net'
username = 'username'
password = 'pwd'
prompt = hostname + '#'

p = pexpect.spawn(login_cmd)
p.setecho(False)
p.logfile = open('Log.log', 'w+')

p.expect('Username:')
print '1',repr(p.before)

p.sendline(username)
p.expect('Password:')
print '2',repr(p.before)

p.sendline(password)
p.expect(prompt)
print '3',repr(p.before)

cmd = 'show clock'
p.sendline(cmd)
p.expect(prompt)
print 'Output for {0}'.format(cmd), repr(p.before)

Output is:

# On Python Console
Output for show clock 'show clock\r\n00:16:40.692 UTC Tue Nov 20 2012\r\n'

# On Log File
Username: username
username
Password: pwd

My Cisco Banner

hostname#show clock
show clock
00:16:40.692 UTC Tue Nov 20 2012
hostname#

Answer

ne_denver picture ne_denver · Nov 25, 2014

I had the same problem when interacting with network devices (not *nix terminals).

Pexpect has 3 logging methods (1. logfile_send(), 2. logfile_read() 3. logfile()).

Using the output example from the original poster above, here is what the output looks like for each logging method:

1.) p.logfile() will log the network device's echo'd output AND it will log the text sent using send() & sendline(). This is what the original poster did NOT want to happen.

In script:

p.logfile = open('Log.log', 'w+')

Output:

# On Python Console
Output for show clock 'show clock\r\n00:16:40.692 UTC Tue Nov 20 2012\r\n'

# On Log File
Username: username   #This is the `sendline()` output
username             #This is echo from the network device
Password: pwd        #This is `sendline()` output
                     #Notice, pwd only echo's once.  There is no echo from the network device since it doesn't echo passwords

My Cisco Banner

hostname#show clock  #This is the `sendline()` output
show clock           #This is echo from the network device
00:16:40.692 UTC Tue Nov 20 2012
hostname#

2.) p.logfile_read() will ONLY log the network device's echo'd output. It will not log p.sendline() characters. This is the desired result the original poster was looking for.

In script:

p.logfile_read = open('Log.log', 'w+')

Output:

# On Python Console
Output for show clock 'show clock\r\n00:16:40.692 UTC Tue Nov 20 2012\r\n'

# On Log File
Username: username   #This is echo from the network device
Password:            #There is no echo from the network device since it doesn't echo passwords

My Cisco Banner

hostname#show clock  #This is echo from the network device
00:16:40.692 UTC Tue Nov 20 2012
hostname#

3.) p.logfile_sendwill only send the p.sendline() characters to the log, which probably isn't very useful in most cases. I'll skip the example, since everyone probably has the idea by now.

So, using logfile_read() will fix the issue with passwords showing in the log output when interacting with network devices. This will also fix the issue of pexpect showing double echo's in log output, which I've seen a few people ask questions about online as well.

Regarding setecho(False), per the pexpect docs, this sets the "terminal echo mode on or off". That function isn't meant to surpress sendline() output as people were hoping (including myself). And since I was dealing with a network device (cisco, juniper, mrv, etc), trying to turn off tty echo wasn't useful.

Hope this helps someone out in the future.