Можно ли сказать ожидающему игнорировать шаблон или сигнал?

Я пытаюсь написать сценарий Python для доступа к нескольким сетевым устройствам Cisco. К сожалению, устройства не настроены одинаково, у некоторых есть баннеры, которые появляются в странных местах. Эти баннеры могут иметь шаблоны, которые имеют некоторые из элементов, которые могут иметь подсказки.

Например, как только я вхожу в систему, я ожидаю приглашения 'hostname#', поэтому я в основном использую pexpect('#'), мне, возможно, придется обрабатывать некоторые другие запросы, такие как 'hostname>', поэтому pexpect('>') работает. У меня действительно есть список возможных подсказок, плюс тайм-аут, и я буду действовать соответственно.

Это нормально, если где-то посередине не появляется баннер. Например, после входа в систему может появиться баннер с надписью ## Welcome ## и быть там прямо перед подсказкой. Я считаю, что если бы я мог сказать pexpect игнорировать регулярное выражение #.*\r, я был бы в порядке, но я не уверен, что это возможно. Можно ли заставить pexpect игнорировать строку или есть лучший способ сделать это?


person WildBill    schedule 01.06.2012    source источник


Ответы (3)


Решение, которое я использовал еще во времена BBS, заключалось в том, чтобы искать подсказку, а затем сразу же после ее получения искать разрыв строки или пробел с таймаутом в секунду или две. Если время второго ожидания истекло, это означало, что я ждал по запросу. Поскольку pexpect использует регулярные выражения, вы действительно можете проверить, получаете ли вы какой-либо символ в течение секунды после приглашения.

def wait_for_prompt(session, prompt, timeout=1):
    gotprompt = 0
    while not gotprompt:
        session.expect(prompt, timeout=None)
        gotprompt = session.expect([".", pexpect.TIMEOUT], timeout=timeout)

child = pexpect.spawn("ssh ...")
wait_for_prompt(child, "[#>] ?")

Я никогда раньше не использовал эту библиотеку, поэтому может потребоваться некоторая настройка, но это подход, который я успешно использовал в 80-х. :-)

person kindall    schedule 01.06.2012
comment
В итоге я использовал этот подход, и это лучший подход IMO. - person WildBill; 29.06.2012

Модуль Python pexpect ожидает ввода соответствия. Фактически вы не можете игнорировать ввод, за исключением создания регулярных выражений, которые не будут соответствовать неоднозначному или нежелательному вводу. Однако вместо создания одного действительно сложного регулярного выражения pexpect может также обрабатывать списки регулярных выражений. Затем вы привязываете эти регулярные выражения, чтобы уменьшить двусмысленность.

Например, вы можете легко отличить командную строку от баннера, привязав совпадение к началу или концу строки и сделав совпадение максимально точным:

users = ['fred', 'ginger']
user_prompt = '^(?:%s)@.*?\$ $' % '|'.join(users)
child.expect (['hostname# $', 'hostname> $', user_prompt])

Их ключ - понять, какой ввод вы хотите сопоставить, создать однозначное регулярное выражение с якорями, а затем обновлять свои выражения всякий раз, когда вы обнаружите несоответствие - что, надеюсь, будет не слишком часто, потому что вы не создавали чрезмерно жадные шаблоны. в первую очередь.

person Todd A. Jacobs    schedule 01.06.2012
comment
Такой тип сопоставления с образцом не будет работать, поскольку pexpect не может обрабатывать символ '$', как вы ожидали (каламбур не предназначен). То же верно и для '^'. См. noah.org/wiki/pexpect. - person WildBill; 29.06.2012
comment
@WildBill Вы правы. Выражение должно было проиллюстрировать концепцию привязки, но не было тщательно проверено. Если у вас есть рабочий пример привязанного выражения с pexpect, я буду рад обновить свой ответ. В противном случае, я думаю, ответ останется концептуально верным, даже если будущим посетителям потребуется переделать якоря EOL. - person Todd A. Jacobs; 29.06.2012
comment
Я не знаю, как обрабатывать закрепленные выражения (по крайней мере, не ожидая подсказки). Вы можете искать новые строки '\ n', но при появлении подсказки новой строки не существует. Это классическая проблема остановки: как узнать, что это последняя строка / символ? Я не уверен, существует ли эта проблема только в pexpect или во всех ожидаемых использованиях ... - person WildBill; 30.06.2012

Как только expect обнаруживает совпадение, он устанавливает атрибуты «до», «после» и «совпадение» в экземпляре процесса. Вы можете использовать их для написания логики.

В качестве альтернативы вы можете просто создать более подходящее регулярное выражение, которое соответствует только той подсказке, которую вы хотите. Даже r '> $ | # $', вероятно, сделает то, что вы хотите, поскольку он будет соответствовать только этим символам в конце строки.

person aychedee    schedule 01.06.2012
comment
r '›$ | # $' не даст ничего лучшего, поскольку в баннере может быть строка, оканчивающаяся на # или› - person WildBill; 04.06.2012