Python subprocess调用SSH修改Linux路由器密码输入交互异常
核心报错原因
你之前的所有尝试都踩了三类共性问题:
- 管道作用域错误:管道符
|写在ssh命令参数外层时,会被本地shell解析,实际是在你的本机执行passwd,而非路由器端,自然出现认证令牌操作错误。 - 特殊字符解析错误:f-string里的
\n会被本地shell直接解析为实际换行,把完整命令拆成多行,导致第二行开头的|没有前置命令,触发语法错误。 - 方案选型不稳定:手动拼接
printf/echo传密码的方式对引号、密码特殊字符(空格、$、引号等)兼容性极差,不同固件的passwd交互逻辑差异也会导致输入错位。
最优实现(兼容99%Linux路由器固件,无交互)
优先用chpasswd实现,这个工具是Linux系统专门用于非交互修改密码的标准组件,OpenWrt、梅林等主流路由器固件默认自带,完全不需要处理两次密码输入的交互逻辑,也不会出现管道、引号解析问题:
import subprocess # 生成32位随机密码,用strip()移除pwgen输出末尾自带的换行符 root_password = subprocess.check_output(["pwgen", "-1", "32"], text=True).strip() # 注意:远程执行的完整命令(含管道)必须作为单独参数传给ssh,确保管道在路由器端生效 remote_command = f'echo "root:{root_password}" | chpasswd' result = subprocess.run( ["ssh", "root@192.168.1.1", remote_command], capture_output=True, text=True ) if result.returncode == 0: print(f"密码修改成功,新密码为:{root_password}") else: print(f"修改失败,错误信息:{result.stderr}")
方案说明
- 禁止使用
shell=True,直接传命令参数列表可以彻底避免本地shell的引号、换行解析问题,也不存在shell注入风险。 - 如果你的路由器固件不带
chpasswd,可以把remote_command替换为f'echo "{root_password}" | passwd --stdin root',适配支持--stdin参数的passwd版本。
极简固件兼容方案(处理交互场景)
如果你的路由器是高度精简的定制固件,既没有chpasswd,passwd也不支持--stdin参数,必须走两次输入密码的交互流程,不要手动拼接管道传参,直接用pexpect库匹配交互提示发送输入,稳定性最高:
- 先安装依赖:
pip install pexpect
- 实现代码:
import pexpect import subprocess root_password = subprocess.check_output(["pwgen", "-1", "32"], text=True).strip() # 拉起ssh远程执行passwd的进程 child = pexpect.spawn("ssh root@192.168.1.1 passwd", encoding="utf-8") # 首次连接时匹配主机指纹确认提示 child.expect([".*yes/no.*", ".*[Pp]assword.*:"]) if child.match.group().startswith("yes"): child.sendline("yes") child.expect(".*[Pp]assword.*:") # 发送第一次密码 child.sendline(root_password) # 匹配第二次确认密码提示 child.expect(".*[Pp]assword.*:") child.sendline(root_password) # 等待命令执行完成,匹配shell提示符 child.expect([".*#.*", ".*\$.*"]) child.close() if child.exitstatus == 0: print(f"密码修改成功,新密码为:{root_password}") else: print(f"修改失败,交互日志:{child.before}")
历史报错对应说明
Syntax error: "|" unexpected:本地shell解析到命令里的实际换行,把管道符拆到了新命令行开头,触发语法错误。- 命令在本机执行而非路由器执行:管道符放在了远程命令参数的包裹范围外,管道左侧的ssh输出直接传给了本机的
passwd进程。 Bearbeitungssfehler des Legitimierungszeichens(德语:认证令牌操作错误):本机普通用户执行passwd修改root密码时的权限报错。
内容的提问来源于stack exchange,提问作者gubwan
相关产品推荐
相关产品推荐

