Repository: ansible/ansible

Issue:
network_cli times out at self._ssh_shell.recv(256) randomly
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and devel branch are affected too.
Always add information AFTER of these html comments.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
 - Bug Report

##### COMPONENT NAME
<!---
Insert below this comment the name of the module, plugin, task or feature.
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path
-->
network_cli

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.5.0
  config file = /home/jgrip/coding/bastions/acl-audit/ansible.cfg
  configured module search path = [u'/home/jgrip/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /home/jgrip/.local/share/virtualenvs/bastions-oL9_cuE5/local/lib/python2.7/site-packages/ansible
  executable location = /home/jgrip/.local/share/virtualenvs/bastions-oL9_cuE5/bin/ansible
  python version = 2.7.13 (default, Nov 24 2017, 17:33:09) [GCC 6.3.0 20170516]
```

##### CONFIGURATION
<!---
If using Ansible 2.4 or above, paste the results of "ansible-config dump --only-changed"
Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
```
ANSIBLE_NOCOWS(/home/jgrip/coding/bastions/acl-audit/ansible.cfg) = True
CACHE_PLUGIN(/home/jgrip/coding/bastions/acl-audit/ansible.cfg) = jsonfile
CACHE_PLUGIN_CONNECTION(/home/jgrip/coding/bastions/acl-audit/ansible.cfg) = /tmp/ans.cache
CACHE_PLUGIN_TIMEOUT(/home/jgrip/coding/bastions/acl-audit/ansible.cfg) = 86400
DEFAULT_FORKS(/home/jgrip/coding/bastions/acl-audit/ansible.cfg) = 1
DEFAULT_GATHERING(/home/jgrip/coding/bastions/acl-audit/ansible.cfg) = explicit
DEFAULT_LOG_PATH(/home/jgrip/coding/bastions/acl-audit/ansible.cfg) = /home/jgrip/coding/bastions/acl-audit/log.txt
DISPLAY_SKIPPED_HOSTS(/home/jgrip/coding/bastions/acl-audit/ansible.cfg) = False
HOST_KEY_CHECKING(/home/jgrip/coding/bastions/acl-audit/ansible.cfg) = False
PARAMIKO_HOST_KEY_AUTO_ADD(/home/jgrip/coding/bastions/acl-audit/ansible.cfg) = True
PERSISTENT_COMMAND_TIMEOUT(/home/jgrip/coding/bastions/acl-audit/ansible.cfg) = 30
PERSISTENT_CONNECT_TIMEOUT(/home/jgrip/coding/bastions/acl-audit/ansible.cfg) = 1800
USE_PERSISTENT_CONNECTIONS(/home/jgrip/coding/bastions/acl-audit/ansible.cfg) = True
```

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say "N/A" for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->
```
$ cat /etc/os-release 
PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
NAME="Debian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
```
Tested with various Cisco network devices, IOS, IOS-XE and NXOS with varying levels of OS versions.

##### SUMMARY
<!--- Explain the problem briefly -->
Seemingly random network_cli fails to connect proper to a device it could previously do so. I've found no pattern as to when it fails or works.

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->
I do not fully understand what triggers the behaviour. It happens when I connect to network devices using network_cli. Sometimes I can collect ten times in a row without issue, other times I have to run ten times to get a success.

<!--- Paste example playbooks or commands between quotes below -->
```yaml
---
- hosts: ios
  connection: network_cli
  remote_user: admin

  tasks:
    - ios_facts
        gather_subset: config
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Successful SSH connection and collection of device configuration.

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
```
fatal: [ludtfol2s01.net.ses]: FAILED! => {"msg": ""}
```

I've added the additional logs from https://github.com/ganeshrn/ansible/commit/b74bd50ddec4716e61c9acc4284f939606365591 resulting in the following log of two runs. First run is successful, second run fails:
```
2018-04-13 14:51:13,138 p=39343 u=jgrip |  PLAY [Audit management ACLs] ****************************************************************************************************************************************************************************************************************
2018-04-13 14:51:13,155 p=39343 u=jgrip |  TASK [common : include_tasks] ***************************************************************************************************************************************************************************************************************
2018-04-13 14:51:13,263 p=39343 u=jgrip |  included: /home/jgrip/coding/bastions/acl-audit/roles/common/tasks/facts/main.yml for ludtfol2s01.net.ses
2018-04-13 14:51:13,271 p=39343 u=jgrip |  TASK [common : include_tasks] ***************************************************************************************************************************************************************************************************************
2018-04-13 14:51:13,394 p=39343 u=jgrip |  included: /home/jgrip/coding/bastions/acl-audit/roles/common/tasks/facts/cisco-facts.yml for ludtfol2s01.net.ses
2018-04-13 14:51:13,404 p=39343 u=jgrip |  TASK [common : IOS - Gather facts] **********************************************************************************************************************************************************************************************************
2018-04-13 14:51:15,378 paramiko.transport starting thread (client mode): 0x41fa14d0L
2018-04-13 14:51:15,378 paramiko.transport Local version/idstring: SSH-2.0-paramiko_2.4.1
2018-04-13 14:51:15,379 paramiko.transport Remote version/idstring: SSH-2.0-Cisco-1.25
2018-04-13 14:51:15,379 paramiko.transport Connected (version 2.0, client Cisco-1.25)
2018-04-13 14:51:15,380 paramiko.transport kex algos:[u'diffie-hellman-group-exchange-sha1', u'diffie-hellman-group14-sha1', u'diffie-hellman-group1-sha1'] server key:[u'ssh-rsa'] client encrypt:[u'aes128-ctr', u'aes192-ctr', u'aes256-ctr', u'aes128-cbc', u'3des-cbc', u'aes192-cbc', u'aes256-cbc'] server encrypt:[u'aes128-ctr', u'aes192-ctr', u'aes256-ctr', u'aes128-cbc', u'3des-cbc', u'aes192-cbc', u'aes256-cbc'] client mac:[u'hmac-sha1', u'hmac-sha1-96'] server mac:[u'hmac-sha1', u'hmac-sha1-96'] client compress:[u'none'] server compress:[u'none'] client lang:[u''] server lang:[u''] kex follows?False
2018-04-13 14:51:15,381 paramiko.transport Kex agreed: diffie-hellman-group-exchange-sha1
2018-04-13 14:51:15,381 paramiko.transport HostKey agreed: ssh-rsa
2018-04-13 14:51:15,381 paramiko.transport Cipher agreed: aes128-ctr
2018-04-13 14:51:15,381 paramiko.transport MAC agreed: hmac-sha1
2018-04-13 14:51:15,381 paramiko.transport Compression agreed: none
2018-04-13 14:51:15,582 paramiko.transport Got server p (2048 bits)
2018-04-13 14:51:16,185 paramiko.transport kex engine KexGex specified hash_algo <built-in function openssl_sha1>
2018-04-13 14:51:16,186 paramiko.transport Switch to new keys ...
2018-04-13 14:51:16,386 paramiko.transport userauth is OK
2018-04-13 14:51:16,387 paramiko.transport Auth banner:  
Unauthorised access to this computer system is prohibited, considered as a
security violation, which may constitute a criminal offense and may be subject
to a disciplinary action, criminal prosecution or other adverse action. 
Disconnect now if you have not been expressly authorised to access this
computer system. 
By accessing it, you have to be aware that this computer system may be
monitored to ensure its correct functioning in case of security events. 
During monitoring, logged information may be reviewed to investigate any
security events having an impact on the correct functioning of the computer
system. 
The retention period of logged information follows the applicable legal privacy
requirements.

2018-04-13 14:51:16,417 paramiko.transport Authentication (password) successful!
2018-04-13 14:51:16,420 paramiko.transport [chan 0] Max packet in: 32768 bytes
2018-04-13 14:51:16,422 paramiko.transport [chan 0] Max packet out: 4096 bytes
2018-04-13 14:51:16,422 paramiko.transport Secsh channel 0 opened.
2018-04-13 14:51:16,425 paramiko.transport [chan 0] Sesch channel 0 request ok
2018-04-13 14:51:16,428 paramiko.transport [chan 0] Sesch channel 0 request ok
2018-04-13 14:51:16,450 p=39387 u=jgrip |  -- receive -> data: 
ludtfol2s01# --
2018-04-13 14:51:16,450 p=39387 u=jgrip |  -- _find_prompt -> response: 
ludtfol2s01# --
2018-04-13 14:51:16,450 p=39387 u=jgrip |  -- _find_prompt -> self._matched_pattern: None --
2018-04-13 14:51:16,451 p=39387 u=jgrip |  -- _find_prompt -> self._matched_prompt: 
ludtfol2s01# --
2018-04-13 14:51:16,451 p=39387 u=jgrip |  -- receive -> self._last_response: 
ludtfol2s01# --
2018-04-13 14:51:16,455 p=39387 u=jgrip |  -- receive -> data: te --
2018-04-13 14:51:16,456 p=39387 u=jgrip |  -- _find_prompt -> response: te --
2018-04-13 14:51:16,457 p=39387 u=jgrip |  -- receive -> data: rm --
2018-04-13 14:51:16,458 p=39387 u=jgrip |  -- _find_prompt -> response: term --
2018-04-13 14:51:16,459 p=39387 u=jgrip |  -- receive -> data: ina --
2018-04-13 14:51:16,459 p=39387 u=jgrip |  -- _find_prompt -> response: termina --
2018-04-13 14:51:16,461 p=39387 u=jgrip |  -- receive -> data: l len --
2018-04-13 14:51:16,462 p=39387 u=jgrip |  -- _find_prompt -> response: terminal len --
2018-04-13 14:51:16,462 p=39387 u=jgrip |  -- receive -> data: gt --
2018-04-13 14:51:16,463 p=39387 u=jgrip |  -- _find_prompt -> response: terminal lengt --
2018-04-13 14:51:16,465 p=39387 u=jgrip |  -- receive -> data: h 0
 --
2018-04-13 14:51:16,465 p=39387 u=jgrip |  -- _find_prompt -> response: terminal length 0
 --
2018-04-13 14:51:16,465 p=39387 u=jgrip |  -- receive -> data: ludtfol2s01# --
2018-04-13 14:51:16,466 p=39387 u=jgrip |  -- _find_prompt -> response: terminal length 0
ludtfol2s01# --
2018-04-13 14:51:16,466 p=39387 u=jgrip |  -- _find_prompt -> self._matched_pattern: None --
2018-04-13 14:51:16,466 p=39387 u=jgrip |  -- _find_prompt -> self._matched_prompt: 
ludtfol2s01# --
2018-04-13 14:51:16,466 p=39387 u=jgrip |  -- receive -> self._last_response: terminal length 0
ludtfol2s01# --
2018-04-13 14:51:16,475 p=39387 u=jgrip |  -- receive -> data: term --
2018-04-13 14:51:16,475 p=39387 u=jgrip |  -- _find_prompt -> response: term --
2018-04-13 14:51:16,476 p=39387 u=jgrip |  -- receive -> data: in --
2018-04-13 14:51:16,477 p=39387 u=jgrip |  -- _find_prompt -> response: termin --
2018-04-13 14:51:16,492 p=39387 u=jgrip |  -- receive -> data: al widt --
2018-04-13 14:51:16,493 p=39387 u=jgrip |  -- _find_prompt -> response: terminal widt --
2018-04-13 14:51:16,494 p=39387 u=jgrip |  -- receive -> data: h --
2018-04-13 14:51:16,494 p=39387 u=jgrip |  -- _find_prompt -> response: terminal width --
2018-04-13 14:51:16,495 p=39387 u=jgrip |  -- receive -> data:   --
2018-04-13 14:51:16,495 p=39387 u=jgrip |  -- _find_prompt -> response: terminal width  --
2018-04-13 14:51:16,497 p=39387 u=jgrip |  -- receive -> data: 512
ludtfol2s01# --
2018-04-13 14:51:16,498 p=39387 u=jgrip |  -- _find_prompt -> response: terminal width 512
ludtfol2s01# --
2018-04-13 14:51:16,498 p=39387 u=jgrip |  -- _find_prompt -> self._matched_pattern: None --
2018-04-13 14:51:16,498 p=39387 u=jgrip |  -- _find_prompt -> self._matched_prompt: 
ludtfol2s01# --
2018-04-13 14:51:16,498 p=39387 u=jgrip |  -- receive -> self._last_response: terminal width 512
ludtfol2s01# --
2018-04-13 14:51:17,302 p=39387 u=jgrip |  -- receive -> data: sh --
2018-04-13 14:51:17,303 p=39387 u=jgrip |  -- _find_prompt -> response: sh --
2018-04-13 14:51:17,305 p=39387 u=jgrip |  -- receive -> data: ow ve --
2018-04-13 14:51:17,305 p=39387 u=jgrip |  -- _find_prompt -> response: show ve --
2018-04-13 14:51:17,307 p=39387 u=jgrip |  -- receive -> data: rs --
2018-04-13 14:51:17,308 p=39387 u=jgrip |  -- _find_prompt -> response: show vers --
2018-04-13 14:51:17,308 p=39387 u=jgrip |  -- receive -> data: io --
2018-04-13 14:51:17,308 p=39387 u=jgrip |  -- _find_prompt -> response: show versio --
2018-04-13 14:51:17,309 p=39387 u=jgrip |  -- receive -> data: n --
2018-04-13 14:51:17,309 p=39387 u=jgrip |  -- _find_prompt -> response: show version --
2018-04-13 14:51:17,310 p=39387 u=jgrip |  -- receive -> data: 
 --
2018-04-13 14:51:17,310 p=39387 u=jgrip |  -- _find_prompt -> response: show version
 --
2018-04-13 14:51:17,318 p=39387 u=jgrip |  -- receive -> data: Cisco IOS Software, C2960X Software (C2960X-UNIVERSALK9-M), Version 15.2(2)E5, RELEASE SOFTWARE (fc2)
<lots of data cut>
2018-04-13 14:51:20,944 p=39343 u=jgrip |  ok: [ludtfol2s01.net.ses]
2018-04-13 14:51:20,953 p=39343 u=jgrip |  TASK [common : IOS - Set object group facts] ************************************************************************************************************************************************************************************************
2018-04-13 14:51:22,803 p=39343 u=jgrip |  ok: [ludtfol2s01.net.ses]
2018-04-13 14:51:22,816 p=39343 u=jgrip |  TASK [common : set_fact] ********************************************************************************************************************************************************************************************************************
2018-04-13 14:51:24,678 p=39343 u=jgrip |  ok: [ludtfol2s01.net.ses]
2018-04-13 14:51:24,685 p=39343 u=jgrip |  TASK [common : set_fact] ********************************************************************************************************************************************************************************************************************
2018-04-13 14:51:24,891 p=39343 u=jgrip |   [ERROR]: User interrupted execution

2018-04-13 14:51:29,924 p=39568 u=jgrip |  PLAY [Audit management ACLs] ****************************************************************************************************************************************************************************************************************
2018-04-13 14:51:29,942 p=39568 u=jgrip |  TASK [common : include_tasks] ***************************************************************************************************************************************************************************************************************
2018-04-13 14:51:30,057 p=39568 u=jgrip |  included: /home/jgrip/coding/bastions/acl-audit/roles/common/tasks/facts/main.yml for ludtfol2s01.net.ses
2018-04-13 14:51:30,065 p=39568 u=jgrip |  TASK [common : include_tasks] ***************************************************************************************************************************************************************************************************************
2018-04-13 14:51:30,184 p=39568 u=jgrip |  included: /home/jgrip/coding/bastions/acl-audit/roles/common/tasks/facts/cisco-facts.yml for ludtfol2s01.net.ses
2018-04-13 14:51:30,195 p=39568 u=jgrip |  TASK [common : IOS - Gather facts] **********************************************************************************************************************************************************************************************************
2018-04-13 14:51:32,658 paramiko.transport starting thread (client mode): 0x26a834d0L
2018-04-13 14:51:32,659 paramiko.transport Local version/idstring: SSH-2.0-paramiko_2.4.1
2018-04-13 14:51:32,660 paramiko.transport Remote version/idstring: SSH-2.0-Cisco-1.25
2018-04-13 14:51:32,660 paramiko.transport Connected (version 2.0, client Cisco-1.25)
2018-04-13 14:51:32,662 paramiko.transport kex algos:[u'diffie-hellman-group-exchange-sha1', u'diffie-hellman-group14-sha1', u'diffie-hellman-group1-sha1'] server key:[u'ssh-rsa'] client encrypt:[u'aes128-ctr', u'aes192-ctr', u'aes256-ctr', u'aes128-cbc', u'3des-cbc', u'aes192-cbc', u'aes256-cbc'] server encrypt:[u'aes128-ctr', u'aes192-ctr', u'aes256-ctr', u'aes128-cbc', u'3des-cbc', u'aes192-cbc', u'aes256-cbc'] client mac:[u'hmac-sha1', u'hmac-sha1-96'] server mac:[u'hmac-sha1', u'hmac-sha1-96'] client compress:[u'none'] server compress:[u'none'] client lang:[u''] server lang:[u''] kex follows?False
2018-04-13 14:51:32,663 paramiko.transport Kex agreed: diffie-hellman-group-exchange-sha1
2018-04-13 14:51:32,663 paramiko.transport HostKey agreed: ssh-rsa
2018-04-13 14:51:32,663 paramiko.transport Cipher agreed: aes128-ctr
2018-04-13 14:51:32,663 paramiko.transport MAC agreed: hmac-sha1
2018-04-13 14:51:32,663 paramiko.transport Compression agreed: none
2018-04-13 14:51:32,868 paramiko.transport Got server p (2048 bits)
2018-04-13 14:51:33,486 paramiko.transport kex engine KexGex specified hash_algo <built-in function openssl_sha1>
2018-04-13 14:51:33,488 paramiko.transport Switch to new keys ...
2018-04-13 14:51:33,687 paramiko.transport userauth is OK
2018-04-13 14:51:33,688 paramiko.transport Auth banner:  
Unauthorised access to this computer system is prohibited, considered as a
security violation, which may constitute a criminal offense and may be subject
to a disciplinary action, criminal prosecution or other adverse action. 
Disconnect now if you have not been expressly authorised to access this
computer system. 
By accessing it, you have to be aware that this computer system may be
monitored to ensure its correct functioning in case of security events. 
During monitoring, logged information may be reviewed to investigate any
security events having an impact on the correct functioning of the computer
system. 
The retention period of logged information follows the applicable legal privacy
requirements.

2018-04-13 14:51:33,722 paramiko.transport Authentication (password) successful!
2018-04-13 14:51:33,731 paramiko.transport [chan 0] Max packet in: 32768 bytes
2018-04-13 14:51:33,735 paramiko.transport [chan 0] Max packet out: 4096 bytes
2018-04-13 14:51:33,735 paramiko.transport Secsh channel 0 opened.
2018-04-13 14:51:33,741 paramiko.transport [chan 0] Sesch channel 0 request ok
2018-04-13 14:51:33,746 paramiko.transport [chan 0] Sesch channel 0 request ok
2018-04-13 14:51:33,768 p=39634 u=jgrip |  -- receive -> data: ludtfol2s01# --
2018-04-13 14:51:33,768 p=39634 u=jgrip |  -- _find_prompt -> response: ludtfol2s01# --
2018-04-13 14:52:03,771 p=39634 u=jgrip |  shutdown complete
2018-04-13 14:52:03,836 paramiko.transport EOF in transport thread
2018-04-13 14:52:03,868 p=39568 u=jgrip |  fatal: [ludtfol2s01.net.ses]: FAILED! => {"msg": ""}
2018-04-13 14:52:08,472 p=39568 u=jgrip |  User interrupted execution
```
It seems to fail to match the prompt for some reason.




Discussion:
Files identified in the description:
* [lib/ansible/plugins/connection/network_cli.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/connection/network_cli.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @Qalthos @ganeshrn @gdpak @gundalow @privateip @rcarrillocruz @trishnaguha
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
I added hex dumping of the prompt string to match and found that sometimes my input string into _find_prompt does not have the leading newlines:

Working:
```
2018-04-16 17:16:15,456 p=38540 u=jgrip |  -- receive -> data: 
ILJER-CIR01# --
2018-04-16 17:16:15,456 p=38540 u=jgrip |  -- _find_prompt -> response: 
ILJER-CIR01# --
2018-04-16 17:16:15,457 p=38540 u=jgrip |  -- _find_prompt -> data: 0d0a494c4a45522d434952303123
2018-04-16 17:16:15,458 p=38540 u=jgrip |  -- _find_prompt -> matching |[\r\n][\w\+\-\.:\/\[\]]+(?:\([^\)]+\)){0,3}(?:[>#]) ?$|
2018-04-16 17:16:15,458 p=38540 u=jgrip |  -- _find_prompt -> self._matched_pattern: None --
```

Non-working:
```
2018-04-16 17:16:33,835 p=38689 u=jgrip |  -- receive -> data: ILJER-CIR02# --
2018-04-16 17:16:33,836 p=38689 u=jgrip |  -- _find_prompt -> response: ILJER-CIR02# --
2018-04-16 17:16:33,837 p=38689 u=jgrip |  -- _find_prompt -> data: 494c4a45522d434952303223
2018-04-16 17:16:33,837 p=38689 u=jgrip |  -- _find_prompt -> matching |[\r\n][\w\+\-\.:\/\[\]]+(?:\([^\)]+\)){0,3}(?:[>#]) ?$|
2018-04-16 17:16:33,837 p=38689 u=jgrip |  -- _find_prompt -> prompt not matched
```

Making the first part of the prompt regex in plugins/terminal/ios.py optional seems to resolve the issue, but I'm not sure of any side effects of this:
```
    terminal_stdout_re = [
        re.compile(br"[\r\n]?[\w\+\-\.:\/\[\]]+(?:\([^\)]+\)){0,3}(?:[>#]) ?$")
    ]
```
@jgrip The optional part was removed as part of PR https://github.com/ansible/ansible/pull/34585 as a precaution. If making [\r\n]? optional fixes the issue we can add it back imo.

@privateip @Qalthos Thoughts/Comments?

FYI the PR linked here https://github.com/ansible/ansible/pull/34585#issuecomment-356788884 is superseded by https://github.com/ansible/ansible/pull/35361. 
I've been testing around trying to find a pattern as to why it sometimes does not have the newline at the start of the prompt but I am unable to find a reason.

It does seem to happen more often as I increase the amount of forks in ansible.cfg, but it also happens at times with forks at 1. Using a different computer doesn't seem to make any difference either.
@ganeshrn LGTM


Resolving patch:
diff --git a/lib/ansible/plugins/terminal/ios.py b/lib/ansible/plugins/terminal/ios.py
--- a/lib/ansible/plugins/terminal/ios.py
+++ b/lib/ansible/plugins/terminal/ios.py
@@ -30,7 +30,7 @@
 class TerminalModule(TerminalBase):
 
     terminal_stdout_re = [
-        re.compile(br"[\r\n][\w\+\-\.:\/\[\]]+(?:\([^\)]+\)){0,3}(?:[>#]) ?$")
+        re.compile(br"[\r\n]?[\w\+\-\.:\/\[\]]+(?:\([^\)]+\)){0,3}(?:[>#]) ?$")
     ]
 
     terminal_stderr_re = [
diff --git a/lib/ansible/plugins/terminal/iosxr.py b/lib/ansible/plugins/terminal/iosxr.py
--- a/lib/ansible/plugins/terminal/iosxr.py
+++ b/lib/ansible/plugins/terminal/iosxr.py
@@ -29,7 +29,7 @@
 class TerminalModule(TerminalBase):
 
     terminal_stdout_re = [
-        re.compile(br"[\r\n][\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$"),
+        re.compile(br"[\r\n]?[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$"),
         re.compile(br']]>]]>[\r\n]?')
     ]
 


Test patch: