期望不正确匹配模式

Posted

技术标签:

【中文标题】期望不正确匹配模式【英文标题】:expect not properly matching patterns 【发布时间】:2021-05-15 18:53:42 【问题描述】:

当使用 sendline 插入 sudo 密码时,我一直在尝试匹配模式,但它以某种方式无法正常工作。我可能做错了什么。我尝试了各种方法,但没有任何效果....请帮助。

示例:

import pexpect
USER = "someuser"
HOST = "IPADDRESSOFREMOTEHOST"
PORT="22"
PORTINFO = "-p " + PORT
CONNECTION = USER + "@" + HOST
SSHTIMEOUT = 5
CMDTIMEOUT=1
SSHOPTIONS = "-oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oPubkeyAuthentication=no -oConnectTimeout=0".format(SSHTIMEOUT)
CMD = 'ssh %s %s %s' % (SSHOPTIONS, CONNECTION, PORTINFO)
PWD = "correctpassword"

child = pexpect.spawn(CMD, timeout=int(CMDTIMEOUT), encoding='utf-8')
r1 = child.expect(['password: ', 'Connection timed out', 'No address associated with hostname','Could not resolve hostname'])
print(r1)
0 -> matching 'password'
child.sendline(PWD)
r2 = child.expect(['Permission denied', '[#\$]'])
print(r2)
1 -> matching '[#\$]'
child.sendline("df -h")
child.sendline("lscpu")
child.sendline("sudo ls /")
r3 = child.expect(['password','[sudo]','[#\$]'])
print(r3)
1 -> matching '[sudo]'
child.sendline(PWD)
r3 = child.expect(['password','[sudo]','[#\$]'])
print(r3)
1 -> AGAIN matching '[sudo]' where it should really be matching '[#\$]'] this is wrong

查看最后一行它总是匹配“[sudo]”,它应该真正匹配“[#\$]”,因为发送了正确的密码。

我不确定我做错了什么,它似乎与提示行不匹配,而是与整个输出匹配?我不太确定。如果是这种情况怎么办,我曾经弄清楚是否输入了正确的 sudo 密码?

-贾廷

【问题讨论】:

为什么要把sudo放在括号里? [sudo] 是匹配单个字符 sudo 的模式。也许你的意思只是'sudo' 当您发送 child.sendline("sudo ls /") 时,提示以 [sudo] 开头,所以我说,您会看到密码位于第 1 位,但它永远不匹配。我不确定发生了什么,为什么它不匹配密码并且它一直只匹配 [sudo]... 【参考方案1】:

使用 pexpect 时,您应该始终在 send 之后执行 expect,以便向前移动 pexpect 光标。否则,pexpect(不是贪婪的)将在前 2000 个字符内的搜索字符串的第一个实例处停止,并且它可能会在当前命令后面出现几个命令。

例如在spawn之后:

child.sendline("df -h")  # Prints the directory listing and a prompt
child.sendline("lscpu")  # Prints the architecture information and a prompt
child.sendline("sudo ls /")  # Expects a password, then prints a directory listing
child.expect(['password','[sudo]','[#\$]'])  # Finds the password prompt, since it is listed first
child.sendline("correctpassword")
child.expect(['password','[sudo]','[#\$]'])  # Finds the earlier sudo prompt, since it was not consumed in the previous expect, and it is listed before the prompt!

我简化并测试了您的代码:

注意 - 使用 Python 3.9 在 Linux 5.14.16 上测试。远程机器是 Ubuntu 8.04。

import sys
import pexpect

try:
    child = pexpect.spawn(
        'ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null ' +
        '-oPubkeyAuthentication=no -oConnectTimeout=5 someuser@192.168.x.x')
    child.logfile = sys.stdout.buffer
    index = child.expect_exact(['password:',
                                'Network is unreachable',
                                'Connection timed out',
                                'No address associated with hostname',
                                'Could not resolve hostname', ])
    if index == 0:
        child.sendline('correctpassword')
        # Use expect_exact to avoid misinterpreting characters as regex delimiters
        child.expect_exact('$')
    else:
        raise RuntimeError('Unable to SSH: Found index 0'.format(index))
    child.sendline('df -h')
    child.expect_exact('$')
    child.sendline('lshw')  # my remote machine does not use lscpu
    child.expect_exact('$')
    child.sendline('sudo ls /')
    index = child.expect_exact(['password', '$', ])
    if index == 0:
        child.sendline('correctpassword')
        # Use expect_exact to avoid misinterpreting characters as regex delimiters
        child.expect_exact('$')

    # ... add additional code here ...

    child.sendline('exit')
    child.expect_exact(['closed', '$', ])
    child.close()
except pexpect.TIMEOUT:
    print('Error: Unable to find the expect search string.\n' +
          pexpect.ExceptionPexpect(pexpect.TIMEOUT).get_trace())
except pexpect.EOF:
    print('Error: Child closed unexpectedly.\n' +
          pexpect.ExceptionPexpect(pexpect.EOF).get_trace())

输出:

Warning: Permanently added '192.168.x.x' (RSA) to the list of known hosts.
someuser@192.168.x.x's password: correctpassword

Linux ********** Thu Apr 10 13:58:00 UTC 2008 i686

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To access official Ubuntu documentation, please visit:
http://help.ubuntu.com/
You have mail.
Last login: Tue Dec 14 20:17:52 2021 from 192.168.x.x
someuser@192.168.x.x:~$ df -h
df -h
Filesystem            Size  Used Avail Use% Mounted on
...
/dev/sda1             228M   25M  192M  12% /boot
someuser@192.168.x.x:~$ lshw
lshw
WARNING: you should run this program as super-user.
...
configuration: driver=ahci latency=64 module=ahci
someuser@192.168.x.x:~$ sudo ls /
sudo ls /
bin    dev    ...
cdrom  home   lib    mnt    proc   srv    usr
someuser@192.168.x.x:~$ exit
exit
logout
Connection to 192.168.x.x closed.

Process finished with exit code 0

【讨论】:

以上是关于期望不正确匹配模式的主要内容,如果未能解决你的问题,请参考以下文章

如何从模式中打印不匹配的字母

Jason 解码两次以正确匹配模式

批处理中的正则表达式模式与子模式不匹配

Erlang中模式匹配字符串的正确方法

如何找到输入列表的匹配模式,然后使用 python 用正确的模式转换替换找到的模式

我如何匹配一个字符串,直到某个模式在模式不出现时也可以工作?