hostnamectl; # tested on 
   Static hostname: lenovo
  Operating System: Debian GNU/Linux 10 (buster)
            Kernel: Linux 4.19.0-17-amd64
      Architecture: x86-64

hostnamectl; # also on
Operating System: Debian GNU/Linux 12 (bookworm) 
Kernel: Linux 6.1.0-17-amd64

# with
virsh --version
# also with

libvirtd --version
libvirtd (libvirt) 5.0.0
# also with
libvirtd (libvirt) 9.0.0

/usr/bin/kvm --version
QEMU emulator version 3.1.0 (Debian 1:3.1+dfsg-8+deb10u8)
Copyright (c) 2003-2018 Fabrice Bellard and the QEMU Project developers

kvm qemu shutdown all vms

cat /scripts/

echo "=== shutting down all kvm vms ==="
for i in $(virsh list | grep running | awk '{print $2}'); do virsh shutdown $i; done
virsh list --all

# example:

start all vms with keyword in name

cat /scripts/
echo "=== starting all kvm vms that contain the word $1 ==="
for i in $(virsh list --all | grep $1 | awk '{print $2}'); do virsh start $i; done
virsh list --all

# example:
/scripts/ keyword


# create a snapshot1 of debian12
virsh snapshot-create-as --domain debian12 --name "snapshot1"
# if the user wants to add a more detailed description
virsh snapshot-create-as --domain debian12 --name "snapshot1" --description "details"

# list all snapshots fo debian12
virsh snapshot-list debian12

# restore-revert to snapshot snapshot1
virsh snapshot-revert --domain debian12 --snapshotname snapshot1

# delete snapshot1
virsh snapshot-delete --domain debian12 --snapshotname snapshot1

in general: how to iterate over all vms:

iterate over all vmnames:

# make sure
# the user is the logged in as user
# that is allowed to "see" all virtual machines
# (per default that is only root)
su - root
virsh list

# if there is a list of vmnames ok let's continue
# iterate over all vmnames
for VM_NAME in $(virsh list | grep running | awk '{print $2}'); do echo $VM_NAME; done

get all mac of all vms

this only works if vms have dhcp assigned addresses of the network “default”!

# iterate over all vms by name
for VM_NAME in $(virsh list | grep running | awk '{print $2}'); do echo $VM_NAME; virsh  dumpxml  $VM_NAME | grep 'mac address'; done

# sample output:
<mac address='52:54:00:da:f7:6f'/>
<mac address='52:54:00:3d:9d:53'/>
<mac address='52:54:00:66:5b:79'/>
<mac address='52:54:00:60:78:19'/>

for VM_NAME in $(virsh list | grep running | awk '{print $2}'); do echo $VM_NAME; virsh dumpxml $VM_NAME | grep 'mac address'| grep -oP "mac address='\K[^']+"; done
# sample output

# alternatively (only lists all dhcp assigned ips)
# list all virtual networks
virsh net-list

# setup the default dhcp network (the dhcp will not be public only on the local machine)
virsh net-start default
virsh net-autostart default

virsh net-dhcp-leases default

 Expiry Time           MAC address         Protocol   IP address           Hostname    Client ID or DUID
 2024-01-08 13:08:39   52:54:00:15:XX:XX   ipv4   ubuntu      ff:56:50:4d:...
 2024-01-08 13:42:21   52:54:00:95:XX:XX   ipv4   debian12    ff:00:95:9d:6e:...
 2024-01-08 13:40:09   52:54:00:aa:XX:XX   ipv4   vmname   -


su - root
apt install netdiscover
# arp scans local network

command might be useful (does active/passive ARP scanning)

if this all did not help: checkout the hacks and scripts

snapshot all vms:

cat /scripts/
echo "=== virsh: snapshot all vms ==="
for i in $(virsh list --all | awk '(NR>2)' | awk '{print $2}'); do virsh snapshot-create $i; done
virsh list --all

# example:
=== virsh: snapshot all vms ===
Domain snapshot 1628801587 created
Domain snapshot 1628801587 created
Domain snapshot 1628801587 created
Domain snapshot 1628801587 created
Domain snapshot 1628801587 created
 Id   Name               State
 -    ansible.master     shut off
 -    ansible.srv1       shut off
 -    ansible.srv2       shut off
 -    ansible.srv3       shut off
 -    debian10template   shut off

# list all snapshots of a vmname
virsh snapshot-list --domain vmname
# revert vmname to snapshotname
virsh snapshot-revert vmname snapshotname

automatically revert to snapshot, start vm and connect to vm:

vim /scripts/kvm-qemu/

(needs to be run as root)


  1. vmname
  2. snapshotname
  3. user is the user that is running the x11 desktop 🙂
echo "=== revert to working snapshot ==="
virsh snapshot-revert vmname snapshotname

echo "=== starting vm ==="
virsh start vmname
export DISPLAY=':0.0'
/usr/bin/cp -fv /home/user/.Xauthority /root/.Xauthority
virt-viewer 'vmname'

clone vm

# clone "vmname"
# even if a "may exceed disk" warning: if the original disk image is thin provisioned the cloned one will be too
virt-clone --original vmname --name vmname-clone --file /where/disk/image/vmname-clone.qcow2 --check disk_size=off

# if the vm has multiple disk files
# things get a bit more complicated
# as the user has to give the --file parameter for every harddisk.qcow2 file in use
virt-clone --original vmname --name vmname-clone --auto-clone --check disk_size=off --file /path/vmname-clone/disk1 --file /path/vmname-clone/disk2 --file /path/vmname-clone/disk3 --file /path/vmname-clone/disk4

delete vm

# forecefull shutdown of vm
virsh destroy --domain vmname
# del disk images
# RAM save states
# delete all snapsnots too
virsh undefine --domain vmname --remove-all-storage --managed-save --snapshots-metadata

add or remove a disk

in theory there is a command that can do that, practically it is currenty NOT working.

so here is how to do it:

# power down the vm
# thin provision create the new disks

qemu-img create -f qcow2 /home/user/vms/kvm/vmname.disk1.qcow2 1024G
qemu-img create -f qcow2 /home/user/vms/kvm/vmname.disk2.qcow2 1024G
qemu-img create -f qcow2 /home/user/vms/kvm/vmname.disk3.qcow2 1024G
qemu-img create -f qcow2 /home/user/vms/kvm/vmname.disk4.qcow2 1024G

# edit vm config file 
vim /etc/libvirt/qemu/vmname.xml

# find the section that says
<disk type='file' device='disk'>

# afterwards insert:
# note that the hex number bus='0x64' (dec: 100)
# needs to be INCREMENTED (+1) for every new disk (max is hex:ff = dec:255)
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/home/user/vms/kvm/vmname.disk1.qcow2'/>
<target dev='vdb' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x64' slot='0x00' function='0x0'/>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/home/user/vms/kvm/vmname.disk2.qcow2'/>
<target dev='vdc' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x65' slot='0x00' function='0x0'/>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/home/user/vms/kvm/vmname.disk3.qcow2'/>
<target dev='vdd' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x66' slot='0x00' function='0x0'/>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/home/user/vms/kvm/vmname.disk4.qcow2'/>
<target dev='vde' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x67' slot='0x00' function='0x0'/>

neat tips:

the user can (mostly always) attach

virsh somecommand --running

which means: immediately after doing somecommand start the vm again


GNU Linux kvm how to get list of all IPs of all vms

liked this article?

  • only together we can create a truly free world
  • plz support dwaves to keep it up & running!
  • (yes the info on the internet is (mostly) free but beer is still not free (still have to work on that))
  • really really hate advertisement
  • contribute: whenever a solution was found, blog about it for others to find!
  • talk about, recommend & link to this blog and articles
  • thanks to all who contribute!