improve defaults and argument processing.
Loop over VMs inside of main function rather than having 2 backup functions
This commit is contained in:
1 parent
4a0a1ff9a7
commit
fcf6f6008d
1 file changed
+50
-70
+50
-70
@@ -1,64 +1,52 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
# Set default options
|
||||||
|
local cmd="${CMD:-lxc}"
|
||||||
|
local backup_dir="${BACKUP_DIR:-$PWD}"
|
||||||
|
local compression="${COMPRESSION:-zstd}"
|
||||||
|
local vm_list
|
||||||
|
local retention=0
|
||||||
|
|
||||||
while getopts ":l:d:t:x:c:h" opt; do
|
while getopts ":l:d:t:x:c:h" opt; do
|
||||||
case "${opt}" in
|
case "${opt}" in
|
||||||
l)
|
l)
|
||||||
unset VM_FILTER
|
IFS="," read -r -a vm_list <<< "$OPTARG";;
|
||||||
IFS="," read -r -a VM_FILTER <<< "$OPTARG"
|
|
||||||
;;
|
|
||||||
d)
|
d)
|
||||||
local backup_location="${OPTARG}"
|
backup_dir="${OPTARG%/}";;
|
||||||
backup_location="${backup_location%/}"
|
|
||||||
;;
|
|
||||||
t)
|
t)
|
||||||
declare -g TARGET="$OPTARG"
|
cmd="$OPTARG";;
|
||||||
;;
|
|
||||||
x)
|
x)
|
||||||
declare -g EXTENSION
|
compression="$OPTARG";;
|
||||||
if [[ "${OPTARG,,}" == 'none' ]]; then
|
|
||||||
EXTENSION=""
|
|
||||||
else
|
|
||||||
command -v "$OPTARG" >/dev/null 2>&1 || { echo "$OPTARG command not found"; exit 1; }
|
|
||||||
EXTENSION="${OPTARG,,}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
declare -g COMPRESSION="$OPTARG"
|
|
||||||
;;
|
|
||||||
c)
|
c)
|
||||||
declare -g run_cleanup=y
|
retention="${OPTARG}";;
|
||||||
declare -g files_to_keep="${OPTARG}"
|
h|*)
|
||||||
;;
|
usage;;
|
||||||
h)
|
|
||||||
usage
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
usage
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
backup_location=${backup_location:-$PWD}
|
# Helper functions
|
||||||
|
lxc() { command "$cmd" "$@"; }
|
||||||
|
list_vms() { lxc list -c n -f csv; }
|
||||||
|
|
||||||
if [[ "${#VM_FILTER[*]}" -gt 0 ]]; then
|
if ((${#vm_list[@]} == 0)); then
|
||||||
backup_vms "$backup_location" "${VM_FILTER[@]}"
|
mapfile -t vm_list < <(list_vms)
|
||||||
else
|
|
||||||
backup_vms "$backup_location"
|
|
||||||
fi
|
fi
|
||||||
}
|
|
||||||
|
|
||||||
lxc() {
|
for vm in "${vm_list[@]}"; do
|
||||||
local lxc_cmd="${TARGET:-lxc}"
|
start_backup "$vm" "$backup_dir" "$compression"
|
||||||
command "$lxc_cmd" "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
list_vms() {
|
if (( retention > 0 )); then
|
||||||
lxc list -c n -f csv
|
prune_backups "$vm" "$backup_dir" "$retention"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
Usage: ${0##*/} [-l vm[,vm...]] [-d backup_dir] [-t lxc|incus] [-x <compression alogorithm>] [-c <keep n backups>] [-h]
|
Usage: ${0##*/} [-l vm[,vm...]] [-d <backup directory>] [-t lxc|incus] [-x <compression alogorithm>] [-c <keep last n backups>] [-h]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-l Comma-separated list of VMs to back up
|
-l Comma-separated list of VMs to back up
|
||||||
@@ -72,47 +60,39 @@ EOF
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
backup_vms() {
|
|
||||||
local backup_location="$1"; shift
|
|
||||||
local vms=("$@")
|
|
||||||
|
|
||||||
# when no argument use list of all VMs
|
|
||||||
if ((${#vms[@]} == 0)); then
|
|
||||||
mapfile -t vms < <(list_vms)
|
|
||||||
fi
|
|
||||||
|
|
||||||
for vm in "${vms[@]}"; do
|
|
||||||
[[ -n $vm ]] || continue
|
|
||||||
start_backup "$vm" "$backup_location"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
start_backup() {
|
start_backup() {
|
||||||
local vm=$1
|
local vm=$1
|
||||||
local backup_base="$2"
|
local backup_dir="$2"
|
||||||
local compression="${COMPRESSION:-none}"
|
local compression="$3"
|
||||||
local ext="${EXTENSION}" ; [[ -n "$ext" ]] && ext=".${ext}"
|
local ext=".${compression}"
|
||||||
local destination="${backup_base}/${vm}"
|
|
||||||
|
if [[ "$compression" == 'none' ]]; then
|
||||||
|
ext=""
|
||||||
|
else
|
||||||
|
command -v "$compression" >/dev/null 2>&1 || { echo "$compression command not found"; exit 1; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
local vm_dir="${backup_dir}/${vm}"
|
||||||
|
|
||||||
local backup_name
|
local backup_name
|
||||||
backup_name="${vm}_$(date +"%Y-%m-%d_%H-%M-%S").tar${ext}"
|
backup_name="${vm}_$(date +"%Y-%m-%d_%H-%M-%S").tar${ext}"
|
||||||
|
|
||||||
[[ -d "$backup_base" ]] || { echo "${backup_base} is not a directory"; exit 1; }
|
[[ -d "$backup_dir" ]] || { echo "${backup_dir} is not a directory"; exit 1; }
|
||||||
[[ -d "$destination" ]] || mkdir "$destination"
|
[[ -d "$vm_dir" ]] || mkdir "$vm_dir" || { echo "Cannont create $vm_dir"; exit 1; }
|
||||||
[[ -f "${destination}/${backup_name}" ]] && { echo "Backup already exists"; return 2; }
|
[[ -f "${vm_dir}/${backup_name}" ]] && { echo "Backup already exists"; return 2; }
|
||||||
|
echo "starting $vm"
|
||||||
lxc export "$vm" --instance-only --compression "${compression}" "${destination}/${backup_name}" || { echo "Error exporting $vm"; return 1; }
|
lxc export "$vm" --instance-only --compression "${compression}" "${vm_dir}/${backup_name}" || { echo "Error exporting $vm"; return 1; }
|
||||||
|
|
||||||
[[ -n "$run_cleanup" ]] && prune_backups "$destination"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prune_backups() {
|
prune_backups() {
|
||||||
local backup_directory="$1"
|
local vm="$1"
|
||||||
mapfile -t backup_files < <(find "$backup_directory" -maxdepth 1 -type f -printf '%T@ %p\n' | sort -n | head -n "-${files_to_keep}" | cut -d' ' -f2-)
|
local backup_dir="$2"
|
||||||
|
local retention="$3"
|
||||||
|
mapfile -t backup_files < <(find "${backup_dir}/${vm}" -maxdepth 1 -type f -printf '%T@ %p\n' | sort -n | head -n "-${retention}" | cut -d' ' -f2-)
|
||||||
|
|
||||||
if [[ ${#backup_files[@]} -gt 0 ]]; then
|
if [[ ${#backup_files[@]} -gt 0 ]]; then
|
||||||
echo "Removing ${#backup_files[@]} old backup files for $vm (keeping last $files_to_keep files)"
|
echo "Removing ${#backup_files[@]} old backup files for $vm (keeping last $retention files)"
|
||||||
printf '%s\0' "${backup_files[@]}" | xargs -0 rm -fv
|
printf '%s\0' "${backup_files[@]}" | xargs -0 rm -fv > /dev/null
|
||||||
else
|
else
|
||||||
echo "No old backups to remove for $vm"
|
echo "No old backups to remove for $vm"
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in new issue
Block a user