Build safe virsh commands for local or remote KVM VMs. 24 actions with risk labels, chained bash scripts, and explicit warnings before destructive ones.
virsh is the command-line front end to libvirt, and it manages KVM/QEMU virtual machines on Linux hosts. It is also a command where two adjacent options do very different things: virsh shutdown asks the guest operating system to close cleanly, while virsh destroy yanks the virtual power cable. Both are one word. This builder assembles correct virsh commands from a form, labels every action with an explicit risk level, and refuses to hand you a destructive command until you have confirmed you understand what it does.
It covers 24 actions across local system, per-user session, and remote SSH connections, chains several into a single bash script, and generates text only. Nothing runs, no host is contacted, and no credentials are collected — you copy the result and execute it yourself.
Every action is classified, and the classification appears as a badge next to the generated command and on each step you add to a script.
| Level | Meaning | Actions |
|---|---|---|
| Read only | Queries state, changes nothing. | list, dominfo, domstate, domstats, domifaddr, domblklist, dumpxml |
| Changes configuration | Alters the VM or its definition without interrupting service. | start, resume, console, autostart, edit, setvcpus, setmem, change-media insert/eject, restore |
| Service interruption | The guest stops serving traffic. | shutdown, reboot, suspend, save |
| Data-loss risk | The guest gets no chance to shut down cleanly, or the definition is removed. | destroy, reset, undefine |
The three danger-zone actions deserve specifics, because their names are misleading if you come from other virtualisation platforms:
virsh destroy does not delete anything. It force-powers-off a running domain — the equivalent of holding the power button. Disks stay, the definition stays. But the guest receives no shutdown signal, so in-flight writes and unflushed filesystem buffers can be lost or corrupted. It is the right tool for a hung VM and the wrong tool for a routine stop.virsh reset is the same hazard in reboot form — a hardware-level reset with no clean guest reboot.virsh undefine is the one that deletes. It removes the persistent domain definition. With the --remove-all-storage option, which this builder exposes behind a separate red-bordered checkbox, it also permanently deletes every libvirt-managed storage volume attached to the domain. That is not recoverable from libvirt.When a destructive command is in your script, the copy button stays disabled until you tick a confirmation stating you have verified the target VM and your backups. That friction is deliberate.
Separately, virsh against the system URI needs privileges — typically membership of the libvirt group, or sudo. The session URI runs unprivileged under your own user account with its own separate set of domains, which is a common source of confusion when a VM that “definitely exists” does not appear in virsh list.
--connect qemu:///system, user session emits qemu:///session, and remote SSH emits qemu+ssh://user@host/system from the username and hostname you supply.#!/usr/bin/env bash, set -euo pipefail, and a numbered comment per step.Values that need it are shell-quoted automatically, so a VM name containing a space or an unusual character produces a safe command rather than a broken one.
Inspect safely on a remote host. Listing every VM on a remote hypervisor over a read-only connection:
virsh --connect qemu+ssh://admin@kvm-host.example.com/system --readonly list --all
The --readonly flag is set automatically for actions that support it. It opens a read-only libvirt connection, which is a genuine guard rather than a courtesy — a typo cannot mutate anything through a read-only handle.
Find a VM’s IP address. Three sources, with different requirements:
virsh --connect qemu:///system domifaddr demo-vm --source lease
DHCP lease lookup works only for interfaces on libvirt-managed networks. The agent source is more reliable but requires the QEMU guest agent installed and running — and it needs a writable connection, so the builder drops --readonly and tells you why. The arp source reads the host ARP table.
Change vCPU count live and persistently.
virsh --connect qemu:///system setvcpus demo-vm 4 --live --config
The scope flags are the important part. --live changes the running VM only, and the change vanishes on next boot. --config changes the persistent definition only, and takes effect at next boot. Both together change each. Forgetting --config is the classic reason a resource change silently reverts after a reboot — which is why the builder defaults to both.
Save a VM’s state to disk.
virsh --connect qemu:///system save demo-vm /var/lib/libvirt/backups/demo-vm.state --verbose
This writes guest RAM and device state to a file and stops the running domain — it is classified as a service interruption for that reason. Restoring later requires the disks to be in a compatible state; restoring a saved state against disks that have changed independently will corrupt guest filesystems, which is exactly the warning the builder attaches to the restore action.
virsh shutdown sends a request to the guest — via the QEMU guest agent, an ACPI power-button event, or whichever libvirt picks by default — and returns immediately. The command succeeding means the request was delivered, not that the guest is down. A VM without a guest agent and with ACPI handling disabled will simply ignore it, which is why an apparently successful shutdown sometimes leaves the domain running. Check with virsh domstate before assuming.
virsh destroy does not ask. It stops the QEMU process immediately. Use it when a guest is genuinely unresponsive and you have accepted the risk to in-flight data — not as the default way to stop a VM.
The same distinction applies to reboot versus reset. Selecting the agent shutdown mode gives the most reliable clean shutdown when the guest agent is present; the builder notes that requirement whenever you choose it.
No. It builds command text in your browser. No SSH connection is made, no libvirt socket is opened, and no credentials are collected. You copy the command and run it yourself, which gives you a chance to check the target name first.
virsh destroy delete my VM?No — despite the name. It force-powers-off a running domain. Disks and the domain definition remain. The command that deletes is virsh undefine, and it only removes storage when you add --remove-all-storage.
qemu:///system and qemu:///session?The system URI connects to the privileged system-wide libvirt daemon and manages the host’s shared VMs; it needs root or libvirt group membership. The session URI runs unprivileged under your own user with a completely separate set of domains and networking. A VM defined under one is invisible from the other.
Because it was applied with --live only, which affects the running VM but not the stored definition. Add --config to persist it. The builder defaults to applying both.
virsh shutdown did nothing. Why?The command only sends a request. If the guest has no QEMU guest agent and is not handling ACPI power events — common on minimal images and on Windows guests at a login screen — nothing responds. Install the guest agent, or accept the data risk and use destroy.
--readonly actually protect against?It opens a read-only libvirt connection, so any state-changing call fails at the library level. It is a useful habit for inspection and for scripts that should never mutate anything. Note that guest-agent address queries require a writable connection and cannot use it.
Yes. The qemu+ssh:// transport needs SSH access to the host with a user that can reach libvirt — in practice, key-based authentication and membership of the libvirt group on the remote machine. The builder generates the URI; it cannot configure access.
virsh console?Press Ctrl+]. The guest must also have a serial console configured, or the connection will attach and show nothing. The builder emits --safe and notes both points.
The VM resource calculator helps size vCPU and memory allocations before you set them, and the Windows Update PowerShell generator covers patching the Windows guests running on those hosts.
virsh is the primary command-line interface for libvirt. It manages virtual machine domains and related libvirt resources, most commonly QEMU/KVM guests on Linux.
qemu:///system connects to the system-wide libvirt daemon and is the normal choice for servers, shared storage, bridges, and administrator-managed VMs. qemu:///session manages VMs owned by the current user and has more limited access to system networking and storage.
No. virsh shutdown sends a clean shutdown request to the guest and returns before the shutdown necessarily finishes. Use virsh domstate to check progress. virsh destroy is the immediate power-off equivalent and risks data loss.
--live changes the currently running VM. --config changes the persistent definition used at the next boot. Supplying both requests the change now and after future starts, when the selected operation and hypervisor support both.
Use a libvirt SSH URI such as virsh --connect qemu+ssh://admin@kvm-host.example.com/system list --all. SSH key authentication is recommended, and the remote account must be authorized to access the system libvirt daemon.
The VM needs a serial device and the guest operating system must be configured to use a serial console. For many Linux guests that means enabling a ttyS0 console in the kernel command line and starting a serial getty. Press Ctrl+] to leave virsh console.
Not by default. virsh undefine removes the persistent domain definition while preserving storage. Adding --remove-all-storage tells libvirt to delete managed volumes too and should be treated as irreversible.