Howto list all running QEMU VMs for a project
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 -name
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
prefix qemu-vm-
:
ps -eo comm | grep ^qemu-vm-
One difficulty with this approach is that the process name in ps
is
limited to 15 characters.
This is due to a limit enforced by the kernel and can also be seen when
showing the file /proc/<procnum>/comm
.
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 pgrep
and pkill
:
# 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 pgrep
but
have to work with the full command name. Same goes for pkill
.
pgrep -f process=qemu-vm-worker-1\\b
pkill -f process=qemu-vm-worker-1\\b
Exits
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 socat
:
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.