Как мне узнать, что буферизует связь от qemu до pexpect? - PullRequest
1 голос
/ 29 марта 2019

У меня есть программа на Python2, которая запускает qemu с образом FreeBSD.
expect() строковый вывод работает.
Однако вывод expect(), у которого не завершена строка (например, при ожидании приглашения типа login:), на этот раз не срабатывает.

Я подозреваю, что что-то в связи между qemu и моей программой выполняет буферизацию строки, но как мне узнать, что это такое? Кандидаты, о которых я могу думать:

  • Сам FreeBSD. Я считаю, что маловероятно, что в интерактивном режиме показываются подсказки, а параметры -nographics в qemu не должны иметь значения для эмулируемой виртуальной машины (но я могу ошибаться).
  • Что-то в настройке pty. У меня нулевой опыт работы с ptys. Если это проблема, то это будет ошибка в pexpect, так как pexpect устанавливает pty.
  • Ошибка в pexpect.
  • Что-то в моем собственном сценарии ... но я понятия не имею, что это может быть.

Для справки вот урезанный код (включая скачивание и распаковку, если кто-то захочет поиграть с ним):

#! /usr/bin/env python2

import os
import pexpect
import re
import sys
import time

def run(cmd):
    '''Run command, log to stdout, no timeout, return the status code.'''
    print('run: ' + cmd)
    (output, rc) = pexpect.run(
        cmd,
        withexitstatus=1,
        encoding='utf-8',
        logfile=sys.stdout,
        timeout=None
        )
    if rc != 0:
        print('simple.py: Command failed with return code: ' + rc)
        exit(rc)


download_path = 'https://download.freebsd.org/ftp/releases/VM-IMAGES/12.0-RELEASE/amd64/Latest'
image_file = 'FreeBSD-12.0-RELEASE-amd64.qcow2'
image_file_xz = image_file + '.xz'

if not os.path.isfile(image_file_xz):
    run('curl -o %s %s/%s' % (image_file_xz, download_path, image_file_xz))

if not os.path.isfile(image_file):
    # Reset image file to initial state
    run('xz --decompress --keep --force --verbose ' + image_file_xz)

#cmd = 'qemu-system-x86_64 -snapshot -monitor none -display curses -chardev stdio,id=char0 ' + image_file
cmd = 'qemu-system-x86_64 -snapshot -nographic ' + image_file
print('interact with: ' + cmd)
child = pexpect.spawn(
    cmd,
    timeout=90, # FreeBSD takes roughly 60 seconds to boot
    maxread=1,
    )
child.logfile = sys.stdout

def expect(pattern):
    result = child.expect([pexpect.TIMEOUT, pattern])
    if result == 0:
        print("timeout: %d reached when waiting for: %s" % (child.timeout, pattern))
        exit(1)
    return result - 1

if False:
    # This does not work: the prompt is not visible, then timeout
    expect('login: ')
else:
    # Workaround, tested to work:
    expect(re.escape('FreeBSD/amd64 (freebsd)')) # Line before prompt
    time.sleep(1) # MUCH longer than actually needed, just to be safe

child.sendline('root')

# This will always time out, and terminate the script
expect('# ')
print('We want to get here but cannot')
...