Python3.6中pxssh连接SSH时提示符动态变化的问题求助
解决pxssh中远程提示符动态变化的问题
嘿,我之前用pxssh做SSH自动化脚本的时候也碰到过一模一样的麻烦——远程机器的提示符会跟着执行的命令变来变去,导致pxssh经常卡壳找不到结束标记。针对这个情况,给你几个实用的解决思路:
1. 让pxssh动态识别当前提示符
pxssh其实自带了提示符检测的能力,没必要硬编码固定值。你可以在登录成功后,手动更新它的PROMPT正则表达式,要么匹配通用格式,要么精准捕获当前的实际提示符:
通用匹配方案
如果远程机器的提示符都是以#、$或>结尾,直接用正则覆盖默认的PROMPT就能适配大部分场景:
import re from pexpect import pxssh ip = "xxx.xxx.xxx.xxx" username = 'user' password = 'pass' s = pxssh.pxssh() if s.login(ip, username, password): # 匹配以 #、$、> 结尾的提示符 s.PROMPT = re.compile(r'[\$#>] $') else: print("登录失败")
精准捕获当前提示符
如果需要更精准的匹配,可以通过echo命令获取当前的PS1(提示符变量),再设置PROMPT:
import re from pexpect import pxssh ip = "xxx.xxx.xxx.xxx" username = 'user' password = 'pass' s = pxssh.pxssh() if s.login(ip, username, password): # 发送echo命令标记提示符内容 s.sendline('echo "MARKER$(PS1)MARKER"') # 匹配标记之间的提示符内容 s.expect(r'MARKER(.*)MARKER') current_prompt = s.match.group(1).strip() # 更新PROMPT为当前实际的提示符(转义特殊字符避免正则冲突) s.PROMPT = re.compile(re.escape(current_prompt)) else: print("登录失败")
2. 给send_cmd函数添加多提示符匹配逻辑
如果你知道可能出现的几种提示符,可以在send_cmd里让pxssh同时匹配多个模式,避免因为提示符变化导致等待超时:
import re from pexpect import pxssh ip = "xxx.xxx.xxx.xxx" username = 'user' password = 'pass' s = pxssh.pxssh() def send_cmd(s, cmd, possible_prompts): """发送命令并返回输出,支持匹配多种提示符""" s.sendline(cmd) # 把所有可能的提示符拼成一个正则表达式 prompt_regex = re.compile('|'.join([re.escape(p) for p in possible_prompts])) s.expect(prompt_regex) # 过滤掉命令本身和提示符,只保留输出内容 output = s.before.decode('utf-8').strip().replace(cmd, '', 1).strip() print(output) return output if s.login(ip, username, password): # 定义所有可能出现的提示符 prompts = ['Something # ', 'NewCmdPrompt> ', 'AdminMode$ '] send_cmd(s, 'some_command_that_changes_prompt', prompts) else: print("登录失败")
3. 强制设置固定提示符(最省心的方案)
如果远程机器允许修改环境变量,登录后直接设置一个固定的自定义提示符,彻底解决变化问题:
from pexpect import pxssh ip = "xxx.xxx.xxx.xxx" username = 'user' password = 'pass' fixed_prompt = 'MyFixedSSHPrompt# ' s = pxssh.pxssh() if s.login(ip, username, password): # 设置固定提示符 s.sendline(f'export PS1="{fixed_prompt}"') s.expect(fixed_prompt) # 更新pxssh的PROMPT为固定值 s.PROMPT = fixed_prompt # 后续所有命令都用这个固定提示符匹配 s.sendline('ls -l') s.expect(fixed_prompt) print(s.before.decode('utf-8')) else: print("登录失败")
这些方案里,我个人最常用的是强制设置固定提示符——只要权限允许,这个方法最稳定,不用操心各种提示符变化的情况。
内容的提问来源于stack exchange,提问作者Difender
相关产品推荐
相关产品推荐

