Skip to content
Commitpedia
Log in Join & edit

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.

Edit history of A vzdump wrapper script with checks, retention and a log file: 1 recorded edit
Edit history · 1 edit
Type
Script
Edits
1
Editors
1
First issued
15 Oct 2026
Last edit
15 Oct 2026
Language
bash
Licence
CC0-1.0

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

  1. Checks arguments, that it runs as root, and that vzdump and pvesh exist.
  2. Reads /nodes/<node>/storage/<id>/status and stops if the storage is missing or not active.
  3. Runs vzdump in snapshot mode (or the mode you pass) with --compress zstd, --prune-backups keep-last=N and a notes template.
  4. 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=N deletes 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.

  1. commitpedia-admin +5,007 chars

Report a problem

Something wrong, unsafe or copied? Tell the editors.
What is wrong?