Files
homelab-docs/scripts/restore-one-vzdump-from-restic.sh

111 lines
4.3 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Восстановление одного файла vzdump из restic (Yandex S3) через mount.
# Не выкачивает весь репозиторий — подгружаются только нужные данные для выбранного файла.
# Запускать на хосте Proxmox под root. Требуется FUSE (restic mount).
#
# Использование:
# restore-one-vzdump-from-restic.sh [SNAPSHOT] [ПУТЬ_В_СНИМКЕ] [КУДА_СОХРАНИТЬ]
#
# Пример (последний снимок, CT 107, сохранить в /mnt/backup):
# ./restore-one-vzdump-from-restic.sh
# ./restore-one-vzdump-from-restic.sh latest /mnt/backup/proxmox/dump/dump/vzdump-lxc-107-2026_02_26-02_03_14.tar.zst /mnt/backup
#
# Список снимков: restic snapshots
# Список файлов в снимке: restic ls SNAPSHOT
set -e
ENV_FILE="${ENV_FILE:-/root/.restic-yandex.env}"
MOUNT_DIR="${MOUNT_DIR:-/mnt/backup/restic-mount}"
RESTIC_PASSWORD_FILE="${RESTIC_PASSWORD_FILE:-/root/.restic-password}"
SNAPSHOT="${1:-latest}"
# Путь к файлу внутри снимка (как в restic ls) — бэкапим /mnt/backup, пути вида /mnt/backup/proxmox/dump/dump/vzdump-lxc-107-...
FILE_IN_SNAPSHOT="${2:-}"
OUTPUT_DIR="${3:-/mnt/backup}"
if [ "$(id -u)" -ne 0 ]; then
echo "Запускайте под root."
exit 1
fi
if [ ! -f "$ENV_FILE" ]; then
echo "Нет файла $ENV_FILE. Скопируйте restic-yandex-env.example и задайте ключи."
exit 1
fi
# shellcheck source=/dev/null
source "$ENV_FILE"
for var in RESTIC_REPOSITORY AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY; do
if [ -z "${!var}" ]; then
echo "В $ENV_FILE не задано: $var"
exit 1
fi
done
export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY RESTIC_REPOSITORY
export RESTIC_PASSWORD_FILE
export AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION:-ru-central1}"
if ! command -v restic >/dev/null 2>&1; then
echo "restic не установлен. Установите: apt install restic."
exit 1
fi
if [ -z "$FILE_IN_SNAPSHOT" ]; then
echo "Использование: $0 [SNAPSHOT] ПУТЬ_В_СНИМКЕ [КУДА_СОХРАНИТЬ]"
echo "Пример: $0 latest /mnt/backup/proxmox/dump/dump/vzdump-lxc-107-2026_02_26-02_03_14.tar.zst /mnt/backup"
echo ""
echo "Доступные снимки:"
restic snapshots 2>/dev/null || true
exit 1
fi
# Resolve "latest" to snapshot ID (restic mount показывает ids/<short-id>/)
if [ "$SNAPSHOT" = "latest" ]; then
SNAPSHOT_ID=$(restic snapshots 2>/dev/null | grep -E '^[a-f0-9]{8}[[:space:]]' | tail -1 | awk '{print $1}')
else
SNAPSHOT_ID="$SNAPSHOT"
fi
[ -z "$SNAPSHOT_ID" ] && echo "Не удалось определить ID снимка." && exit 1
echo "Снимок: $SNAPSHOT_ID"
mkdir -p "$OUTPUT_DIR"
mkdir -p "$MOUNT_DIR"
# Проверяем, не смонтировано ли уже
if mountpoint -q "$MOUNT_DIR" 2>/dev/null; then
echo "Точка монтирования $MOUNT_DIR уже занята. Размонтируйте: fusermount -u $MOUNT_DIR"
exit 1
fi
echo "Монтируем репозиторий в $MOUNT_DIR ..."
restic mount "$MOUNT_DIR" &
MOUNT_PID=$!
trap 'kill $MOUNT_PID 2>/dev/null; fusermount -u "$MOUNT_DIR" 2>/dev/null; exit' EXIT INT TERM
# В смонтированном репо файлы снимка лежат в ids/<short_id>/<путь>
SOURCE_FILE="$MOUNT_DIR/ids/$SNAPSHOT_ID/$FILE_IN_SNAPSHOT"
for i in $(seq 1 45); do
if [ -e "$SOURCE_FILE" ] 2>/dev/null; then
break
fi
sleep 1
done
if [ ! -e "$SOURCE_FILE" ]; then
echo "Файл не найден: $SOURCE_FILE (подождали 45 с). Проверьте: restic ls $SNAPSHOT_ID"
exit 1
fi
BASENAME_FILE="$(basename "$FILE_IN_SNAPSHOT")"
OUTPUT_FILE="$OUTPUT_DIR/$BASENAME_FILE"
echo "Копируем $SOURCE_FILE -> $OUTPUT_FILE ..."
cp "$SOURCE_FILE" "$OUTPUT_FILE"
echo "Готово: $OUTPUT_FILE ($(du -sh "$OUTPUT_FILE" | cut -f1))"
# Размонтировать
kill $MOUNT_PID 2>/dev/null || true
wait $MOUNT_PID 2>/dev/null || true
fusermount -u "$MOUNT_DIR" 2>/dev/null || true
trap - EXIT INT TERM
echo "Размонтировано. Для восстановления контейнера:"
echo " pct create NEW_VMID $OUTPUT_FILE --restore 1 --storage local-lvm"