#!/bin/sh # # Purpose {{{ # This script will hardlink latest Proxmox's backup with a explicit name. # # This script is intended to be used as a hook script for the Proxmox # VZDump utility. # # In order to use it, use the configuration directive "script" of the # vzdump utility. This can be done for scheduled backups by putting # "script: /path/to/this/script" in /etc/vzdump.conf. Don't forget to # set executable permission for the script file. # # Based on RobHost's vzdump_hook script : # https://github.com/robhost/proxmox-scripts/blob/master/vzdump_hook.sh # }}} # Vars {{{ readonly PROGNAME=$(basename "${0}") readonly ARGS="${*}" [ -z "${DEBUG}" ] && DEBUG=0 ## Export DEBUG for sub-script export DEBUG ## Colors readonly PURPLE='\033[1;35m' readonly RED='\033[0;31m' readonly RESET='\033[0m' readonly COLOR_DEBUG="${PURPLE}" # }}} usage() { # {{{ cat <<- HELP usage: ${PROGNAME} [-h] Hardlink latest Proxmox's backup with a explicit name. OPTIONS : -h,--help Print this help message. HELP } # }}} debug_message() { # {{{ local_debug_message="${1}" local_temp_log="/tmp/pve.log" if [ ! -f "${local_temp_log}" ]; then true > "${local_temp_log}" fi ## Print message if DEBUG is enable (=0) [ "${DEBUG}" -eq "0" ] && printf '\e[1;35m%-6b\e[m\n' "DEBUG − ${PROGNAME} : ${local_debug_message}" >> "${local_temp_log}" unset local_debug_message return 0 } # }}} error_message() { # {{{ local_error_message="${1}" local_error_code="${2}" ## Print message printf '%b\n' "ERROR − ${PROGNAME} : ${RED}${local_error_message}${RESET}" exit "${local_error_code:=66}" } # }}} main() { # {{{ debug_message "main − \ ARGS=${ARGS} env=$(env)" # If backup is complete {{{ if [ "${phase}" = "backup-end" ]; then ## Get TARGET's file extension target_archive_extension="$(printf '%s' "${TARGET}" | sed -n "s/.*\.\([[:alnum:]]*\.[[:alnum:]]*\)$/\1/p")" ## Set path for LATEST archive file latest_archive="${dumpdir}/vzdump-${vmtype}-${vmid}-latest.${target_archive_extension}" debug_message "backup-end − \ target_archive_extension=${target_archive_extension} latest_archive=${latest_archive}" ## hardlink TARGET archive to LATEST debug_message "hardlink TARGET archive (${target_archive}) to \ LATEST (${latest_archive})." ln --force "${target_archive}" "${latest_archive}" fi # }}} # If log is complete {{{ if [ "${phase}" = "log-end" ]; then ## Set path for LATEST log file latest_log="${dumpdir}/vzdump-${vmtype}-${vmid}-latest.log" debug_message "log-end − \ latest_log=${latest_log}" ## hardlink TARGET log to LATEST debug_message "hardlink TARGET logs (${logfile}) to \ LATEST (${latest_log})." ln --force "${logfile}" "${latest_log}" fi # }}} debug_message "---" } # }}} # Manage arguments # {{{ # This code can't be in a function due to argument management phase="${1}" # (job|backup)-(start|end|abort)|log-end|pre-(stop|restart)|post-restart case "${phase}" in # set variables for the phases #backup-start|backup-end|backup-abort|log-end|pre-stop|pre-restart|post-restart) #;; # do work job-init|job-start|job-end|job-abort) # Available vars {{{ # Arguments : job-start #LVM_SUPPRESS_FD_WARNINGS=1 #DUMPDIR=/path/to/backup/dump #STOREID=backup.id.from.storage.cfg # }}} ;; backup-start|backup-end|backup-abort) # Available vars {{{ #ARGS=backup-start stop vm.id #HOSTNAME=hostname.domain.tld #TARGET=/path/to/backup/dump/vzdump-$VMTYPE_VALUE-$2_VALUE-YYYY_MM_DD-hh-mm-ss.tar.zst #LOGFILE=/path/to/backup/dump/vzdump-$VMTYPE_VALUE-$2_VALUE-YYYY_MM_DD-hh-mm-ss.log #LVM_SUPPRESS_FD_WARNINGS=1 #DUMPDIR=/path/to/backup/dump #VMTYPE=lxc|qemu #STOREID=backup.id.from.storage.cfg # }}} vmid="${3}" target_archive="${TARGET}" dumpdir="${DUMPDIR}" vmtype="${VMTYPE}" ;; log-end) # Available vars {{{ #ARGS=log-end stop vm.id #HOSTNAME=hostname.domain.tld #TARGET=/path/to/backup/dump/vzdump-$VMTYPE_VALUE-$2_VALUE-YYYY_MM_DD-hh-mm-ss.tar.zst #LOGFILE=/path/to/backup/dump/vzdump-$VMTYPE_VALUE-$2_VALUE-YYYY_MM_DD-hh-mm-ss.log #LVM_SUPPRESS_FD_WARNINGS=1 #DUMPDIR=/path/to/backup/dump #VMTYPE=lxc|qemu #STOREID=backup.id.from.storage.cfg # }}} vmid="${3}" logfile="${LOGFILE}" dumpdir="${DUMPDIR}" vmtype="${VMTYPE}" ;; pre-stop) ;; pre-restart) ;; post-restart) ;; *) error_message "Unknown phase ${phase}." 1 ;; esac # }}} main exit 0