Virtualization

Virsh Commands: Complete KVM & libvirt Cheat Sheet (2026)

Use virsh to list, inspect, start, stop, configure, and safely remove KVM virtual machines. Includes tested local and remote libvirt commands.

By InventiveHQ Team

Episode 3 of the InventiveHQ KVM virtualization series. It reuses the Ubuntu guest created in Episode 2 and prepares it for the storage and networking lessons.

virsh is the command-line control panel for libvirt-managed virtual machines. If you need to find a guest, inspect its disks, change its CPU allocation, open its console, or shut it down without a GUI, this is the tool you use.

This walkthrough uses the guest created in Episode 2 to establish a baseline, change CPU and memory, verify live and persistent state, recover through the console, and review safe deletion.

Verified July 2026 · tested with libvirt 12.0.0, QEMU 10.2.1 and nested KVM on Ubuntu 26.04 LTS

Use the builder to generate exact local, session, or remote commands. It identifies read-only operations, service interruptions, and commands that can delete data before you copy anything to a terminal.

Quick reference: essential virsh commands

# Inventory and inspection
virsh list --all
virsh dominfo demo-vm
virsh domstate demo-vm
virsh domblklist demo-vm
virsh domifaddr demo-vm --source lease

# Lifecycle
virsh start demo-vm
virsh shutdown demo-vm
virsh reboot demo-vm
virsh suspend demo-vm
virsh resume demo-vm
virsh console demo-vm --safe

# Persistent configuration
virsh autostart demo-vm
virsh dumpxml demo-vm --inactive > demo-vm.xml
virsh edit demo-vm

# Resources
virsh setvcpus demo-vm 4 --live --config
virsh setmem demo-vm 4096MiB --live --config

The safe default is to inspect before changing anything:

virsh list --all
virsh dominfo demo-vm
virsh dumpxml demo-vm --inactive > demo-vm.before.xml

That XML export gives you a copy of the persistent definition before a resource or device change. It does not copy the VM's disks or RAM and is not a complete backup.

How KVM, QEMU, libvirt and virsh fit together

These names are frequently treated as synonyms, but each has a separate job:

  • KVM is the Linux kernel virtualization capability that uses CPU hardware acceleration.
  • QEMU provides the virtual machine process and emulated or paravirtualized devices.
  • libvirt manages VM definitions, processes, networks, storage and security policy through a stable API.
  • virsh is the command-line client for that libvirt API.

A libvirt-managed VM is called a domain. That is why commands use names such as dominfo, domstate, domifaddr and domblklist.

Use libvirt rather than finding a QEMU PID and changing the process directly. Libvirt understands the persistent definition, applies host security labels, coordinates device operations and handles differences between hypervisor versions.

Choose the correct libvirt connection

Most unexplained virsh problems begin with connecting to the wrong libvirt scope.

System connection

virsh --connect qemu:///system list --all

qemu:///system connects to the system-wide QEMU/libvirt service. It is the normal choice for servers, administrator-managed guests, host bridges, shared storage and VMs that start at boot.

Depending on the distribution, access may come from membership in a libvirt group, polkit authorization, or root privileges. Prefer the distribution's authorization model to running every command through unrestricted sudo.

User session connection

virsh --connect qemu:///session list --all

qemu:///session manages domains owned by the current user. It is useful for desktop or development VMs but has more limited access to system networking and storage.

If virsh list --all returns an empty list while a graphical manager shows running guests, compare these explicitly:

virsh --connect qemu:///system list --all
virsh --connect qemu:///session list --all

They are separate collections. A domain created in one does not automatically appear in the other.

Remote connection over SSH

virsh --connect qemu+ssh://admin@kvm-host.example.com/system list --all

This connects to the remote system libvirt service through SSH. Use SSH keys, confirm the host key, and authorize the remote account for libvirt. The remote host needs the libvirt daemon or modular sockets running, but it does not need a separately exposed TCP management port.

For repeated commands, set the URI for the current shell:

export LIBVIRT_DEFAULT_URI='qemu+ssh://admin@kvm-host.example.com/system'
virsh list --all
virsh dominfo demo-vm

List virtual machines

The unqualified list shows only running domains:

virsh list

Add --all to include shut-off domains:

virsh list --all

Useful filters include:

# Stopped domains only
virsh list --inactive

# Names only, suitable for a shell loop
virsh list --all --name

# Persistent domains configured to start with the host
virsh list --all --persistent --autostart

For read-only automation, request a read-only connection:

virsh --connect qemu:///system --readonly list --all

Inspect VM status and configuration

General domain information

virsh dominfo demo-vm

dominfo reports the state, UUID, CPU count, current and maximum memory, persistence, autostart setting and security model. It is the quickest single check before a change.

For only the current state:

virsh domstate demo-vm

Common results include running, paused and shut off. Lifecycle commands return after sending a request, so scripts should query state rather than assuming the transition has completed.

CPU, memory, disk and network statistics

virsh domstats demo-vm \
  --state \
  --cpu-total \
  --balloon \
  --block \
  --interface

Unlike the compact dominfo output, domstats returns machine-friendly counters. It can show CPU time, memory balloon information, bytes read and written per disk, network traffic and backing-chain details.

List guest disks

virsh domblklist demo-vm

Example:

 Target   Source
------------------------------------------------
 vda      /var/lib/libvirt/images/demo-vm.qcow2
 sda      /var/lib/libvirt/images/installer.iso

The target is the virtual device name in the domain definition. The source is the host file, block device or managed volume backing it.

Find the VM's IP address

There are three useful sources:

# Libvirt-managed DHCP lease
virsh domifaddr demo-vm --source lease

# QEMU guest agent inside the VM
virsh domifaddr demo-vm --source agent

# Host ARP table
virsh domifaddr demo-vm --source arp

Lease lookup works well for the default libvirt NAT network. It may return nothing for a guest on a host bridge whose address came from an external DHCP server.

Agent lookup can see addresses reported from inside the guest but requires qemu-guest-agent to be installed, running and attached. It also requires a normal writable libvirt connection: libvirt rejects domifaddr --source agent through virsh --readonly.

Start, shut down and reboot VMs

Start an inactive domain

virsh start demo-vm

The domain must have a persistent definition. If you only have an XML definition, import it first with virsh define file.xml.

Request a clean shutdown

virsh shutdown demo-vm

This asks the guest OS to shut down. It is not an immediate power-off and it does not wait for completion.

Check progress:

virsh domstate demo-vm

You can request a specific mechanism:

virsh shutdown demo-vm --mode agent
virsh shutdown demo-vm --mode acpi

Agent mode requires the QEMU guest agent. ACPI requires the guest to respond to a virtual power-button event. With no mode, libvirt selects an available method, which is usually the best default.

Request a clean reboot

virsh reboot demo-vm

As with shutdown, this returns when the request is sent rather than when the VM has finished rebooting. A guest agent can also reject a reboot—for example, when the guest OS has an active shutdown inhibitor—so automation must check the exit status and guest state.

Pause and resume a VM

virsh suspend demo-vm
virsh domstate demo-vm
virsh resume demo-vm

Suspend pauses guest CPU execution but keeps its memory allocated on the host. It is useful for short administrative pauses, not long-term capacity recovery. Use save when you need to release the guest's allocated RAM.

Connect to the serial console

First confirm the domain exposes a console device:

virsh ttyconsole demo-vm

Then connect:

virsh console demo-vm --safe

Press Ctrl+] to disconnect from the console without stopping the VM.

A blank console usually means the guest is not configured to use its serial port. Linux cloud images commonly enable ttyS0; manually installed guests may require a kernel console argument and a serial getty.

--safe refuses to connect if another session already owns the console, preventing two administrators from accidentally sharing the same character stream.

Start a VM automatically with its host

Enable autostart:

virsh autostart demo-vm

Disable it:

virsh autostart demo-vm --disable

Verify the result:

virsh dominfo demo-vm | grep Autostart

Autostart does not guarantee application readiness. A bridged VM can still fail if its host starts the domain before the bridge or remote storage is online.

Export and edit domain XML

Export the persistent definition

virsh dumpxml demo-vm --inactive > demo-vm.xml

--inactive requests the definition that will be used on the next start. Without it, a running guest's XML can include live-only state.

Keep exports out of public repositories until reviewed. Domain XML can contain MAC addresses, host paths, source URLs, device identifiers and, in some configurations, secret references.

Edit with validation

virsh edit demo-vm

This opens the definition in $VISUAL or $EDITOR and validates the XML before replacing the persistent configuration. XML that is structurally valid can still describe unsupported hardware, so export the previous definition first.

To define or redefine a persistent domain from a file:

virsh define demo-vm.xml

define does not start the domain. Run virsh start demo-vm separately.

Change vCPUs and memory

Understand live and persistent scopes

  • --live changes the running VM.
  • --config changes the definition used at its next start.
  • --live --config requests both.
  • --current uses the active context chosen by libvirt.

Do not assume a live change persists across reboot.

Change the vCPU count

virsh setvcpus demo-vm 4 --live --config

The live count cannot exceed the maximum vCPU count declared in the domain. The guest OS must also support CPU hotplug for an online increase or decrease.

Libvirt can attach the processors successfully while Linux still leaves them offline. Verify inside the guest:

lscpu | grep -E 'On-line|Off-line'

If the new processors appear in the offline list, review the target CPUs and online them explicitly:

for cpu in /sys/devices/system/cpu/cpu*/online; do
  [ "$(cat "$cpu")" = 0 ] && echo 1 | sudo tee "$cpu"
done
nproc

In the verified Ubuntu guest, CPUs 2 and 3 were present but offline after the live hotplug. Onlining them changed nproc from 2 to 4. A clean boot from the persistent four-vCPU definition also brings all four online.

Check the result:

virsh dominfo demo-vm | grep 'CPU(s)'
virsh vcpucount demo-vm

Change current memory

virsh setmem demo-vm 4096MiB --live --config

setmem changes current memory rather than the maximum ceiling. A live reduction or increase normally depends on the virtio balloon device and guest driver. The command can succeed before the guest has finished adjusting, so compare dominfo, dommemstat and monitoring inside the guest.

Changing maximum memory is a separate operation and frequently requires an offline domain:

virsh setmaxmem demo-vm 8192MiB --config

Insert or eject ISO media

Find the virtual CD-ROM target first:

virsh domblklist demo-vm

If the CD-ROM target is sda, eject it from the running and persistent configurations:

virsh change-media demo-vm sda --eject --live --config

Insert an ISO:

virsh change-media demo-vm sda \
  /var/lib/libvirt/images/installer.iso \
  --insert \
  --live \
  --config

This changes an existing removable-media device. It does not create a missing CD-ROM controller or device.

Save and restore running state

Save RAM and virtual-device state to a file:

virsh save demo-vm /var/lib/libvirt/backups/demo-vm.state --verbose

When the save completes, the domain is no longer running and its host memory is released.

Restore it:

virsh restore /var/lib/libvirt/backups/demo-vm.state

A save-state file does not contain the VM disks. The disks must still represent the same point in time when restored. Restoring saved RAM against independently changed disks can corrupt the guest, so save/restore is not a substitute for a coordinated backup.

Force operations: destroy and reset

These are emergency controls, not normal shutdown commands.

# Immediate power-off
virsh destroy demo-vm

# Immediate virtual hardware reset
virsh reset demo-vm

destroy stops the running instance but preserves the persistent definition and disk files. reset keeps the domain running while resetting its virtual hardware. Neither gives the guest OS time to flush application or filesystem data.

Use them only when a guest is unresponsive and a clean shutdown or reboot has failed.

Remove a VM definition safely

Preserve disks

virsh shutdown old-vm
virsh undefine old-vm

This removes the persistent libvirt definition but preserves storage. Record the output of domblklist and export the XML before undefining if you may need to reconstruct it.

Delete managed storage too

virsh undefine old-vm --remove-all-storage

This is irreversible. In our disposable validation lab, a cloned VM retained a virtual CD-ROM backed by the same cloud-init ISO as its source. Running --remove-all-storage against the clone deleted both its qcow2 disk and the shared ISO. A storage attachment is not necessarily exclusive to one domain.

Before using the flag:

virsh domblklist old-vm --details
virsh dumpxml old-vm --inactive > old-vm.before-delete.xml

Check every source path and confirm that no other domain uses it:

virsh list --all --name | while read -r vm; do
  [ -n "$vm" ] && virsh domblklist "$vm"
done

Troubleshooting common virsh errors

The VM list is unexpectedly empty

Compare system and session connections:

virsh -c qemu:///system list --all
virsh -c qemu:///session list --all

Permission denied connecting to libvirt

Check the URI and your distribution's libvirt authorization. On many systems, log out and back in after adding a user to the relevant group so the new membership reaches the shell.

id
virsh uri

Shutdown does nothing

Confirm that the guest agent or ACPI shutdown mechanism works:

virsh shutdown demo-vm --mode agent
virsh shutdown demo-vm --mode acpi

Do not automatically escalate to destroy without checking application and storage consequences.

Guest-agent IP lookup fails through readonly

This fails by design:

virsh --readonly domifaddr demo-vm --source agent

Use a normal authorized connection for the agent query:

virsh domifaddr demo-vm --source agent

A live resource change succeeds but the value looks unchanged

The guest may still be processing CPU hotplug or memory ballooning. Inspect both libvirt and the guest OS, and verify the persistent definition separately:

virsh dominfo demo-vm
virsh dumpxml demo-vm --inactive

A safe operating sequence

For a routine VM change, use this pattern:

# 1. Confirm the target and current state
virsh dominfo demo-vm
virsh domblklist demo-vm

# 2. Save the persistent definition
virsh dumpxml demo-vm --inactive > demo-vm.before.xml

# 3. Make one scoped change
virsh setvcpus demo-vm 4 --live --config

# 4. Verify live and persistent results
virsh dominfo demo-vm
virsh dumpxml demo-vm --inactive > demo-vm.after.xml

The command builder at the top can chain inspection and configuration operations into one reviewable script. It deliberately requires a second confirmation before copying any script that contains destroy, reset or undefine.

Official references

Frequently Asked Questions

What is virsh?

virsh is the command-line interface for libvirt. It manages virtual machine domains and other libvirt resources. On Linux it is most commonly used to control QEMU/KVM guests, but the command talks to libvirt rather than directly to the QEMU process.

How do I list all KVM virtual machines with virsh?

Run 'virsh list --all'. Without --all, virsh shows only running domains. Use 'virsh list --inactive' for stopped domains or 'virsh list --all --name' when a script needs names without the table.

What is the difference between virsh shutdown and destroy?

virsh shutdown asks the guest operating system to shut down cleanly. virsh destroy immediately stops the virtual hardware, like pulling a physical server's power cable. Destroy does not delete the VM definition or disks, but it can cause data loss or filesystem corruption.

What do --live and --config mean in virsh?

--live changes the currently running VM. --config changes the persistent definition used on its next start. Supplying both requests the change now and for future boots, if that command and hypervisor support both modes. --current lets libvirt choose the current context.

How do I find a KVM guest's IP address?

Use 'virsh domifaddr VM --source lease' for guests on a libvirt DHCP network. Use '--source agent' when the QEMU guest agent is installed and running, or '--source arp' to consult the host ARP table. Guest-agent queries require a normal writable libvirt connection and fail through --readonly.

Why is virsh console blank?

The VM must have a serial device and its guest OS must send a login console to that device, commonly ttyS0 on Linux. Check the domain with 'virsh ttyconsole VM'. Connect with 'virsh console VM --safe' and press Ctrl+] to disconnect.

Does virsh undefine delete the virtual machine disks?

Not by default. 'virsh undefine VM' removes the persistent libvirt definition but preserves disk files. Adding --remove-all-storage asks libvirt to delete every managed storage volume attached to the definition, which can include media shared with another VM.

How do I manage a remote KVM host with virsh?

Use a libvirt SSH URI, such as 'virsh --connect qemu+ssh://admin@kvm-host.example.com/system list --all'. Configure SSH key authentication and ensure the remote user is authorized to access the system libvirt daemon.

Need help from an IT & cybersecurity partner?

InventiveHQ helps businesses secure, modernize, and run their technology. Let's talk about your goals.

Get in touch