A vzdump wrapper script with checks, retention and a log file
A Bash wrapper around vzdump that checks the target storage first, backs up chosen guests or all guests with zstd and keep-last retention, writes a log and lists failed guests.
Not checked by a trusted editor yet Last edited Outdated?
What this changes
As root, runs vzdump to write new zstd backups of the chosen guests to STORAGE and prunes it to the newest KEEP_LAST per guest (default 7), deleting older ones. Writes a log in /var/log/pve-backup-wrapper. Modes stop and suspend pause guests.
How to undo it
Remove an unwanted backup in the web UI or with pvesm free VOLID. Pruned backups cannot be recovered: raise -k or copy older backups elsewhere before running.
Scheduled backup jobs in the web UI cover most needs. A small wrapper is still useful for ad-hoc runs before maintenance, for cron on standalone nodes, or as a building block for your own automation. This script validates its input, confirms the target storage is active through the API, runs vzdump with consistent options and keeps a log per run.
What it does
- Checks arguments, that it runs as root, and that
vzdumpandpveshexist. - Reads
/nodes/<node>/storage/<id>/statusand stops if the storage is missing or not active. - Runs
vzdumpin snapshot mode (or the mode you pass) with--compress zstd,--prune-backups keep-last=Nand a notes template. - Saves output to
/var/log/pve-backup-wrapper/, returns vzdump’s exit code and prints lines for failed guests.
Script
#!/usr/bin/env bash
# pve-backup.sh - run vzdump for selected guests with sane defaults and a log
# License: CC0-1.0
# Usage: pve-backup.sh -s STORAGE [-k KEEP_LAST] [-m MODE] (-a | VMID...)
# -s target storage ID (must allow the "backup" content type)
# -k how many backups per guest to keep on that storage (default 7)
# -m snapshot | suspend | stop (default snapshot)
# -a back up all guests on this node
set -euo pipefail
storage=""
keep_last=7
mode="snapshot"
all=0
log_dir="/var/log/pve-backup-wrapper"
usage() {
echo "Usage: $0 -s STORAGE [-k KEEP_LAST] [-m snapshot|suspend|stop] (-a | VMID...)" >&2
exit 2
}
while getopts ":s:k:m:a" opt; do
case "$opt" in
s) storage="$OPTARG" ;;
k) keep_last="$OPTARG" ;;
m) mode="$OPTARG" ;;
a) all=1 ;;
*) usage ;;
esac
done
shift $((OPTIND - 1))
[ -n "$storage" ] || usage
[[ "$keep_last" =~ ^[1-9][0-9]*$ ]] || { echo "Error: -k must be a positive number" >&2; exit 2; }
case "$mode" in snapshot|suspend|stop) ;; *) usage ;; esac
if [ "$all" -eq 0 ] && [ "$#" -eq 0 ]; then usage; fi
for id in "$@"; do
[[ "$id" =~ ^[0-9]+$ ]] || { echo "Error: '$id' is not a VMID" >&2; exit 2; }
done
if [ "$(id -u)" -ne 0 ]; then
echo "Error: run as root on a Proxmox VE node." >&2
exit 1
fi
for cmd in vzdump pvesh; do
command -v "$cmd" >/dev/null 2>&1 || { echo "Error: '$cmd' not found - is this a Proxmox VE node?" >&2; exit 1; }
done
node=$(hostname)
status_json=$(pvesh get "/nodes/$node/storage/$storage/status" --output-format json 2>/dev/null) || {
echo "Error: storage '$storage' not found on node '$node'." >&2
exit 1
}
if ! grep -Eq '"active"[[:space:]]*:[[:space:]]*1' <<<"$status_json"; then
echo "Error: storage '$storage' is not active on node '$node'." >&2
exit 1
fi
mkdir -p "$log_dir"
log_file="$log_dir/backup-$(date +%Y%m%d-%H%M%S).log"
args=(--storage "$storage" --mode "$mode" --compress zstd
--prune-backups "keep-last=$keep_last"
--notes-template '{{guestname}} on {{node}}')
if [ "$all" -eq 1 ]; then
args+=(--all 1)
targets="all guests"
else
targets="$*"
fi
echo "Backing up $targets to '$storage' (mode=$mode, keep-last=$keep_last)"
echo "Log: $log_file"
set +e
if [ "$all" -eq 1 ]; then
vzdump "${args[@]}" 2>&1 | tee "$log_file"
else
vzdump "$@" "${args[@]}" 2>&1 | tee "$log_file"
fi
rc=${PIPESTATUS[0]}
set -e
if [ "$rc" -eq 0 ]; then
echo "Backup finished successfully."
else
echo "Backup finished with errors (exit code $rc). Failed guests:" >&2
grep -E '^ERROR: Backup of VM [0-9]+ failed' "$log_file" >&2 || echo " see $log_file" >&2
fi
exit "$rc"
Usage
chmod +x pve-backup.sh
./pve-backup.sh -s nas-backup 110 111
./pve-backup.sh -s nas-backup -k 14 -a
./pve-backup.sh -s nas-backup -m stop 200
Example cron entry for a nightly run at 01:30 on a standalone node (/etc/cron.d/pve-backup):
30 1 * * * root /usr/local/sbin/pve-backup.sh -s nas-backup -k 7 -a
Notes
--prune-backups keep-last=Ndeletes older backups of each guest on that storage beyond N. If the storage already has a retention policy you rely on, adjust or remove that option so the two do not conflict.- The node name is taken from
hostname, which matches the Proxmox VE node name on a standard install. - In a cluster, prefer a backup job under Datacenter → Backup: it runs on every node and is visible to all administrators.
- Test a restore of the resulting files regularly.
Official documentation
See also
- 0058 Safe bash script template with set ‑euo pipefail and trap A starting point for bash scripts that stops on errors, rejects unset variables, cleans up temp files on exit and parses options.… Intermediate · Reference · Linux, macOS Script Shell scripting 15 Oct 2026
- 0059 Incremental snapshot backups with rsync A bash script that copies a folder into dated snapshots with rsync, hard-links unchanged files to the previous snapshot to save space,… Advanced · How-to · Linux, macOS Script Backups & syncing · Shell scripting 15 Oct 2026
- 0061 Fix: Address already in use (free a busy port) Your server cannot start because another process already listens on its port. This script shows which process holds the port and stops… Intermediate · Fix · Linux, macOS Script Processes & ports · Shell scripting 15 Oct 2026
- 0106 Back up and restore guests with vzdump, backup jobs and Proxmox Backup Server Back up Proxmox VE VMs and containers with vzdump, choose a backup mode, schedule backup jobs with retention, restore with qmrestore or… Intermediate · How-to · Linux Article Backup & restore 15 Oct 2026
- 0108 List all Proxmox VE guests with status and locks (pvesh + jq) A Bash script that lists every VM and container in the cluster with node, status, lock, memory and uptime, using the Proxmox… Intermediate · Reference · Linux Script Shell scripting · VMs & containers 15 Oct 2026
- 0110 Fix: TASK ERROR: VM is locked (backup) A VM or container still carries a backup lock, usually after a backup was interrupted. Check that no backup is running, then… Beginner · Fix · Linux Article Backup & restore · VMs & containers 15 Oct 2026
History
Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.
- Commitpedia +5,007 chars