pxssh匹配#提示符失败求助:多设备自动化脚本故障排查
Hey there! Let's figure out why your pxssh script is timing out on the #-style prompts for routerA and routerB, and get it fixed up.
Common Causes of the Timeout Issue
From your description, the problem almost certainly boils down to prompt matching failures—here's why:
- pxssh's default prompt regex doesn't account for custom prompts like
rp/0/rps0/cpu0:routerB#(it has special characters like slashes and colons that need proper handling). - Your current script's expect logic only targets the
>-based prompts, so it ignores the#prompts entirely, leading to timeouts when waiting for a match that never comes. - Post-login output (like banners, MOTD messages) might be delaying the prompt, making your timeout window too short.
Step-by-Step Fix
Let's adjust the script to handle all four prompt types explicitly, with proper regex escaping and flexible matching.
1. Define a Comprehensive Prompt Regex
First, create a regex that matches all four of your device prompts. Note that special characters like parentheses and colons need to be escaped for regex:
all_device_prompts = r'(routerA#|rp/0/rps0/cpu0:routerB#|routerC> \(enable\)|routerD>)'
- We use
|to separate each exact prompt match \(and\)escape the parentheses in(enable)since they're special regex characters
2. Modify the pxssh Connection Logic
Override pxssh's default prompt handling and explicitly wait for your custom prompts. Here's an updated script snippet:
import pxssh import pexpect def collect_device_data(host, username, password): try: ssh = pxssh.pxssh() # Disable pxssh's automatic prompt reset so we can use our own regex ssh.login(host, username, password, auto_prompt_reset=False) # Clear any post-login banner/MOTD by sending a return (optional but helpful) ssh.sendline('') # Wait for any of our defined prompts with a generous timeout ssh.expect(all_device_prompts, timeout=10) print(f"Connected successfully! Matched prompt: {ssh.after.decode().strip()}") # Example: Run a command and wait for the prompt to return ssh.sendline('show running-config') ssh.expect(all_device_prompts, timeout=20) command_output = ssh.before.decode() ssh.logout() return command_output except pxssh.ExceptionPxssh as e: print(f"SSH connection error: {str(e)}") except pexpect.TIMEOUT: # Print the last received output to debug what's actually showing up print(f"Timeout waiting for prompt! Last device output:\n{ssh.before.decode()}") except Exception as e: print(f"Unexpected error: {str(e)}")
3. Debugging Tips If You Still Hit Timeouts
If the timeout persists, use the ssh.before output (printed in the TIMEOUT catch block) to:
- Check if the device's actual prompt differs from what you expected (e.g., extra spaces like
routerA #instead ofrouterA#) - See if there's post-login output (like acceptance prompts for terms of service) that you need to handle before the main prompt appears
- Adjust the timeout value—some devices take longer to load their prompt after login
Key Takeaways
- Always explicitly define prompts for custom network devices instead of relying on pxssh's defaults
- Escape special regex characters (like
(,),/) when writing prompt matches - Use
ssh.beforeto debug what the device is actually sending back when timeouts occur
内容的提问来源于stack exchange,提问作者123troy

