Paramiko expect 在接收到预期输出之前发送命令

Paramiko expect sends a command before the expected output is received

我正在尝试使用 python 脚本配置路由器,并希望使用 paramiko expect 来完成这项工作。函数 change_password 是 class 的一部分,包含以下 paramiko-expect-lines(self.ssh_client 作为 paramiko.SSHClient 的实例):

with SSHClientInteraction(self.ssh_client, timeout=5, display=True) as self.interact:
    # change password
    prompt = '.*root@cb_park:~#.*'
    self.interact.expect(prompt)
    self.interact.send('passwd')
    self.interact.expect(['.*Changing password for root.*', '.*New password:.*'])
    self.interact.send('NewPassword')
    self.interact.expect('.*Retype password:.*')
    self.interact.send('NewPassword')
    self.interact.expect(['.*passwd: password for root changed by root.*', prompt])

    # modify firstlogin
    self.interact.send('uci delete vuci.main.firstlogin')
    self.interact.expect(prompt)
    self.interact.send('uci commit')
    self.interact.expect(prompt)

但是,有时会在出现提示之前执行发送命令。例如在以下场景中:

root@cb_park:~# passwd
Changing password for root
New password: 
Retype password: 
passwd: password for root changed by root
root@cb_park:~# uci delete vuci.main.firstlogin
uci commit
uci: Entry not found
root@cb_park:~# uci commit

'uci commit' 正在执行,即使没有给出预期的提示。有时这甚至发生在第二行,并且在 'Changing password for root' 之后立即执行新密码,即使 'New password:' 尚未给出,这会导致超时:

root@cb_park:~# passwd
Changing password for root
NewPassword
New password: EXCESS TIME RECV_READY TIMEOUT, did you expect() before a send()

Retype password: EXCESS TIME RECV_READY TIMEOUT, did you expect() before a send()

Passwords don't match
passwd: password for root is unchanged
root@cb_park:~#

我真的不知道错误可能是什么或如何调试。有什么想法吗?

paramiko 2.8.0

paramiko-expect 0.3.0

Python 3.8.10

干杯伊恩

如果有人遇到类似问题:

我把多行期望去掉,换成了只期望最后一行。我想我误解了文档并认为我必须期待这两行。新代码如下,没有超时。

with SSHClientInteraction(self.ssh_client, timeout=5, display=True) as self.interact:
    # change password
    prompt = '.*root@cb_park:~#.*'
    self.interact.expect(prompt)
    self.interact.send('passwd')
    self.interact.expect('.*New password:.*') # instead of self.interact.expect(['.*Changing password for root.*', '.*New password:.*'])
    self.interact.send('NewPassword')
    self.interact.expect('.*Retype password:.*')
    self.interact.send('NewPassword')
    self.interact.expect(prompt) # instead of self.interact.expect(['.*passwd: password for root changed by root.*', prompt])

    # modify firstlogin
    self.interact.send('uci delete vuci.main.firstlogin')
    self.interact.expect(prompt)
    self.interact.send('uci commit')
    self.interact.expect(prompt)

伊恩