From 321f6e7b6bc8f463de53b81cd167b123dfedf545 Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Sat, 22 Aug 2026 11:25:06 +0300 Subject: [PATCH] =?UTF-8?q?backups:=20=D0=B2=20=D0=BD=D0=BE=D1=82=D0=B8?= =?UTF-8?q?=D1=84=D0=B8=D0=BA=D0=B0=D1=86=D0=B8=D1=8E=20=D0=BF=D0=BE=D0=BF?= =?UTF-8?q?=D0=B0=D0=B4=D0=B0=D1=8E=D1=82=20=D0=B2=D1=81=D0=B5=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=B1=D0=B5=D0=BA=D0=B0=D0=BF=D0=BB=D0=B5=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D0=BF=D1=80=D0=B8=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - список строится по backup-targets, а не только по успешным скриптам дампа, поэтому приложения с бекапом одних данных (calibre, goatcounter, tududi, tuwunel) больше не теряются - отсутствие backup.sh при наличии backup-targets — штатный случай, теперь это info, а warning остался только когда бекапить нечего вообще --- files/backups/backup-all.py | 41 +++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/files/backups/backup-all.py b/files/backups/backup-all.py index 62791da..539c7e8 100644 --- a/files/backups/backup-all.py +++ b/files/backups/backup-all.py @@ -438,7 +438,7 @@ class BackupManager: ): self.errors: List[str] = [] self.warnings: List[str] = [] - self.successful_backups: List[str] = [] + self.backed_up_apps: List[str] = [] self.config = config self.storages = storages self.notifiers = notifiers @@ -468,17 +468,33 @@ class BackupManager: for app in applications: app_dir = str(app.path) username = app.owner - logger.info(f"Processing backup for app: {app_dir} (user {username})") + app_name = app.path.name if app.backup_script is None: - warning_msg = ( - f"No backup script found for app: {app_dir} (user {username})" - ) - logger.warning(warning_msg) - self.warnings.append(warning_msg) + if app.backup_targets: + # Приложение без дампа: restic забирает его данные как есть, + # отдельный шаг архивации ему не нужен. + logger.info( + f"No backup script for app: {app_dir} (user {username}), " + f"data directories go to restic as is" + ) + self.backed_up_apps.append(app_name) + else: + warning_msg = ( + f"Nothing to back up for app: {app_dir} (user {username}): " + f"no backup script and no backup targets" + ) + logger.warning(warning_msg) + self.warnings.append(warning_msg) continue - self._run_app_backup(str(app.backup_script), app_dir, username) + logger.info(f"Processing backup for app: {app_dir} (user {username})") + if not self._run_app_backup(str(app.backup_script), app_dir, username): + continue + # Дамп сделан, но в restic он попадёт только если есть цели бекапа; + # об их отсутствии уже предупредил ApplicationFinder. + if app.backup_targets: + self.backed_up_apps.append(app_name) else: logger.info("Backup phase not active, skipping per-app archive scripts") self.archive_duration = time.monotonic() - archive_start @@ -567,7 +583,6 @@ class BackupManager: if result.returncode == 0: logger.info(f"Backup script for {username} completed successfully") - self.successful_backups.append(username) return True else: error_msg = f"Backup script {script_path} failed with return code {result.returncode}" @@ -597,15 +612,15 @@ class BackupManager: if success and not self.errors: title = f"{host}: бекап успешно завершен" message = f"

{host}: бекап успешно завершен!

" - if self.successful_backups: - items = "".join(f"
  • {b}
  • " for b in self.successful_backups) + if self.backed_up_apps: + items = "".join(f"
  • {b}
  • " for b in self.backed_up_apps) message += f"

    Успешные бекапы:

    " else: title = f"{host}: бекап завершен с ошибками ({len(self.errors)})" message = f"

    {host}: бекап завершен с ошибками!

    " - if self.successful_backups: - items = "".join(f"
  • {b}
  • " for b in self.successful_backups) + if self.backed_up_apps: + items = "".join(f"
  • {b}
  • " for b in self.backed_up_apps) message += f"

    ✅ Успешные бекапы:

    " if self.warnings: