You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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库匹配交互提示发送输入,稳定性最高:

  1. 先安装依赖:
pip install pexpect
  1. 实现代码:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 03:48:22