Finding all snapshots in cluster


May 24, 2022

I am running a 5-node HA ceph cluster. I like to occasionally look for old snapshots that are no longer needed so I can remove them. I have been trying to figure out a good way to scan the entire cluster for snapshots but have not had good results so far. Currently I run this command on each node:

for x in $(qm list | tail +2 | awk '{print $1}'); do echo -n $x; qm status $x -verbose| grep name | cut -d':' -f2; qm listsnapshot $x | grep -v current; done

It's not pretty, but it works in showing the VM ID, name, and all snapshots that each VM may have.

Does anyone have a suggestion on how I can get all the snapshots from the cluster without having to run this on each node?

Thank you!
You should be using API. A good start would be to process output of "pvesh".
i.e.: pvesh get /cluster/resources
Use jq to process json: pvesh get /cluster/resources --output-forma json
You can do all the same stuff you do now, except query entire cluster and any VM or storage.
If you want to run this off the PVE, you can use "curl" to send the APIs.

Blockbridge : Ultra low latency all-NVME shared storage for Proxmox -
I have used pvesh to look at which values are returned, but unless I overlooked it I did not see any snapshot details.
Thanks for the command. Unfortunately when I run it in bash, it errors with
400 too many arguments
Thanks for the command. Unfortunately when I run it in bash, it errors with
What exactly did you run? The code I provided was "pseudo code" few steps away from being runnable directly. Its missing all the "jq" processing. It was meant to point you in the right direction not as a finaloutput.

Blockbridge : Ultra low latency all-NVME shared storage for Proxmox -
Thanks @bbgeek17 for the hints and your code examples in other places. Here is my rough contribution for those needing a quick snapshot list without the hours of figuring out syntax. FYI - it's a *slow* script having to do an API query to every VM to check if there are snapshots, but the script concisely gets the data needed.

#!/usr/bin/env bash

nodes=$(pvesh get /cluster/resources --type vm  --output-format json |jq -r '.[] | [.vmid, .name, .node] | @json')
printf  "processing data ... \n"
for i in $nodes; do
  #printf "\n i= $i" # -- shows all iterations for troubleshooting
  vmid=$(jq -r '.[0]' <<< $i);
  vmname=$(jq -r '.[1]' <<< $i);
  node=$(jq -r '.[2]' <<< $i);
  snapshots=$(pvesh get "/nodes/$node/qemu/$vmid/snapshot" --output-format=json)
  snapdates=$(echo $snapshots | jq -r '[.[] | select(.snaptime) | (.snaptime  | tonumber | todate[:10])] | @csv ');
  if [[ $snapdates ]]; then
    printf "\n $node \t $vmid \t $vmname \t SNAPDATES: $snapdates"
printf "\n processing complete. \n"
Last edited:
if you have many vms and/or are impatient, here is a faster script:
you have to set the variable pool to the name of your pool
pool=<enter your pool name> # "ceph osd pool ls" may help

tmpfile=$(mktemp /tmp/cluster_rescources.XXXXX)
pvesh get /cluster/resources --type vm --output-format json-pretty >> ${tmpfile}
for vmid in $(rbd ls -l -p ${pool}|grep "vm.*@" | cut -c 4-6|uniq); do
    vmname=$(jq -r ".[] | select ( .vmid == ${vmid}) | .name" ${tmpfile})
    node=$(jq -r ".[] | select ( .vmid == ${vmid}) | .node" ${tmpfile})
    filter=".[] | select ( .name != \"current\" ) + {\"vmname\": \"${vmname}\",\"vmid\": \"${vmid}\"} | .snaptime |= strftime(\"%Y-%m-%d\")"
    pvesh get /nodes/${node}/qemu/${vmid}/snapshot --output-format json-pretty | jq "${filter}"
rm ${tmpfile}


The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!