Python pexpect Help - Loop Back if Password Fails

1.6k views Asked by At

So I am pretty new to developing so I decided a good way to teach myself would be by creating a small script that configures Cisco switches/routers over SSH. Am a bit stuck on a loop though.

Basically the user has already SSH'd into the switch with username@ip_address and now they need to enter the password. What I need though is for this to loop back to needing the login password if it fails (Because most likely it's because the wrong password was entered)

x = 'false5'

while x != 'true5':
    switch_ssh_password = raw_input('What is the Login Password: ')
    #Commands to grant entry level access
    child.expect('password:')
    child.sendline(switch_ssh_password)
    if child.expect('%>'):
            print "1 - Entry to Switch was Granted"
            x = 'true5'
    else:
            print "1 - Entry to Switch was Denied, Try Again"
            x = 'false5'

Now when I get to this user input, I input the password, it hangs for about 30 seconds then comes back with this, I have no idea what's going wrong :(

Traceback (most recent call last):
  File "./configcisco.py", line 68, in <module>
    if child.expect('%>'):
  File "/usr/lib/python2.7/dist-packages/pexpect/__init__.py", line 1418, in expect
    timeout, searchwindowsize)
  File "/usr/lib/python2.7/dist-packages/pexpect/__init__.py", line 1433, in expect_list
    timeout, searchwindowsize)
  File "/usr/lib/python2.7/dist-packages/pexpect/__init__.py", line 1535, in expect_loop
    raise TIMEOUT(str(err) + '\n' + str(self))
pexpect.TIMEOUT: Timeout exceeded.
<pexpect.spawn object at 0x76a87f70>
version: 3.2
command: /usr/bin/ssh
args: ['/usr/bin/ssh', '[email protected]']
searcher: <pexpect.searcher_re object at 0x76a9ec50>
buffer (last 100 chars): ' \r\n\r\nryan-sw01>'
before (last 100 chars): ' \r\n\r\nryan-sw01>'
after: <class 'pexpect.TIMEOUT'>
match: None
match_index: None
exitstatus: None
flag_eof: False
pid: 11917
child_fd: 3
closed: False
timeout: 30
delimiter: <class 'pexpect.EOF'>
logfile: None
logfile_read: None
logfile_send: None
maxread: 2000
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1
2

There are 2 answers

1
Richard Cintorino On

Without all of your code it's difficult to figure out exactly what is going on. but based on what you've posted your Timing out looking for the shell character, For some additional diagnostics I would change up your code a little:

while True:
    switch_ssh_password = raw_input('What is the Login Password: ')
    #Commands to grant entry level access
    child.expect('password:')
    child.sendline(switch_ssh_password)
    if child.expect('%>'):
        print "1 - Entry to Switch was Granted"
        break
    elif child.expect('Permission denied'):
        print "Password Error or some message..."
    else:
        print "1 - Entry to Switch was Denied, Try Again"
0
Richard Cintorino On

So I rewrote your code as if I was doing it myself, (and also left some of your stuff in there) tested it and made sure it was working, you can see it here:

Pastebin code

My coding style is a mix between a LOT of different languages and styles, so don't concentrate on that too much. BUT, do look at how I deal with the IP address. In the process I did find out a few errors:

1) The expect function can catch the TIMEOUT, instead of raising an exception. This is a much better programming practice. When you do this, it returns the index in the list of the item found (in this case, 0). You should take some time to read the full documentation for pexpect, use the search function it helps a LOT, these modules are often EXTREMELY powerful and feature full, so you may be missing out on the true functionality you need and re-inventing the wheel in your own code, so to speak.

2) if you look at your error, you can see:

buffer (last 100 chars): ' \r\n\r\nryan-sw01>'

So it DID successfully connect to a host nryan-sw01, and you are at a prompt, but you're looking for '%>', instead of just '>'