Python pxssh expect pattern is not matching '#'

565 views Asked by At

I am trying to use pxssh to connect to several devices and collect data from them. The devices have one of the following prompts:

routerA#
rp/0/rps0/cpu0:routerB#
routerC> (enable)
routerD>

Devices with a "#" have one set of commands, devices with "> (enable)" has a different set and those with just ">" get a third set of commands. Given that we do not know what the prompt is until after login, we need to have one script that differentiates based on the prompt.

With my code below, routerC and routerD work, but routerA and routerB do not.

#!/usr/local/bin/python3

import sys
import pexpect
from pexpect import pxssh
import time
import subprocess
import pdb

routerFile = open('test.hosts','r')
routeServers = [i for i in routerFile]
commandFile = open('standard.commands','r')
commands = [i for i in commandFile]
pdb.set_trace()
for router in routeServers:
  router = router.strip()
  print('####connecting to####', router)
  for i in range(max_retries):
    try:
      s = pxssh.pxssh()
      s.login(router,'username','password', original_prompt="\S+#$|\S+# $|\(\S+\)$|\(\S+\) $|\S+>$|\S+> $", auto_prompt_reset=False)
      print(s.before)
      print(s.after)
      pattern_index = s.expect([r'\S+#$', r'\S+# $', r'\S+> ', r'\S+>$'])
      print(s.before)
      print(s.after)
      if pattern_index == 0 or pattern_index == 1:
        print("#")        
      elif pattern_index == 2:
        print("catos")
       if pattern_index == 3:
        print("enable")
    except Exception as e:
      print ('!!!!!ERROR!!!!! Issue with host %s', router)
      print (str(e))
      s = None

Here is the debug output that I get.

> pxssh_test.py(21)<module>()
-> for router in routeServers:
(Pdb) n
> pxssh_test.py(22)<module>()
-> router = router.strip()
(Pdb)
> pxssh_test.py(23)<module>()
-> print('####connecting to####', router)
(Pdb)
####connecting to#### routerA
> pxssh_test.py(24)<module>()
-> for i in range(max_retries):
(Pdb)
> pxssh_test.py(25)<module>()
-> try:
(Pdb)
> pxssh_test.py(26)<module>()
-> s = pxssh.pxssh()
(Pdb)
> pxssh_test.py(27)<module>()
-> s.login(router,'username','password', original_prompt="\S+#$|\S+# $|\(\S+\)$|\(\S+\) $|\S+>$|\S+> $", auto_prompt_reset=False)
(Pdb)
> directory/pxssh_test.py(28)<module>()
-> print(s.before)
(Pdb)
b' \r\n....data removed....\r\n\r'
> directory/pxssh_test.py(29)<module>()
-> print(s.after)
(Pdb)
b'routerA# '
> pxssh_test.py(30)<module>()
-> pattern_index = s.expect([r'\S+#$', r'\S+# $', r'\S+> ', r'\S+>$'])
(Pdb)
pexpect.exceptions.TIMEOUT: Timeout exceeded.
<pexpect.pxssh.pxssh object at 0x7f9f19f8efd0>
command: /bin/ssh
args: ['/bin/ssh', '-q', '-l', 'intelliden', 'routerA']
buffer (last 100 chars): b''


after: <class 'pexpect.exceptions.TIMEOUT'>
match: None
match_index: None
exitstatus: None
flag_eof: False
pid: 42618
child_fd: 7
closed: False
timeout: 30
delimiter: <class 'pexpect.exceptions.EOF'>
logfile: None
logfile_read: None
logfile_send: None
maxread: 2000
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1
searcher: searcher_re:
    0: re.compile("b'\\S+#$'")
    1: re.compile("b'\\S+# $'")
    2: re.compile("b'\\S+> '")
    3: re.compile("b'\\S+>$'")
> pxssh_test.py(30)<module>()
-> pattern_index = s.expect([r'\S+#$', r'\S+# $', r'\S+> ', r'\S+>$'])
(Pdb)
> pxssh_test.py(106)<module>()
-> except pexpect.EOF:
(Pdb)
> pxssh_test.py(113)<module>()
-> except pexpect.TIMEOUT:
(Pdb)

Any help on why the # will not work would be greatly appreciated.

1

There are 1 answers

0
123troy On

For anyone that runs into the same issue, I had to add a sendline() and set the prompt between pxssh.pxssh() and the login.

Like this:

...
s = pxssh.pxssh()
s.PROMPT = "\S+#|\S+# |(\S+)$|(\S+) $|\S+>$|\S+> $"
s.login(router,'username','password', auto_prompt_reset=False)
s.sendline()
pattern_index = s.expect([r'\S+#$', r'\S+# $', r'\S+> ', r'\S+>$'])
if pattern_index == 0 or pattern_index == 1:
...