我如何找出什么在缓冲从qemu到pexpect的通信?

时间:2019-03-29 06:54:29

标签: qemu pexpect

我有一个使用FreeBSD映像运行qemu的Python2程序。
expect()列出输出作品。
但是,expect()不会终止其行的输出(例如,在等待诸如login:之类的提示时)不会超时,

我怀疑qemu和我的程序之间的通信中有某些事情在进行行缓冲,但是我如何找出它们是哪一个呢?我能想到的候选人:

  • FreeBSD本身。我发现这不太可能,它会在交互式运行时显示提示,并且qemu的-nographics选项不会对模拟的VM有所影响(但我可能错了)。
  • pty设置中的某些内容。我对pty的经验为零。如果是这个问题,那么这将是pexpect中的一个错误,因为pexpect正在设置pty。
  • 预期的错误。
  • 我自己的脚本中有东西...但是我不知道那可能是什么。

作为参考,这是简化的代码(包括下载和解压缩,如果有人想玩的话):

#! /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')

0 个答案:

没有答案