Automatically Restart a Proxmox VM After Backup Completion

Automatically Restart a Proxmox VM After Backup Completion
Restart a Proxmox VM After Backup Completion

πŸ”§ The Opportunity

While managing Proxmox VE environments, many system administrators schedule backups using vzdump, particularly for virtual machines that require cold backups (where the VM must be powered off during the snapshot). However, in some cases, the stop backup mode doesn't work as expected. As a workaround, we may need to manually shut down the VM via a script inside the guest, perform the backup externally, and then restart the VM once the backup is complete.

Unfortunately, Proxmox does not currently offer a built-in mechanism to run a custom script after a backup job completes, which means there's no native way to automatically power the VM back on.

This can lead to undesired downtimeβ€”especially if a VM is critical but remains powered off after a nightly backup.

βœ… The Goal

We needed a reliable and automated way to:

  • Detect when a VM backup has successfully completed.
  • Check if the VM is still powered off.
  • Automatically start the VM only once, and only after a successful backup.

!/bin/bash

VMID=100
LOGFILE="/var/log/start_vm_after_backup_${VMID}.log"
LAST_LOG_FILE="/tmp/last_backup_vm_${VMID}.txt"
VZDUMP_LOG="/var/log/vzdump/qemu-${VMID}.log"
MAX_AGE_SECONDS=3600 # 1 hour

log() {
local LOG_TIME
LOG_TIME=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$LOG_TIME] $1" | tee -a "$LOGFILE"
}

if [[ $EUID -ne 0 ]]; then
echo "❌ This script must be run as root." >&2
exit 1
fi

log "--------------------------------------------------"
log "πŸš€ Script started for VM $VMID"

if [[ ! -f "$VZDUMP_LOG" ]]; then
log "❌ Log file not found: $VZDUMP_LOG"
exit 1
fi

MODIFIED=$(stat -c %Y "$VZDUMP_LOG")
NOW=$(date +%s)
AGE=$((NOW - MODIFIED))

if (( AGE > MAX_AGE_SECONDS )); then
log "⏱️ vzdump log is older than $MAX_AGE_SECONDS seconds β€” skipping."
exit 0
fi

FINISHED_LINE=$(grep "INFO: Finished Backup of VM $VMID" "$VZDUMP_LOG" | tail -n 1)

if [[ -z "$FINISHED_LINE" ]]; then
log "❌ No 'Finished Backup' line found for VM $VMID"
exit 0
fi

FINISHED_TIMESTAMP=$(echo "$FINISHED_LINE" | cut -d' ' -f1,2)
log "πŸ“… Last backup completed at: $FINISHED_TIMESTAMP"

if [[ -f "$LAST_LOG_FILE" ]] && grep -q "$FINISHED_TIMESTAMP" "$LAST_LOG_FILE"; then
log "⏩ Backup already handled (timestamp: $FINISHED_TIMESTAMP)"
exit 0
fi

STATUS=$(qm status "$VMID" | awk '{print $2}')
if [[ "$STATUS" == "running" ]]; then
log "πŸ” VM $VMID is already running. Nothing to do."
else
log "πŸš€ Starting VM $VMID..."
if OUTPUT=$(/usr/sbin/qm start "$VMID" 2>&1); then
log "βœ… VM $VMID started successfully."
else
log "❌ Failed to start VM $VMID"
log "πŸ”Ž Output: $OUTPUT"
exit 1
fi
fi

echo "$FINISHED_TIMESTAMP" > "$LAST_LOG_FILE"
log "πŸ“Œ Backup marked as handled: $FINISHED_TIMESTAMP"

πŸ› οΈ The Bash Script

Here’s the full working script used for VM ID 100. It should be placed somewhere like /root/start_vm_after_backup.sh and made executable.

πŸ“… Scheduling with Cron

To automatically monitor for backups and restart the VM when needed, schedule the script via cron:

*/30 * * * * /root/start_vm_after_backup.sh

This checks every 5 minutes whether a new backup has completed.

πŸ” Final Thoughts

This solution is lightweight, reliable, and avoids unnecessary VM restarts by tracking the exact timestamp of the last successful backup using the vzdump log.

If you're running nightly backups on powered-off VMs and want them back online immediately after the backup completes, this script solves that gap left by Proxmox's lack of post-backup hooks.

βš™οΈ Customizable Parameters

You can easily adjust the script to fit your setup by changing the following variables at the top of the script:

ParameterDescription
VMIDThe ID of the VM to monitor and restart after backup
LOGFILEPath to the log file where script actions and output are saved
LAST_LOG_FILEPath to the file that stores the last handled backup timestamp
VZDUMP_LOGPath to the vzdump log file for the VM (usually /var/log/vzdump/qemu-<VMID>.log)
MAX_AGE_SECONDSMax age (in seconds) for considering a vzdump log "fresh" (default: 3600 = 1 hour)

Feel free to tweak it, fork it, or expand it based on your infrastructure's complexity.

Need help building a multi-VM or HA-aware version? Just let me know!

Privacy PolicyCookie Policy