virsh es la herramienta de línea de comandos de libvirt para administrar máquinas virtuales KVM. Con ella se hace todo lo que ofrece una interfaz gráfica como virt-manager: arrancar y apagar VMs, cambiar CPU y memoria, añadir discos, tomar snapshots o exportar la configuración, y además se puede automatizar en scripts.

En este tutorial recorrerás las tareas de administración más habituales sobre una VM de ejemplo llamada vm1 en un anfitrión con Ubuntu 24.04. Los comandos son los mismos en cualquier distribución con libvirt.

Requisitos previos

  • Un anfitrión con Ubuntu 24.04 LTS con KVM, QEMU y libvirt instalados, y tu usuario en el grupo libvirt. La guía de instalación de KVM/QEMU en Linux explica cómo prepararlo.
  • Al menos una VM creada. Los ejemplos usan vm1 con un disco en /var/lib/libvirt/images/vm1.qcow2.
  • La variable LIBVIRT_DEFAULT_URI=qemu:///system en tu ~/.bashrc, o ejecutar los comandos con sudo.

Paso 1: Conectarte a libvirt y listar VMs

libvirt tiene dos instancias: qemu:///system, con las VMs del sistema, y qemu:///session, privada de cada usuario. Comprueba a cuál te conectas:

virsh uri
qemu:///system

También puedes gestionar un anfitrión remoto por SSH sin iniciar sesión en él, indicando la URI con -c:

virsh -c qemu+ssh://your_user@your_server_ip/system list --all

Lista todas las VMs definidas, en marcha o no:

virsh list --all
 Id   Name   State
-----------------------
 1    vm1    running
 -    vm2    shut off

Las VMs apagadas no tienen Id. Para ver solo las apagadas usa virsh list --inactive.

virsh help lista todos los comandos agrupados por categoría y virsh help comando explica las opciones de uno concreto, por ejemplo virsh help shutdown.

Paso 2: Consultar el estado de una VM

dominfo resume la configuración y el estado:

virsh dominfo vm1
Id:             1
Name:           vm1
UUID:           5d1c7f0e-3a2b-4c8e-9f11-2b7a0c6d8e41
OS Type:        hvm
State:          running
CPU(s):         2
CPU time:       41.3s
Max memory:     2097152 KiB
Used memory:    2097152 KiB
Persistent:     yes
Autostart:      disable
Managed save:   no
Security model: apparmor
Security DOI:   0

Otros comandos útiles de consulta:

virsh domblklist vm1
virsh domiflist vm1
virsh domifaddr vm1
  • domblklist muestra los discos y su ruta en el anfitrión.
  • domiflist muestra las interfaces de red, su red de libvirt y su MAC.
  • domifaddr muestra la IP que la VM obtuvo por DHCP de la red de libvirt.

Para ver el uso de CPU, memoria, disco y red en un solo informe, usa virsh domstats vm1.

Paso 3: Arrancar, apagar y reiniciar

Arranca una VM apagada:

virsh start vm1

Apágala de forma ordenada. shutdown envía la señal de apagado ACPI al sistema invitado, que cierra sus servicios como si pulsaras el botón de encendido:

virsh shutdown vm1

El comando vuelve enseguida; el apagado tarda unos segundos. Compruébalo con virsh domstate vm1, que mostrará shut off al terminar. Si el invitado tiene qemu-guest-agent, puedes pedir el apagado a través del agente, que es más fiable:

virsh shutdown vm1 --mode agent

Para reiniciar de forma ordenada:

virsh reboot vm1

Si la VM está colgada y no responde a shutdown, destroy la para de inmediato, como quitarle la corriente. No borra nada, pero puede corromper datos que no se hubieran escrito en disco:

virsh destroy vm1

virsh suspend vm1 congela la VM en memoria y virsh resume vm1 la reanuda al instante.

Paso 4: Configurar el arranque automático

Para que una VM arranque junto con el anfitrión, márcala con autostart:

virsh autostart vm1

Compruébalo:

virsh dominfo vm1 | grep Autostart
Autostart:      enable

Para desactivarlo:

virsh autostart --disable vm1

Paso 5: Acceder a la consola

virsh console abre la consola serie de la VM, útil cuando la red del invitado no funciona. Las imágenes cloud de Ubuntu y Debian la tienen activada por defecto:

virsh console vm1
Connected to domain 'vm1'
Escape character is ^] (Ctrl + ])

vm1 login:

Pulsa Enter si no aparece el prompt y sal con Ctrl+]. Si la consola queda en blanco, el invitado no tiene una consola en ttyS0; accede por SSH o activa console=ttyS0 en su cargador de arranque.

Paso 6: Cambiar CPU y memoria

libvirt distingue entre el valor actual y el máximo configurado. La forma más segura es cambiar la configuración persistente (--config) con la VM apagada y arrancarla después.

Apaga la VM y espera a que virsh domstate vm1 muestre shut off:

virsh shutdown vm1

Sube la memoria a 4 GB. Primero el máximo y luego el valor asignado:

virsh setmaxmem vm1 4G --config
virsh setmem vm1 4G --config

Sube las vCPU a 4. Igual que con la memoria, primero el máximo:

virsh setvcpus vm1 4 --config --maximum
virsh setvcpus vm1 4 --config

Arranca la VM y verifica los nuevos valores:

virsh start vm1
virsh dominfo vm1 | grep -E 'CPU\(s\)|memory'
CPU(s):         4
Max memory:     4194304 KiB
Used memory:    4194304 KiB

Dentro del invitado, nproc y free -h deben mostrar lo mismo.

Paso 7: Añadir y ampliar discos

Crea un disco de datos de 10 GB en formato qcow2:

sudo qemu-img create -f qcow2 /var/lib/libvirt/images/vm1-datos.qcow2 10G

Conéctalo a la VM como vdb. --live lo añade ya a la VM en marcha y --config lo guarda en la configuración para los siguientes arranques:

virsh attach-disk vm1 /var/lib/libvirt/images/vm1-datos.qcow2 vdb --driver qemu --subdriver qcow2 --targetbus virtio --live --config

Verifícalo:

virsh domblklist vm1
 Target   Source
---------------------------------------------------
 vda      /var/lib/libvirt/images/vm1.qcow2
 vdb      /var/lib/libvirt/images/vm1-datos.qcow2

Dentro de la VM aparecerá como /dev/vdb, listo para particionar y formatear.

Para ampliar un disco existente con la VM en marcha, usa blockresize con el tamaño final:

virsh blockresize vm1 vda 30G

Después tendrás que ampliar la partición y el sistema de archivos dentro del invitado (por ejemplo con growpart y resize2fs). Reducir un disco no es seguro con este método.

Para quitar el disco de datos:

virsh detach-disk vm1 vdb --live --config

Paso 8: Trabajar con snapshots

Una snapshot guarda el estado de los discos (y de la memoria si la VM está en marcha) para poder volver atrás, por ejemplo antes de actualizar el sistema. Con discos qcow2, libvirt crea snapshots internas dentro del propio archivo:

virsh snapshot-create-as vm1 --name antes-update --description "Antes de actualizar paquetes"

Lista las snapshots de la VM:

virsh snapshot-list vm1
 Name           Creation Time               State
---------------------------------------------------
 antes-update   2026-09-25 11:02:17 +0000   running

Si la actualización sale mal, vuelve al estado guardado. Todo lo que cambió desde la snapshot se pierde:

virsh snapshot-revert vm1 antes-update

Cuando ya no la necesites, bórrala para liberar espacio:

virsh snapshot-delete vm1 antes-update

Paso 9: Guardar, editar y clonar la configuración

Cada VM se define en un XML. Guárdalo como copia de seguridad antes de cambios importantes:

virsh dumpxml vm1 > ~/vm1.xml

Para cambiar opciones que no tienen comando propio, edita el XML con virsh edit. Abre el editor definido en $EDITOR y valida el XML al guardar:

virsh edit vm1

Los cambios se aplican en el siguiente arranque completo de la VM (apagar y arrancar, no reiniciar desde dentro).

Si borraste la definición, puedes volver a registrarla desde el XML guardado:

virsh define ~/vm1.xml

Para crear una copia de una VM apagada con discos y MAC nuevos, usa virt-clone, incluido en el paquete virtinst:

virsh shutdown vm1

Cuando virsh domstate vm1 muestre shut off, clona la VM:

virt-clone --original vm1 --name vm1-clon --auto-clone

Recuerda que el clon tiene el mismo hostname y las mismas claves SSH de host que el original; cámbialos antes de usarlo en producción.

Paso 10: Eliminar una VM

undefine elimina la definición de la VM. Por defecto conserva los discos, así que puedes volver a crearla con virsh define:

virsh destroy vm1-clon
virsh undefine vm1-clon

Para borrar también todos sus discos, añade --remove-all-storage. Si la VM usa UEFI, añade --nvram, y si tiene snapshots, --snapshots-metadata:

virsh undefine vm1-clon --remove-all-storage

Solución de problemas

  • error: failed to get domain 'vm1': el nombre no existe en la conexión actual. Revisa virsh list --all y virsh uri; puede que la VM esté en qemu:///system y estés en qemu:///session.
  • virsh shutdown no apaga la VM: el invitado no atiende ACPI (por ejemplo, sin acpid o parado en el cargador). Usa --mode agent si tiene el agente, o virsh destroy como último recurso.
  • setvcpus o setmem fallan con un error sobre el máximo: el valor supera el máximo configurado. Sube primero --maximum o setmaxmem con la VM apagada.
  • internal snapshots of a VM with pflash based firmware are not supported: la VM usa UEFI. Usa virsh snapshot-create-as vm1 --name nombre --disk-only o una copia con la VM apagada.

Conclusión

Con virsh puedes cubrir todo el ciclo de vida de una VM KVM: consultar su estado, arrancarla y apagarla, ajustar CPU, memoria y discos, protegerla con snapshots y exportar o eliminar su definición. Como siguientes pasos:

  • Configura redes aisladas, enrutadas o en puente para tus VMs con virsh net-*.
  • Automatiza copias de seguridad de los discos con un script programado con un timer de systemd.
  • Consulta man virsh para operaciones avanzadas como la migración en vivo entre anfitriones.