fix(ops): бэкап без выгрузки в S3 падает, а не рапортует успех #3086
6 changed files with 122 additions and 18 deletions
|
|
@ -24,10 +24,12 @@
|
||||||
# Usage (cron — note `bash`, not a bare path, so +x is irrelevant):
|
# Usage (cron — note `bash`, not a bare path, so +x is irrelevant):
|
||||||
# 30 3 * * * bash /opt/gendesign/ops/backup.sh >> /var/log/gendesign-backup.log 2>&1
|
# 30 3 * * * bash /opt/gendesign/ops/backup.sh >> /var/log/gendesign-backup.log 2>&1
|
||||||
#
|
#
|
||||||
# Optional S3 upload — set these in /etc/default/gendesign-backup (root-owned,
|
# S3 upload — REQUIRED by default (#3085). Set these in /etc/default/gendesign-backup
|
||||||
# chmod 600, NOT in git). Without them, dumps stay local only:
|
# (root-owned, chmod 600, NOT in git). Without all four, the script fails
|
||||||
|
# LOUDLY before taking a dump — set BACKUP_ALLOW_LOCAL_ONLY=1 to explicitly
|
||||||
|
# accept a local-only backup instead (e.g. local testing):
|
||||||
# S3_ENDPOINT=https://s3.ru-1.storage.selcloud.ru # Selectel S3
|
# S3_ENDPOINT=https://s3.ru-1.storage.selcloud.ru # Selectel S3
|
||||||
# S3_BUCKET=gendesign-backups
|
# S3_BUCKET=gendsgn-backups
|
||||||
# S3_ACCESS_KEY=...
|
# S3_ACCESS_KEY=...
|
||||||
# S3_SECRET_KEY=...
|
# S3_SECRET_KEY=...
|
||||||
# A redacted template lives at ops/gendesign-backup.default.example.
|
# A redacted template lives at ops/gendesign-backup.default.example.
|
||||||
|
|
@ -64,6 +66,28 @@ SENTINEL_FILE="${SENTINEL_FILE:-${LOCAL_BACKUP_DIR}/.last_success}"
|
||||||
# Optional S3 env. Loaded from /etc/default/gendesign-backup if present.
|
# Optional S3 env. Loaded from /etc/default/gendesign-backup if present.
|
||||||
[[ -f /etc/default/gendesign-backup ]] && source /etc/default/gendesign-backup
|
[[ -f /etc/default/gendesign-backup ]] && source /etc/default/gendesign-backup
|
||||||
|
|
||||||
|
# --- guard: S3 upload is REQUIRED by default (#3085). A backup that only
|
||||||
|
# lives on the same disk as the DB it protects is not a backup once
|
||||||
|
# Poincare has no configured fallback host to copy from — before this
|
||||||
|
# guard, a missing/incomplete /etc/default/gendesign-backup made the
|
||||||
|
# script log "backup stays local only" and exit 0, indistinguishable
|
||||||
|
# from a real off-box backup in the cron log. Fail LOUD, before the dump
|
||||||
|
# is even taken (no point spending time/disk on a dump that can't leave
|
||||||
|
# the box). BACKUP_ALLOW_LOCAL_ONLY=1 is the explicit escape hatch for
|
||||||
|
# running on a box without S3 creds on purpose (e.g. local testing) —
|
||||||
|
# it still warns loudly so it can't be forgotten silently. ---
|
||||||
|
if [[ -z "${S3_ENDPOINT:-}" || -z "${S3_BUCKET:-}" || -z "${S3_ACCESS_KEY:-}" || -z "${S3_SECRET_KEY:-}" ]]; then
|
||||||
|
if [[ "${BACKUP_ALLOW_LOCAL_ONLY:-0}" == "1" ]]; then
|
||||||
|
log "WARNING: S3 vars not fully set — BACKUP_ALLOW_LOCAL_ONLY=1, proceeding with a LOCAL-ONLY backup. This copy will NOT survive loss of this VM." >&2
|
||||||
|
BACKUP_LOCAL_ONLY_USED=1
|
||||||
|
else
|
||||||
|
log "ERROR: S3 upload is not configured — missing one or more of S3_ENDPOINT / S3_BUCKET / S3_ACCESS_KEY / S3_SECRET_KEY." >&2
|
||||||
|
log "ERROR: fill them into /etc/default/gendesign-backup (see ops/gendesign-backup.default.example)," >&2
|
||||||
|
log "ERROR: or set BACKUP_ALLOW_LOCAL_ONLY=1 to explicitly accept a local-only backup." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Integrity check beyond "non-empty"/"big enough": a dump truncated mid-write
|
# Integrity check beyond "non-empty"/"big enough": a dump truncated mid-write
|
||||||
# (disk full, OOM-kill, docker exec dropped) can still gzip into a structurally
|
# (disk full, OOM-kill, docker exec dropped) can still gzip into a structurally
|
||||||
# valid, non-tiny .gz — neither `-s` nor MIN_DUMP_BYTES catch that reliably.
|
# valid, non-tiny .gz — neither `-s` nor MIN_DUMP_BYTES catch that reliably.
|
||||||
|
|
@ -161,7 +185,8 @@ fi
|
||||||
|
|
||||||
log "Globals dump OK: ${globals_out} ($(du -h "$globals_out" | cut -f1))"
|
log "Globals dump OK: ${globals_out} ($(du -h "$globals_out" | cut -f1))"
|
||||||
|
|
||||||
# --- optional S3 upload (only if all four vars present) — both the main dump
|
# --- S3 upload (only if all four vars present — guaranteed unless the
|
||||||
|
# BACKUP_ALLOW_LOCAL_ONLY escape hatch above was used) — both the main dump
|
||||||
# and the globals dump go up, same bucket, same layout. ---
|
# and the globals dump go up, same bucket, same layout. ---
|
||||||
if [[ -n "${S3_ENDPOINT:-}" && -n "${S3_BUCKET:-}" && -n "${S3_ACCESS_KEY:-}" && -n "${S3_SECRET_KEY:-}" ]]; then
|
if [[ -n "${S3_ENDPOINT:-}" && -n "${S3_BUCKET:-}" && -n "${S3_ACCESS_KEY:-}" && -n "${S3_SECRET_KEY:-}" ]]; then
|
||||||
for f in "$out" "$globals_out"; do
|
for f in "$out" "$globals_out"; do
|
||||||
|
|
@ -212,5 +237,16 @@ log "Backup done. Local dumps retained: ${#remaining[@]} data + ${#remaining_glo
|
||||||
# guard above (dump/globals integrity, retention, and — since this whole
|
# guard above (dump/globals integrity, retention, and — since this whole
|
||||||
# script runs under `set -euo pipefail` — any S3 upload) has passed. See
|
# script runs under `set -euo pipefail` — any S3 upload) has passed. See
|
||||||
# ops/check-backup-staleness.sh for the piece that actually alerts if
|
# ops/check-backup-staleness.sh for the piece that actually alerts if
|
||||||
# this stops being refreshed. ---
|
# this stops being refreshed. A LOCAL-ONLY run (BACKUP_ALLOW_LOCAL_ONLY=1
|
||||||
write_sentinel "$SENTINEL_FILE"
|
# escape hatch above) does NOT count as a verified backup for this
|
||||||
|
# purpose — writing the sentinel here would leave the staleness watchdog
|
||||||
|
# permanently green while the box has no off-box copy at all (#3085
|
||||||
|
# reopened via the escape hatch). Instead: skip the sentinel (watchdog
|
||||||
|
# alerts within max_age_hours) and notify() immediately so it isn't only
|
||||||
|
# a WARNING buried in a log nobody tails. ---
|
||||||
|
if [[ "${BACKUP_LOCAL_ONLY_USED:-0}" == "1" ]]; then
|
||||||
|
log "Skipping sentinel write — this was a LOCAL-ONLY backup (BACKUP_ALLOW_LOCAL_ONLY=1), not a verified off-box backup." >&2
|
||||||
|
notify "⚠️ gendesign main backup: LOCAL-ONLY run (S3 not configured, BACKUP_ALLOW_LOCAL_ONLY=1). Dump ${out} is NOT off-box. Sentinel NOT updated — staleness watchdog will alert if this isn't fixed."
|
||||||
|
else
|
||||||
|
write_sentinel "$SENTINEL_FILE"
|
||||||
|
fi
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,20 @@
|
||||||
# crontab ПРИНИМАЮЩЕГО хоста (Selectel Poincare, 188.246.224.93) — после 30.08.
|
# crontab ПРИНИМАЮЩЕГО хоста (Selectel Poincare, 188.246.224.93) — после 30.08.
|
||||||
#
|
#
|
||||||
# Устанавливать СРАЗУ после того, как стек поднялся и смоук прошёл:
|
# Устанавливать СРАЗУ после того, как стек поднялся и смоук прошёл:
|
||||||
|
# mkdir -p /opt/gendesign/logs
|
||||||
# crontab /opt/gendesign/ops/crontab-poincare.cron
|
# crontab /opt/gendesign/ops/crontab-poincare.cron
|
||||||
# crontab -l # сверить
|
# crontab -l # сверить
|
||||||
#
|
#
|
||||||
|
# Перед установкой в /etc/default/ должны лежать (root-owned, chmod 600,
|
||||||
|
# НЕ в git, переносятся руками с предыдущего хоста или создаются заново):
|
||||||
|
# /etc/default/gendesign-backup — S3_ENDPOINT/S3_BUCKET/S3_ACCESS_KEY/S3_SECRET_KEY
|
||||||
|
# (см. ops/gendesign-backup.default.example)
|
||||||
|
# /etc/default/tradein-backup — свои S3_*, либо отсутствует (тогда
|
||||||
|
# backup-tradein-db.sh падает на общий
|
||||||
|
# /etc/default/gendesign-backup выше)
|
||||||
|
# Без них ops/backup.sh и backup-tradein-db.sh теперь падают громко (#3085),
|
||||||
|
# а не молча пишут локальный бэкап.
|
||||||
|
#
|
||||||
# ⚠️ САМЫЙ ОПАСНЫЙ ПРОПУСК ВСЕГО ПЕРЕЕЗДА. Если этот файл не установить,
|
# ⚠️ САМЫЙ ОПАСНЫЙ ПРОПУСК ВСЕГО ПЕРЕЕЗДА. Если этот файл не установить,
|
||||||
# на новом хосте НЕ БУДЕТ НИ ОДНОГО БЭКАПА — ни tradein, ни gendesign. И узнать
|
# на новом хосте НЕ БУДЕТ НИ ОДНОГО БЭКАПА — ни tradein, ни gendesign. И узнать
|
||||||
# об этом будет неоткуда: сторож пропущенных прогонов (check-backup-staleness)
|
# об этом будет неоткуда: сторож пропущенных прогонов (check-backup-staleness)
|
||||||
|
|
@ -17,8 +28,9 @@
|
||||||
# ── Бэкапы обоих кластеров ──────────────────────────────────────────────────
|
# ── Бэкапы обоих кластеров ──────────────────────────────────────────────────
|
||||||
# Off-box выгрузка в S3 включается через /etc/default/tradein-backup и
|
# Off-box выгрузка в S3 включается через /etc/default/tradein-backup и
|
||||||
# /etc/default/gendesign-backup — файлы НЕ переезжают сами (в git их нет и не
|
# /etc/default/gendesign-backup — файлы НЕ переезжают сами (в git их нет и не
|
||||||
# должно быть), их нужно перенести руками. Без них дампы останутся локальными,
|
# должно быть), их нужно перенести руками. Без них оба скрипта падают ГРОМКО
|
||||||
# то есть на том же диске, что и БД, — ровно то, из-за чего заводился #2203.
|
# (exit 1, дамп не снимается вовсе) — см. #3085; они больше НЕ пишут молча
|
||||||
|
# локальный бэкап.
|
||||||
30 3 * * * bash /opt/gendesign/ops/backup.sh >> /opt/gendesign/logs/gendesign-backup.log 2>&1
|
30 3 * * * bash /opt/gendesign/ops/backup.sh >> /opt/gendesign/logs/gendesign-backup.log 2>&1
|
||||||
30 4 * * * bash /opt/gendesign/tradein-mvp/deploy/backup-tradein-db.sh >> /opt/gendesign/logs/tradein-backup.log 2>&1
|
30 4 * * * bash /opt/gendesign/tradein-mvp/deploy/backup-tradein-db.sh >> /opt/gendesign/logs/tradein-backup.log 2>&1
|
||||||
|
|
||||||
|
|
@ -28,6 +40,15 @@
|
||||||
0 * * * * bash /opt/gendesign/ops/check-backup-staleness.sh /opt/gendesign/backups/.last_success 26 "gendesign main backup" >> /opt/gendesign/logs/backup-staleness.log 2>&1
|
0 * * * * bash /opt/gendesign/ops/check-backup-staleness.sh /opt/gendesign/backups/.last_success 26 "gendesign main backup" >> /opt/gendesign/logs/backup-staleness.log 2>&1
|
||||||
0 * * * * bash /opt/gendesign/ops/check-backup-staleness.sh /opt/gendesign/backups/tradein/.last_success 26 "tradein backup" >> /opt/gendesign/logs/backup-staleness.log 2>&1
|
0 * * * * bash /opt/gendesign/ops/check-backup-staleness.sh /opt/gendesign/backups/tradein/.last_success 26 "tradein backup" >> /opt/gendesign/logs/backup-staleness.log 2>&1
|
||||||
|
|
||||||
|
# ── Restore-дрель, раз в месяц (#3085) ───────────────────────────────────────
|
||||||
|
# Восстановимость дампа никогда не проверялась автоматически — только
|
||||||
|
# ручными прогонами. 1-е число месяца, 02:15 — до ночных бэкапов (03:30/04:30)
|
||||||
|
# и до обогащения/геокодинга (05:00-05:45), не пересекается ни с чем.
|
||||||
|
# Берёт САМЫЙ СВЕЖИЙ на тот момент main-дамп; ops/restore-drill.sh сам найдёт
|
||||||
|
# рядом лежащий globals-файл и сам снесёт свой временный контейнер — прод не
|
||||||
|
# трогает никогда (см. заголовок скрипта).
|
||||||
|
15 2 1 * * bash -c 'f=$(ls -t /opt/gendesign/backups/gendesign_[0-9]*.sql.gz 2>/dev/null | head -1); if [ -n "$f" ]; then bash /opt/gendesign/ops/restore-drill.sh "$f"; else echo "no gendesign dump found to drill"; exit 1; fi' >> /opt/gendesign/logs/restore-drill.log 2>&1
|
||||||
|
|
||||||
# ── Обогащение и геокодирование (ходят в tradein-backend) ───────────────────
|
# ── Обогащение и геокодирование (ходят в tradein-backend) ───────────────────
|
||||||
0 5 * * * cd /opt/gendesign/tradein-mvp && docker exec tradein-backend python -m scripts.backfill_houses_dadata --limit 100 --priority both >> /opt/gendesign/logs/dadata-backfill.log 2>&1
|
0 5 * * * cd /opt/gendesign/tradein-mvp && docker exec tradein-backend python -m scripts.backfill_houses_dadata --limit 100 --priority both >> /opt/gendesign/logs/dadata-backfill.log 2>&1
|
||||||
30 5 * * * cd /opt/gendesign/tradein-mvp && docker exec tradein-backend python -m scripts.geocode_deals_from_houses --limit 50000 >> /opt/gendesign/logs/deals-geocode.log 2>&1
|
30 5 * * * cd /opt/gendesign/tradein-mvp && docker exec tradein-backend python -m scripts.geocode_deals_from_houses --limit 50000 >> /opt/gendesign/logs/deals-geocode.log 2>&1
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,11 @@
|
||||||
# Without these two set, ops/check-backup-staleness.sh still logs, just
|
# Without these two set, ops/check-backup-staleness.sh still logs, just
|
||||||
# doesn't send a Telegram alert.
|
# doesn't send a Telegram alert.
|
||||||
|
|
||||||
# --- S3 off-site upload (Selectel S3-compatible). All four required to enable. ---
|
# --- S3 off-site upload (Selectel S3-compatible). All four REQUIRED (#3085) —
|
||||||
|
# without them, backup.sh and backup-tradein-db.sh refuse to run unless
|
||||||
|
# BACKUP_ALLOW_LOCAL_ONLY=1 is also set (see below). ---
|
||||||
#S3_ENDPOINT=https://s3.ru-1.storage.selcloud.ru
|
#S3_ENDPOINT=https://s3.ru-1.storage.selcloud.ru
|
||||||
#S3_BUCKET=gendesign-backups
|
#S3_BUCKET=gendsgn-backups
|
||||||
#S3_ACCESS_KEY=REPLACE_WITH_REAL_ACCESS_KEY
|
#S3_ACCESS_KEY=REPLACE_WITH_REAL_ACCESS_KEY
|
||||||
#S3_SECRET_KEY=REPLACE_WITH_REAL_SECRET_KEY
|
#S3_SECRET_KEY=REPLACE_WITH_REAL_SECRET_KEY
|
||||||
|
|
||||||
|
|
@ -44,6 +46,9 @@
|
||||||
#TELEGRAM_CHAT_ID=123456789
|
#TELEGRAM_CHAT_ID=123456789
|
||||||
|
|
||||||
# --- optional overrides (defaults are sensible; uncomment only to change) ---
|
# --- optional overrides (defaults are sensible; uncomment only to change) ---
|
||||||
|
#BACKUP_ALLOW_LOCAL_ONLY=1 # explicit escape hatch: run without S3 creds and
|
||||||
|
# accept a local-only backup (still logs a loud
|
||||||
|
# WARNING each run). Leave unset in prod.
|
||||||
#KEEP=7 # how many recent local dumps to retain (applies to both
|
#KEEP=7 # how many recent local dumps to retain (applies to both
|
||||||
# the main dump series and the globals dump series)
|
# the main dump series and the globals dump series)
|
||||||
#MIN_DUMP_BYTES=51200 # sanity floor for the MAIN dump; a dump smaller than
|
#MIN_DUMP_BYTES=51200 # sanity floor for the MAIN dump; a dump smaller than
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ notify() {
|
||||||
-d "disable_web_page_preview=true" \
|
-d "disable_web_page_preview=true" \
|
||||||
--data-urlencode "text=${text}" \
|
--data-urlencode "text=${text}" \
|
||||||
>/dev/null 2>&1 \
|
>/dev/null 2>&1 \
|
||||||
|| { log "WARN: telegram sendMessage failed — пробую запасной канал"; \n notify_fallback_mail "$text"; }
|
|| { log "WARN: telegram sendMessage failed — пробую запасной канал"; notify_fallback_mail "$text"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- запасной канал оповещения (#3059) ----------------------------------
|
# --- запасной канал оповещения (#3059) ----------------------------------
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,17 @@
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
# notify() on failure (reviewer finding): unlike backup.sh/backup-tradein-db.sh
|
||||||
|
# this drill has no sentinel/watchdog of its own — its cron entry has no
|
||||||
|
# MAILTO, so a non-zero exit previously vanished into restore-drill.log with
|
||||||
|
# nobody looking. Reuse the same Telegram/mail channel as the backups so an
|
||||||
|
# unrestorable dump is loud, not discovered during an actual incident. Wired
|
||||||
|
# into cleanup() below (not its own trap) — bash only honours the LAST trap
|
||||||
|
# registered for a given signal, and cleanup() already owns EXIT.
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
# shellcheck source=./lib-backup.sh
|
||||||
|
source "$SCRIPT_DIR/lib-backup.sh"
|
||||||
|
|
||||||
IMAGE="${RESTORE_DRILL_IMAGE:-postgis/postgis:16-3.4}"
|
IMAGE="${RESTORE_DRILL_IMAGE:-postgis/postgis:16-3.4}"
|
||||||
READY_TIMEOUT="${RESTORE_DRILL_READY_TIMEOUT:-60}" # seconds to wait for postgres startup
|
READY_TIMEOUT="${RESTORE_DRILL_READY_TIMEOUT:-60}" # seconds to wait for postgres startup
|
||||||
DRILL_DB="drill"
|
DRILL_DB="drill"
|
||||||
|
|
@ -96,8 +107,12 @@ IFS=',' read -r -a TABLES <<< "$tables_csv"
|
||||||
# single-use, bound to 127.0.0.1, destroyed on exit. ---
|
# single-use, bound to 127.0.0.1, destroyed on exit. ---
|
||||||
CONTAINER="restore-drill-$$-$(date -u +%s)"
|
CONTAINER="restore-drill-$$-$(date -u +%s)"
|
||||||
cleanup() {
|
cleanup() {
|
||||||
|
local rc=$?
|
||||||
log "Cleaning up container ${CONTAINER}"
|
log "Cleaning up container ${CONTAINER}"
|
||||||
docker rm -f "$CONTAINER" >/dev/null 2>&1 || true
|
docker rm -f -v "$CONTAINER" >/dev/null 2>&1 || true
|
||||||
|
if [[ $rc -ne 0 ]]; then
|
||||||
|
notify "🔴 restore-drill FAILED (exit ${rc}) for ${DUMP_FILE:-<unset>} — dump may not be restorable. Check restore-drill.log on the VM." || true
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,13 @@
|
||||||
# docker exec -i tradein-postgres psql -U tradein -d tradein
|
# docker exec -i tradein-postgres psql -U tradein -d tradein
|
||||||
# Restore-дрель (безопасно, не трогает прод): ops/restore-drill.sh.
|
# Restore-дрель (безопасно, не трогает прод): ops/restore-drill.sh.
|
||||||
#
|
#
|
||||||
# Опциональная выгрузка в S3 — переменные в /etc/default/tradein-backup
|
# Выгрузка в S3 ОБЯЗАТЕЛЬНА по умолчанию (#3085) — переменные в
|
||||||
# (root-owned, chmod 600, НЕ в git); если файла нет — фолбэк на
|
# /etc/default/tradein-backup (root-owned, chmod 600, НЕ в git); если файла
|
||||||
# /etc/default/gendesign-backup (общие креды с основным бэкапом). Без
|
# нет — фолбэк на /etc/default/gendesign-backup (общие креды с основным
|
||||||
# переменных поведение прежнее: дамп остаётся только локально.
|
# бэкапом). Без всех четырёх переменных скрипт падает ДО снятия дампа —
|
||||||
|
# BACKUP_ALLOW_LOCAL_ONLY=1 явно разрешает прежнее локальное поведение.
|
||||||
# S3_ENDPOINT=https://s3.ru-1.storage.selcloud.ru
|
# S3_ENDPOINT=https://s3.ru-1.storage.selcloud.ru
|
||||||
# S3_BUCKET=gendesign-backups
|
# S3_BUCKET=gendsgn-backups
|
||||||
# S3_ACCESS_KEY=...
|
# S3_ACCESS_KEY=...
|
||||||
# S3_SECRET_KEY=...
|
# S3_SECRET_KEY=...
|
||||||
#
|
#
|
||||||
|
|
@ -51,6 +52,27 @@ elif [[ -f /etc/default/gendesign-backup ]]; then
|
||||||
source /etc/default/gendesign-backup
|
source /etc/default/gendesign-backup
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# --- guard: S3-выгрузка обязательна по умолчанию (#3085). Без неё дамп живёт
|
||||||
|
# только на том же диске, что и БД, — не бэкап, если хост потерян. До
|
||||||
|
# этой проверки отсутствие/неполнота env-файла давали в логе «дамп
|
||||||
|
# остаётся только локально» и код возврата 0, неотличимо от настоящего
|
||||||
|
# off-box бэкапа. Падаем ГРОМКО, до снятия дампа — незачем тратить время
|
||||||
|
# и место на дамп, которому всё равно некуда уехать. BACKUP_ALLOW_LOCAL_ONLY=1 —
|
||||||
|
# явная форточка (та же переменная, что у ops/backup.sh) для намеренного
|
||||||
|
# локального прогона; всё равно шумит предупреждением, чтобы это не
|
||||||
|
# забылось молча. ---
|
||||||
|
if [[ -z "${S3_ENDPOINT:-}" || -z "${S3_BUCKET:-}" || -z "${S3_ACCESS_KEY:-}" || -z "${S3_SECRET_KEY:-}" ]]; then
|
||||||
|
if [[ "${BACKUP_ALLOW_LOCAL_ONLY:-0}" == "1" ]]; then
|
||||||
|
log "ПРЕДУПРЕЖДЕНИЕ: S3-переменные заданы не полностью — BACKUP_ALLOW_LOCAL_ONLY=1, продолжаю с ЛОКАЛЬНЫМ бэкапом. Эта копия НЕ переживёт потерю этой VM." >&2
|
||||||
|
BACKUP_LOCAL_ONLY_USED=1
|
||||||
|
else
|
||||||
|
log "ОШИБКА: выгрузка в S3 не настроена — не хватает одной или нескольких из S3_ENDPOINT / S3_BUCKET / S3_ACCESS_KEY / S3_SECRET_KEY." >&2
|
||||||
|
log "ОШИБКА: заполни их в /etc/default/tradein-backup (или /etc/default/gendesign-backup) —" >&2
|
||||||
|
log "ОШИБКА: см. ops/gendesign-backup.default.example, — либо выстави BACKUP_ALLOW_LOCAL_ONLY=1, чтобы явно принять локальный бэкап." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Проверка целостности сверх «не пустой»: битый посреди записи дамп (диск
|
# Проверка целостности сверх «не пустой»: битый посреди записи дамп (диск
|
||||||
# кончился, OOM-kill, оборвался docker exec) может дать структурно валидный,
|
# кончился, OOM-kill, оборвался docker exec) может дать структурно валидный,
|
||||||
# не крошечный .gz — ни `-s`, ни MIN_DUMP_BYTES это не ловят. Две проверки,
|
# не крошечный .gz — ни `-s`, ни MIN_DUMP_BYTES это не ловят. Две проверки,
|
||||||
|
|
@ -169,4 +191,9 @@ log "backup ok: $out ($size), копий хранится: $count данных +
|
||||||
# Детект пропущенного запуска (#2203): отмечаем успех только тут, после всех
|
# Детект пропущенного запуска (#2203): отмечаем успех только тут, после всех
|
||||||
# проверок выше (и — под `set -euo pipefail` — после S3-выгрузки, если она
|
# проверок выше (и — под `set -euo pipefail` — после S3-выгрузки, если она
|
||||||
# включена). См. ops/check-backup-staleness.sh.
|
# включена). См. ops/check-backup-staleness.sh.
|
||||||
write_sentinel "$SENTINEL_FILE"
|
if [[ "${BACKUP_LOCAL_ONLY_USED:-0}" == "1" ]]; then
|
||||||
|
log "Sentinel не пишется — это ЛОКАЛЬНЫЙ прогон (BACKUP_ALLOW_LOCAL_ONLY=1), не подтверждённый off-box бэкап." >&2
|
||||||
|
notify "⚠️ tradein backup: ЛОКАЛЬНЫЙ прогон (S3 не настроен, BACKUP_ALLOW_LOCAL_ONLY=1). Дамп ${out} НЕ ушёл off-box. Sentinel не обновлён — сторож свежести подаст сигнал, если это не поправить."
|
||||||
|
else
|
||||||
|
write_sentinel "$SENTINEL_FILE"
|
||||||
|
fi
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue