удаление test-контура (дополнение)

This commit is contained in:
2026-09-14 20:50:40 +03:00
parent dafbf5bad4
commit 101c457f7e
27 changed files with 195 additions and 375 deletions
+9 -58
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# Бэкапы Forbidden Stars с ПК (Linux / macOS / Git Bash). Команды уходят в контейнер backup
# прода на Pi по SSH или (с --test) в локальный тест-клон (docker-compose.test.yml).
# На Windows удобнее scripts/fs-backup.ps1 — поведение то же. Инструкция: deploy/backup/README.md
# прода на Pi по SSH. На Windows удобнее scripts/fs-backup.ps1 — поведение то же.
# Инструкция: deploy/backup/README.md
#
# scripts/fs-backup.sh status состояние бэкапов на Pi
# scripts/fs-backup.sh list [vps] хронология снимков
@@ -9,9 +9,6 @@
# scripts/fs-backup.sh verify проверить целостность данных
# scripts/fs-backup.sh pull [<id>|latest] [--repo vps]
# скачать снимок в backups/ (сверка sha256)
# scripts/fs-backup.sh restore-test <файл.tar|.tar.gz>
# учебное восстановление в локальный тест-клон
# --test первым аргументом — status/list/now/verify/pull для локального тест-клона
#
# Настройки — из корневого .env (переменная окружения с тем же именем важнее):
# BACKUP_PI_SSH как зайти на Pi по SSH, например pi@192.168.1.10 (или Host из ~/.ssh/config)
@@ -19,8 +16,6 @@
set -euo pipefail
PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
TEST_COMPOSE="$PROJECT_DIR/docker-compose.test.yml"
export MSYS_NO_PATHCONV=1 # Git Bash: не переписывать /import/... в аргументах docker
die() { echo "ОШИБКА: $*" >&2; exit 1; }
@@ -35,10 +30,7 @@ setting() { # setting <ключ> <по умолчанию>: окружение,
PI_SSH="$(setting BACKUP_PI_SSH "")"
# shellcheck disable=SC2088 # тильда намеренно не раскрывается здесь — её раскроет shell на Pi
PI_DIR="$(setting BACKUP_PI_DIR "~/forbidden-stars")"
TARGET="pi"
if [ "${1:-}" = "--test" ]; then TARGET="test"; shift; fi
native_path() { if command -v cygpath >/dev/null 2>&1; then cygpath -w "$1"; else printf '%s' "$1"; fi; }
sha256() { if command -v sha256sum >/dev/null 2>&1; then sha256sum "$1" | cut -d' ' -f1; else shasum -a 256 "$1" | cut -d' ' -f1; fi; }
pi() { # pi <shell-команда>: выполнить на Pi в папке прода
@@ -46,22 +38,8 @@ pi() { # pi <shell-команда>: выполнить на Pi в папке п
ssh -o ConnectTimeout=15 "$PI_SSH" "cd $PI_DIR && $1"
}
tc() { docker compose -f "$(native_path "$TEST_COMPOSE")" "$@"; }
start_test_backup() {
if [ -z "$(tc ps -q backup 2>/dev/null)" ]; then
echo "Запускаю контейнер backup тест-клона…"
tc up -d --build backup
fi
}
fs() { # fs <аргументы fs-backup…>
if [ "$TARGET" = test ]; then
start_test_backup
tc exec -T backup fs-backup "$@"
else
pi "docker compose exec -T backup fs-backup $*"
fi
fs() { # fs <аргументы fs-backup…>: выполнить fs-backup в контейнере backup на Pi
pi "docker compose exec -T backup fs-backup $*"
}
cmd_pull() {
@@ -84,18 +62,10 @@ cmd_pull() {
partial="$local_file.part"
echo "Снимок $id ($repo) -> $local_file"
if [ "$TARGET" = test ]; then
start_test_backup
local tmp="/tmp/fs-backup/export-$id.tar"
expected="$(tc exec -T backup sh -c "fs-backup export $id --repo $repo > $tmp && sha256sum $tmp" | tail -n 1 | cut -d' ' -f1)"
tc cp "backup:$tmp" "$(native_path "$partial")" || { tc exec -T backup rm -f "$tmp"; die "копирование из контейнера не удалось"; }
tc exec -T backup rm -f "$tmp"
else
local remote="fs-export-$id.tar"
expected="$(pi "docker compose exec -T backup fs-backup export $id --repo $repo > ~/$remote && sha256sum ~/$remote" | tail -n 1 | cut -d' ' -f1)"
scp -o ConnectTimeout=15 "$PI_SSH:$remote" "$partial" || { pi "rm -f ~/$remote"; die "scp не удался"; }
pi "rm -f ~/$remote"
fi
local remote="fs-export-$id.tar"
expected="$(pi "docker compose exec -T backup fs-backup export $id --repo $repo > ~/$remote && sha256sum ~/$remote" | tail -n 1 | cut -d' ' -f1)"
scp -o ConnectTimeout=15 "$PI_SSH:$remote" "$partial" || { pi "rm -f ~/$remote"; die "scp не удался"; }
pi "rm -f ~/$remote"
actual="$(sha256 "$partial")"
if [ "$expected" != "$actual" ]; then
@@ -107,24 +77,6 @@ cmd_pull() {
echo "OK: $local_file ($(du -h "$local_file" | cut -f1), $(tar -tf "$local_file" | grep -vc '/$') файлов, sha256 сверена)"
}
cmd_restore_test() {
local file="${1:-}"
[ -n "$file" ] || die "укажите архив: scripts/fs-backup.sh restore-test backups/fs_....tar"
[ -f "$file" ] || die "файл не найден: $file"
local in_container=/import/restore-test.archive # tar или tar.gz — формат fs-backup определит сам
echo "Учебное восстановление $file в ЛОКАЛЬНЫЙ ТЕСТ-КЛОН (прод не затрагивается)."
start_test_backup
tc stop app
tc cp "$(native_path "$file")" "backup:$in_container"
local rc=0
tc exec -T backup fs-backup import "$in_container" --yes || rc=$?
tc exec -T backup rm -f "$in_container"
[ "$rc" -eq 0 ] || die "импорт не удался (код $rc) — данные тест-клона не изменены."
tc up -d app
echo "Готово: тест-клон работает на восстановленных данных."
echo " На https://forbidden-stars.ru: docker compose -f docker-compose.test.yml up -d (или ./run.sh при APP_ENV=test)"
}
cmd="${1:-help}"
[ $# -eq 0 ] || shift
case "$cmd" in
@@ -133,6 +85,5 @@ case "$cmd" in
now) fs run "$@" ;;
verify) fs verify ;;
pull) cmd_pull "$@" ;;
restore-test) cmd_restore_test "$@" ;;
*) sed -n '2,19p' "$0" | sed 's/^# \{0,1\}//' ;;
*) sed -n '2,15p' "$0" | sed 's/^# \{0,1\}//' ;;
esac