Today I played around a bit with QEMU/KVM. At first I tried to use libvirt as the abstraction layer to hide QEMU, but a few weeks ago I had already read that some user had stability issues with libvirt compared to QEMU without libvirt. Additionally, during my tests for simple use cases I found the QEMU command line API much simpler than the libvirt XML definitions.
However, managing running QEMU Virtual Machines is more difficult without libvirt. libvirt keeps track of all VMs that have been started and provides a command line interface to list running VMs and stop them. QEMU only starts VMs and then basically forgets about them and there seems to be no interface that keeps track of all running VMs.
Then I found out that with QEMU you can set a process name with the
parameter. This parameter accepts a window name and a process name and we
can use the process name to find our VMs with standard linux tools.
So let’s create a few VMs with a custom process name. For simplicity I will only start
Live-CDs and not use pre-created images:
for i in $(seq 1 10); do qemu-system-x86_64 -cdrom archlinux-2020.05.01-x86_64.iso -cpu host \ -enable-kvm -m 1024 -smp 1 \ -name worker-$i,process=qemu-vm-worker-$i -daemonize done
That was easy. To list all started VMs we now only have to search for the
ps -eo comm | grep ^qemu-vm-
One difficulty with this approach is that the process name in
limited to 15 characters.
This is due to a limit enforced by the kernel and can also be seen when
showing the file
This means that either we have to ensure that the process name always has less than or equal to 15 characters or we have to work with the full command line like this:
ps -eo cmd | grep -oP "qemu.+process=\\Kqemu-vm-[a-z0-9-]+"
Process names with at most 15 characters
Knowing the names of our processes we can then retrieve their process ID or
kill them with
# I shortened the VM name in the start script above pgrep qemu-vm-wor-1$ pkill qemu-vm-wor-1$
Process names longer than 15 characters
If we work with process names longer than 15 characters we can still use
have to work with the full command name. Same goes for
pgrep -f process=qemu-vm-worker-1\\b pkill -f process=qemu-vm-worker-1\\b
Of course, killing is no graceful shutdown, but at least we already know how to stop the processes. Shutting down the VMs gracefully without libvirt seems quite a bit more difficult.
A nice way to do this seems to be connecting to the QEMU monitor through a
unix socket and then writing the command
system_powerdown to the monitor.
To test this you can open a socket connection with
qemu-system-x86_64 -cdrom archlinux-2020.05.01-x86_64.iso \ -cpu host -enable-kvm -m 1024 -smp 1 \ -name worker-1,process=qemu-vm-worker-1 \ -daemonize \ -monitor unix:qemu-monitor.sock,server,nowait socat -,echo=0,icanon=0 unix-connect:qemu-monitor.sock
Then boot the machine completely (it will not work if you’re still in the
boot menu) and when it has booted type
system_powerdown into the
socket and press Enter.