38 使用 QEMU 监控器管理虚拟机 #
    通过 qemu-system-ARCH 命令(例如 qemu-system-x86_64)调用虚拟机时,会提供一个监控器控制台用来与用户交互。使用监控器控制台中提供的命令可以检查运行中的操作系统、更改可移动媒体、截取屏幕截图或音频片段,以及控制虚拟机的其他方面。
  
      下列章节列出了精选的实用 QEMU 监控器命令及其用途。要获取完整列表,请在 QEMU 监控器命令行中输入 help。
    
38.1 访问监控器控制台 #
libvirt 没有监控器控制台
        仅当您直接使用 qemu-system-ARCH 命令启动虚拟机并在内置 QEMU 窗口中查看其图形输出时,才可以访问监控器控制台。
      
        如果您使用 libvirt 启动了虚拟机(例如,使用 virt-manager)并通过 VNC 或 Spice 会话查看其输出,则无法直接访问监控器控制台。不过,您可以通过 virsh 将监控器命令发送到虚拟机:
      
# virsh qemu-monitor-command COMMAND
      访问监控器控制台的方式取决于您使用哪种显示设备来查看虚拟机的输出。第 37.3.2.2 节 “显示选项”中提供了有关显示器的更多细节。例如,要在使用 -display gtk 选项的情况下查看监控器,请按 Ctrl–Alt–2。同样,在使用 -nographic 选项时,可按以下组合键切换到监控器控制台:Ctrl–AC。
    
      在使用控制台时如需帮助,请使用 help 或 ?。要获取有关特定命令的帮助,请使用 help COMMAND。
    
38.2 获取有关 Guest 系统的信息 #
      要获取有关 Guest 系统的信息,请使用 info。如果不结合任何选项使用该命令,将列显可能的选项的列表。选项可确定要分析系统的哪个部分:
    
- info version
- 显示 QEMU 的版本。 
- info commands
- 列出可用的 QMP 命令。 
- info network
- 显示网络状态。 
- info chardev
- 显示字符设备。 
- info block
- 有关块设备(例如硬盘、软盘驱动器或 CD-ROM)的信息。 
- info blockstats
- 块设备的读取和写入统计数据。 
- info registers
- 显示 CPU 寄存器。 
- info cpus
- 显示有关可用 CPU 的信息。 
- info history
- 显示命令行历史。 
- info irq
- 显示中断统计数据。 
- info pic
- 显示 i8259 (PIC) 状态。 
- info pci
- 显示 PCI 信息。 
- info tlb
- 显示虚拟内存到物理内存的映射。 
- info mem
- 显示活动的虚拟内存映射。 
- info jit
- 显示动态编译器信息。 
- info kvm
- 显示 KVM 信息。 
- info numa
- 显示 NUMA 信息。 
- info usb
- 显示 Guest USB 设备。 
- info usbhost
- 显示主机 USB 设备。 
- info profile
- 显示分析信息。 
- info capture
- 显示捕获(音频抓取)信息。 
- info snapshots
- 显示当前保存的虚拟机快照。 
- info status
- 显示当前虚拟机的状态。 
- info mice
- 显示哪些 Guest 鼠标正在接收事件。 
- info vnc
- 显示 VNC 服务器状态。 
- info name
- 显示当前虚拟机的名称。 
- info uuid
- 显示当前虚拟机的 UUID。 
- info usernet
- 显示用户网络堆栈连接状态。 
- info migrate
- 显示迁移状态。 
- info balloon
- 显示气球设备信息。 
- info qtree
- 显示设备树。 
- info qdm
- 显示 qdev 设备型号列表。 
- info roms
- 显示 ROM。 
- info migrate_cache_size
- 显示当前迁移 xbzrle(“基于 Xor 的零运行长度编码”)缓存大小。 
- info migrate_capabilities
- 显示多个迁移功能(例如 xbzrle 压缩)的状态。 
- info mtree
- 显示 VM Guest 内存层次结构。 
- info trace-events
- 显示可用的跟踪事件及其状态。 
38.3 更改 VNC 口令 #
      要更改 VNC 口令,请使用 change vnc
      password 命令并输入新口令:
    
(qemu) change vnc password Password: ******** (qemu)
38.4 管理设备 #
      要在 Guest 运行时添加新磁盘(热插入),请使用 drive_add 和 device_add 命令。首先定义要作为设备添加到总线 0 的新驱动器:
    
(qemu) drive_add 0 if=none,file=/tmp/test.img,format=raw,id=disk1 OK
可以通过查询块子系统来确认新设备:
(qemu) info block [...] disk1: removable=1 locked=0 tray-open=0 file=/tmp/test.img ro=0 drv=raw \ encrypted=0 bps=0 bps_rd=0 bps_wr=0 iops=0 iops_rd=0 iops_wr=0
      定义新驱动器后,需将它连接到某个设备,使 Guest 能够看到它。典型的设备是 virtio-blk-pci 或 scsi-disk。要获取可用值的完整列表,请运行:
    
(qemu) device_add ? name "VGA", bus PCI name "usb-storage", bus usb-bus [...] name "virtio-blk-pci", bus virtio-bus
现在添加设备
(qemu) device_add virtio-blk-pci,drive=disk1,id=myvirtio1
并使用以下命令确认
(qemu) info pci
[...]
Bus  0, device   4, function 0:
    SCSI controller: PCI device 1af4:1001
      IRQ 0.
      BAR0: I/O at 0xffffffffffffffff [0x003e].
      BAR1: 32 bit memory at 0xffffffffffffffff [0x00000ffe].
      id "myvirtio1"
        可以使用 device_del 从 Guest 中去除通过 device_add 命令添加的设备。如需详细信息,请在 QEMU 监控器命令行中输入 help device_del。
      
      要释放与可移动媒体设备连接的设备或文件,请使用 eject DEVICE 命令。使用可选的 -f 可以强制弹出。
    
      要更改可移动媒体(例如 CD-ROM),请使用 change DEVICE 命令。可以使用 info
      block 命令确定可移动媒体的名称:
    
(qemu)info blockide1-cd0: type=cdrom removable=1 locked=0 file=/dev/sr0 ro=1 drv=host_device(qemu)change ide1-cd0 /path/to/image
38.5 控制键盘和鼠标 #
      如果需要,可以使用监控器控制台来模拟键盘和鼠标输入。例如,如果您的图形用户界面拦截了某些低级别的组合键(例如 X Window 系统中的 Ctrl–Alt–F1),您仍可以使用 sendkey KEYS 来输入这些组合键:
    
sendkey ctrl-alt-f1
      要列出 KEYS 选项中使用的按键名称,请输入 sendkey 并按 →|。
    
要控制鼠标,可使用以下命令:
- mouse_moveDX dy [DZ]
- 将活动的鼠标指针移到指定的坐标 dx, dy, dz(该滚动轴可选)。 
- mouse_buttonVAL
- 更改鼠标按钮的状态(1=左,2=中,4=右)。 
- mouse_setINDEX
- 设置由哪个鼠标设备接收事件。可以使用 - info mice命令获取设备索引号。
38.6 更改可用内存 #
      如果启动虚拟机时使用了 -balloon
      virtio 选项(如此会启用半虚拟化气球设备),您便可以动态更改可用内存。有关启用气球设备的详细信息,请参见第 36.1 节 “使用 qemu-system-ARCH 进行基本安装”。
    
      要在监控器控制台中获取有关气球设备的信息,并确定该设备是否已启用,请使用 info
      balloon 命令:
    
(qemu) info balloon
      如果气球设备已启用,请使用 balloon MEMORY_IN_MB 命令设置请求的内存量:
    
(qemu) balloon 400
38.7 转储虚拟机内存 #
要将虚拟机内存的内容保存到磁盘或控制台输出,请使用以下命令:
- memsaveADDRSIZEFILENAME
- 将起始地址为 ADDR、大小为 SIZE 的虚拟内存转储保存到 FILENAME 文件中 
- pmemsaveADDRSIZEFILENAME
- 将起始地址为 ADDR、大小为 SIZE 的物理内存转储保存到 FILENAME- 文件中 
- x /FMTADDR
- 创建起始地址为 ADDR 并根据 FMT 字符串设置格式的虚拟内存转储。FMT 字符串由 - COUNTFORMATSIZE这三个参数构成:- COUNT 参数是要转储的项数。 - FORMAT 可以是 - x(十六进制)、- d(有符号十进制)、- u(无符号十进制)、- o(八进制)、- c(字符)或- i(汇编指令)。- SIZE 参数可以是 - b(8 位)、- h(16 位)、- w(32 位)或- g(64 位)。在 x86 上,可以使用- i格式指定- h或- w,以分别选择 16 位或 32 位代码指令大小。
- xp /FMTADDR
- 创建起始地址为 ADDR 并根据 FMT 字符串设置格式的物理内存转储。FMT 字符串由 - COUNTFORMATSIZE这三个参数构成:- COUNT 参数是要转储的项数。 - FORMAT 可以是 - x(十六进制)、- d(有符号十进制)、- u(无符号十进制)、- o(八进制)、- c(字符)或- i(汇编指令)。- SIZE 参数可以是 - b(8 位)、- h(16 位)、- w(32 位)或- g(64 位)。在 x86 上,可以使用- i格式指定- h或- w,以分别选择 16 位或 32 位代码指令大小。
38.8 管理虚拟机快照 #
SUSE 目前不支持在 QEMU 监控器中管理快照。本节中的信息在特定的情形下可能有帮助。
虚拟机快照是整个虚拟机的快照,包括 CPU、RAM 的状态以及所有可写磁盘的内容。要使用虚拟机快照,您必须至少有一个使用 qcow2 磁盘映像格式且不可移动的可写块设备。
    
当您需要保存特定状态的虚拟机时,快照非常有用。例如,在虚拟化服务器上配置网络服务后,您可以从上次保存的虚拟机状态快速启动虚拟机。您还可以在关闭虚拟机之后创建快照,以便在尝试执行某种会导致 VM Guest 不稳定的试验性操作之前创建备份状态。本节介绍前一种做法,后一种做法已在第 36.2.3 节 “使用 qemu-img 管理虚拟机的快照”中介绍。
可在 QEMU 监控器中使用以下命令管理快照:
- savevmNAME
- 创建一个标记为 NAME 的新虚拟机快照,或替换现有快照。 
- loadvmNAME
- 加载标记为 NAME 的虚拟机快照。 
- delvm
- 删除虚拟机快照。 
- info snapshots
- 列显有关可用快照的信息。 - (qemu) info snapshots Snapshot list: ID1 TAG2 VM SIZE3 DATE4 VM CLOCK5 1 booting 4.4M 2013-11-22 10:51:10 00:00:20.476 2 booted 184M 2013-11-22 10:53:03 00:02:05.394 3 logged_in 273M 2013-11-22 11:00:25 00:04:34.843 4 ff_and_term_running 372M 2013-11-22 11:12:27 00:08:44.965 
38.9 挂起和恢复虚拟机执行 #
以下命令可用于挂起和恢复虚拟机:
- stop
- 挂起虚拟机的执行。 
- cont
- 恢复虚拟机的执行。 
- system_reset
- 重置虚拟机。效果类似于物理机上的复位按钮。这可能会使文件系统处于一种不干净状态。 
- system_powerdown
- 向计算机发送 ACPI 关机请求。效果类似于物理机上的电源按钮。 
- q或- quit
- 立即终止 QEMU。 
38.10 动态迁移 #
实时迁移过程可将任何虚拟机从一个主机系统传输到另一个主机系统,而不会对可用性造成任何干扰。您可以永久性更改主机,或者仅在维护期间更改主机。
实时迁移的要求:
- 第 17.2 节 “迁移要求”中所述的所有要求均适用。 
- 只能在具有相同 CPU 功能的 VM 主机服务器之间进行实时迁移。 
- 必须以相同的方式启动源主机和目标主机上的 Guest。 
- 不应使用 - -snapshotqemu 命令行选项进行迁移(不支持此- qemu命令行选项)。
SUSE Linux Enterprise Server 中尚不支持 postcopy 模式。此模式仅发布为技术预览版。有关 postcopy 的详细信息,请参见 https://wiki.qemu.org/Features/PostCopyLiveMigration。
      
以下网站上提供了更多建议:https://www.linux-kvm.org/page/Migration
实时迁移过程包括以下步骤:
- 虚拟机实例正在源主机上运行。 
- 虚拟机以冻结侦听模式在目标主机上启动。使用的参数与源主机上相同,不过还要加上 - -incoming tcp:IP:PORT参数,其中 IP 指定 IP 地址,PORT 指定用于侦听传入迁移的端口。如果设置了 0 作为 IP 地址,则虚拟机将侦听所有接口。
- 在源主机上,切换到监控器控制台,并使用 - migrate -d tcp:DESTINATION_IP:PORT 命令启动迁移。
- 要确定迁移状态,请在源主机上的监控器控制台中使用 - info migrate命令。
- 要取消迁移,请在源主机上的监控器控制台中使用 - migrate_cancel命令。
- 要设置迁移时容许的最长停机时间(以秒为单位),请使用 - migrate_set_downtimeNUMBER_OF_SECONDS 命令。
- 要设置最大迁移速度(每秒字节数),请使用 - migrate_set_speedBYTES_PER_SECOND 命令。
38.11 QMP - QEMU 计算机协议 #
      QMP 是基于 JSON 的协议,可使应用程序(例如 libvirt)能够与运行中的 QEMU 实例通讯。您可以使用 QMP 命令以多种方式访问 QEMU 监控器。
    
38.11.1 通过标准输入/输出访问 QMP #
        最灵活的 QMP 使用方式是指定 -mon 选项。下面的示例使用标准输入/输出创建了一个 QMP 实例。在以下示例中,-> 标记了包含从客户端发送到运行中 QEMU 实例的命令的行,而 <- 标记了包含 QEMU 返回的输出的行。
      
>sudoqemu-system-x86_64 [...] \ -chardev stdio,id=mon0 \ -mon chardev=mon0,mode=control,pretty=on <- { "QMP": { "version": { "qemu": { "micro": 0, "minor": 0, "major": 2 }, "package": "" }, "capabilities": [ ] } }
        建立新的 QMP 连接后,QMP 将发送其问候消息并进入功能协商模式。在此模式下,只有 qmp_capabilities 命令能够正常运行。要退出功能协商模式并进入命令模式,必须先发出 qmp_capabilities 命令:
      
-> { "execute": "qmp_capabilities" }
<- {
    "return": {
    }
}
"return": {} 是 QMP 成功时返回的响应。
      
QMP 的命令可以附带参数。例如,要弹出 CD-ROM 驱动器,请输入以下命令:
->{ "execute": "eject", "arguments": { "device": "ide1-cd0" } }
<- {
    "timestamp": {
        "seconds": 1410353381,
        "microseconds": 763480
    },
    "event": "DEVICE_TRAY_MOVED",
    "data": {
        "device": "ide1-cd0",
        "tray-open": true
    }
}
{
    "return": {
    }
}38.11.2 通过 telnet 访问 QMP #
如果不使用标准输入/输出,您可将 QMP 接口连接到某个网络套接字,并通过特定的端口与其通讯:
>sudoqemu-system-x86_64 [...] \ -chardev socket,id=mon0,host=localhost,port=4444,server,nowait \ -mon chardev=mon0,mode=control,pretty=on
然后运行 telnet 连接到端口 4444:
> telnet localhost 4444
Trying ::1...
Connected to localhost.
Escape character is '^]'.
<- {
    "QMP": {
        "version": {
            "qemu": {
                "micro": 0,
                "minor": 0,
                "major": 2
            },
            "package": ""
        },
        "capabilities": [
        ]
    }
}您可以同时创建多个监控器接口。下面的示例在标准输入/输出上创建了一个 HMP 实例(可识别“常规”QEMU 监控器命令的人工监控器),并在 localhost 端口 4444 上创建了一个 QMP 实例:
>sudoqemu-system-x86_64 [...] \ -chardev stdio,id=mon0 -mon chardev=mon0,mode=readline \ -chardev socket,id=mon1,host=localhost,port=4444,server,nowait \ -mon chardev=mon1,mode=control,pretty=on
38.11.3 通过 Unix 套接字访问 QMP #
        使用 -qmp 选项调用 QEMU,并创建一个 Unix 套接字:
      
>sudoqemu-system-x86_64 [...] \ -qmp unix:/tmp/qmp-sock,server --monitor stdio QEMU waiting for connection on: unix:./qmp-sock,server
        要通过 /tmp/qmp-sock 套接字来与 QEMU 实例通讯,请在同一主机上的另一个终端中使用 nc(有关详细信息,请参见 man 1 nc):
      
>sudonc -U /tmp/qmp-sock <- {"QMP": {"version": {"qemu": {"micro": 0, "minor": 0, "major": 2} [...]
38.11.4 通过 libvirt 的 virsh 命令访问 QMP #
        如果您在 libvirt 下运行虚拟机(请参见第 II 部分 “使用 libvirt 管理虚拟机”),则可以通过运行 virsh
        qemu-monitor-command 来与它的运行中 Guest 通讯:
      
>sudovirsh qemu-monitor-command vm_guest1 \ --pretty '{"execute":"query-kvm"}' <- { "return": { "enabled": true, "present": true }, "id": "libvirt-8" }
        在以上示例中,我们运行了简单的 query-kvm 命令来检查主机是否能够运行 KVM,以及是否启用了 KVM。
      
          要使用 QEMU 的直观易懂的标准输出格式而不是 JSON 格式,请使用 --hmp 选项:
        
>sudovirsh qemu-monitor-command vm_guest1 --hmp "query-kvm"