Метод ожидает разрыва модуля pexpect python при сопоставлении строки в старом выводе

Я пытаюсь работать с gdb удаленно, используя pexpect. Это мой текущий код:

child = pexpect.spawn("ssh [email protected] \"gdb\"")
child.logfile = sys.stdout
child.expect("password:")
child.sendline("xxxx")
child.expect("(gdb)")
child.sendline("attach 9813")
child.expect("(gdb)")
child.sendline("info registers")
child.expect("(gdb)")
child.sendcontrol('c')

И это часть вывода моей консоли:

(...)
GNU gdb (GDB) 7.4.1-debian
(...)
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) attach 9813
info registers
test@test-virtual-machine:~$

Хотя я ожидаю что-то вроде этого:

(...)
GNU gdb (GDB) 7.4.1-debian
(...)
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) attach 9813
<Attaching...>
(gdb) info registers
<Registers info displayed...>
(gdb) <Ctrl+C is done>
test@test-virtual-machine:~$

Итак, проблема, похоже, заключается в том, что после сопоставления первой (gdb) и отправки первой команды attach 9813 pexpect не ожидает, что вторая строка (gdb) отправит новую команду info registers. Он снова видит первую (gdb), сопоставляет ее и просто отправляет вторую команду, не дожидаясь выполнения первой (пока мы не подключимся к нужному процессу).

Как я могу заставить его анализировать только следующий вывод? Без повторного сопоставления предыдущего вывода? Я видел такой пример для ftp-сервера:

child = pexpect.spawn('ftp ftp.openbsd.org')
child.expect('(?i)name .*: ')
child.sendline('anonymous')
child.expect('(?i)password')
child.sendline('[email protected]')
child.expect('ftp> ')
child.sendline('cd /pub/OpenBSD/3.7/packages/i386')
child.expect('ftp> ')
child.sendline('bin')
child.expect('ftp> ')
child.sendline('prompt')

Как я понимаю, здесь pexpect успевает отреагировать на ftp> в нужном порядке и отправляет команды последовательно. Мой код кажется похожим.

Я также пытался сбросить стандартный вывод, это не сработало.


person primavera314    schedule 22.07.2014    source источник
comment
expect() на самом деле рассматривает свой аргумент как шаблон регулярного выражения, а не простую строку, поэтому ваш поиск подсказки в первый раз, вероятно, совпадает с GNU gdb (GDB) 7.4.1-debian, а во второй раз - с URL-адресом отчета об ошибке или с чем-то в пропущенной части. Попробуйте использовать expect_exact() для простого сопоставления строк.   -  person Thomas K    schedule 22.07.2014
comment
Спасибо за ответ! Пробовал expect_exact() не помогло. Но я также попробовал expect(((gdb).*){2}) для моего второго cmd info registers, и, к сожалению, он работает, поэтому он соответствует 2 (gdb). Но такое решение — крайняя мера. Знаете ли вы, имеет ли оно какое-либо отношение к размеру окна поиска? Пробовал назначать 0, 1, 2, не помогает, и похоже я не понимаю механизма.   -  person primavera314    schedule 23.07.2014
comment
Я изменил свой expect() на expect_exact(), хотя это кажется более справедливым (за исключением регулярного выражения, которое я показал выше).   -  person primavera314    schedule 23.07.2014
comment
Может ли что-нибудь в пропущенной вами части ((...)) содержать (gdb)? Размер окна поиска здесь не должен иметь значения.   -  person Thomas K    schedule 23.07.2014
comment
Думаю, нет. Документация действительно говорит, что expect полностью анализирует представленный буфер каждый раз с самого начала. Тогда я не очень понимаю, как работает пример ftp. Так или иначе, мне пришлось expect использовать специальные ключевые слова в выводе выполнения команд, только так я пока могу понять, что выполнение завершено. Если я придумаю что-то лучше, я опубликую это. Спасибо за помощь!   -  person primavera314    schedule 25.07.2014


Ответы (2)


Кажется, что GDB иногда снова показывает подсказку перед любым выводом команд. Вы сопоставляете первое приглашение, отправляете свою команду, а затем сразу же сопоставляете «преждевременное» приглашение до отображения результата. Это означает, что Control-C в конце отправляется до отображения результата из «информационных регистров», но остальная часть скрипта работает.

Решение состоит в том, чтобы сопоставить любой ожидаемый результат перед отправкой следующей команды.

person joelmatth    schedule 04.09.2014
comment
Это именно то, что я придумал в конце. Спасибо за подтверждение моего решения. Я отмечу это как правильное. - person primavera314; 05.09.2014
comment
Это может заинтересовать сотрудников Google: github.com/cirosantilli. /cpp-cheat/blob/ :-) - person Ciro Santilli 新疆再教育营六四事件ۍ 09.11.2018

У меня была такая же проблема. Ответ Джоэлмата напомнил мне об исправлении.

trash = child.expect([".+"])

«.+» соответствует первому найденному объекту и помогает сбросить все.

person James Shrum    schedule 26.02.2017