使用paramiko-expect修改OpenWRT路由器root密码未生效问题求助
问题根本原因
- 交互匹配逻辑错误:你调用
interact.expect(['.*password.*', '.*password.*'])时,paramiko-expect只会匹配列表中第一个出现的符合规则的内容,也就是Changing password for root这行,此时还没到New password:的输入提示,你提前发送的密码没有被passwd程序正确接收。 - 会话提前断开导致变更未落地:两次密码发送完成后,你没有等待passwd命令执行完成、返回shell提示符,就直接退出了SSH上下文,连接被主动关闭,系统还没来得及将密码变更写入
/etc/shadow文件,修改自然不生效。你遇到的重定向输出为空的问题也是同样逻辑:ls、ip a执行耗时比pwd长,输出还没写入文件会话就被销毁,只有执行速度最快的pwd能完成写入操作。 - 补充:
send方法默认不会自动追加换行符,如果你发送的内容没有显式加\n,也会导致输入没有被系统确认接收。
修复代码示例
import paramiko from paramiko_expect import SSHClientInteraction # 可选:开启paramiko debug日志排查交互细节 # paramiko.common.logging.basicConfig(level=paramiko.common.DEBUG) try: with paramiko.SSHClient() as ssh: ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect('192.168.1.1', 22, 'root', 'old_password') with SSHClientInteraction(ssh, timeout=10, display=True) as interact: # 精准匹配shell提示符再执行命令 interact.expect(r'.*root@.*#\s*$') # 发送命令显式加换行模拟回车操作 interact.send('passwd\n') # 匹配到密码输入提示后再发送密码 interact.expect(r'New password:\s*$') interact.send('new_password\n') # 匹配到确认密码提示后再发送二次密码 interact.expect(r'Retype password:\s*$') interact.send('new_password\n') # 重点:等待passwd执行完成,返回shell提示符再结束会话 interact.expect(r'.*root@.*#\s*$') # 可选:执行sync确保文件变更写入闪存 interact.send('sync\n') interact.expect(r'.*root@.*#\s*$') except Exception as e: print(f"执行错误: {e}")
通用排查方法
- 每一步
expect执行后打印缓冲区内容interact.current_output,确认匹配到的内容是否符合预期。 - 执行耗时较长的命令时,增加超时时间,或者主动等待命令执行完成返回提示符后再断开连接。
- 测试重定向类命令时,可在命令后追加
; sync确保输出内容落地到存储。
内容的提问来源于stack exchange,提问作者Ian_Ious
相关产品推荐
相关产品推荐

