Skip to content

переведён на многозадачную конфигурацию / uses a layered multi-task configuration

Choose a tag to compare

@qtronixx qtronixx released this 15 Sep 13:50
· 17 commits to main since this release
9a5ba9a

What's Changed

см. [English version](#english)

Кратко: скрипт резервного копирования переведён на многозадачную конфигурацию (common.psd1 + tasks/*.psd1), убран хардкод секретов, исправлена логика классификации ошибок Robocopy, добавлена защита от параллельного запуска и Unicode-логирование.

Основные изменения:

  • Конфигурация вынесена в .psd1: общий common.psd1 (Telegram, коды ошибок, ретеншн логов) + конфиг задачи в tasks/*.psd1 (Source/Destination/исключения), трёхуровневое слияние (defaults → common → task) с валидацией обязательных полей.
  • Единый скрипт Invoke-MirrorBackup.ps1 обслуживает произвольное число независимых задач через параметр -ConfigPath — вместо отдельной копии скрипта под каждую шару/БД.
  • Токен Telegram и все настройки убраны из тела скрипта.
  • Unicode-лог Robocopy (/UNILOG:) — устранены проблемы с кириллицей в путях и именах файлов.
  • Защита от параллельного запуска: Mutex уникален для каждой задачи (TaskName) — разные задачи не блокируют друг друга.
  • Проверка доступности источника и свободного места на диске назначения перед стартом.
  • Ретраи (до 3 попыток) и таймаут при отправке уведомлений в Telegram, поддержка parse_mode: Markdown.
  • Новая опция задачи CopyAcls — управляет флагом /SEC индивидуально (шара — да, каталог с дампами БД — нет).
  • Новая опция TreatCopiedFailuresAsWarning — код возврата Robocopy с битом 8 («часть файлов не скопирована») теперь явно помечается статусом «ВНИМАНИЕ», а не тихо засчитывается как «УСПЕХ».
  • Автоматическая ротация (удаление) старых логов по LogRetentionDays.
  • Добавлен режим -DryRun (/L) для тестового прогона без реальных изменений.
  • Общий try/catch/finally — необработанное исключение теперь тоже уходит уведомлением в Telegram, а не теряется молча.
  • Добавлены README.md, common.psd1.example и .gitignore для безопасной публикации в git.

Миграционные заметки:

  • Отзовите любой токен, ранее захардкоженный в старых версиях скриптов, — новый токен переносится в common.psd1 (в git не коммитится, см. .gitignore).
  • Два отдельных скрипта (шара / БД) заменяются одним Invoke-MirrorBackup.ps1 + конфигами в tasks/ — обновите задания в Планировщике заданий на новую команду с -ConfigPath.
  • Примените NTFS-права (icacls) на папку со скриптом и common.psd1 — там теперь хранится токен открытым текстом.
  • Пути и префиксы логов задаются в LogDir/LogFilePrefix конфига задачи — при необходимости сохранить прежнюю структуру, укажите старые значения.

Как тестировать:

  1. Скопировать common.psd1.example → common.psd1, вписать BotToken/ChatId.
  2. Проверить конфиги задач в tasks/ (share01.psd1, sql01.psd1).
  3. Прогнать вхолостую: Invoke-MirrorBackup.ps1 -ConfigPath tasks\share01.psd1 -DryRun.
  4. Проверить лог задачи и сообщение «ЗАПУСК» в Telegram.
  5. Запустить без -DryRun, проверить итоговый статус (УСПЕХ / ВНИМАНИЕ / КРИТИЧЕСКИЙ СБОЙ) и соответствующее сообщение.
  6. Запустить обе задачи параллельно и убедиться, что они не блокируют друг друга (разные Mutex).

English

Summary: the backup script now uses a layered multi-task configuration (common.psd1 + tasks/*.psd1), hardcoded secrets were removed, Robocopy error-classification logic was fixed, and concurrent-run protection plus Unicode logging were added.

Key changes:

  • Configuration moved to .psd1: shared common.psd1 (Telegram, error codes, log retention) + per-task config in tasks/*.psd1 (Source/Destination/exclusions), merged in three layers (defaults → common → task) with required-field validation.
  • A single Invoke-MirrorBackup.ps1 script now handles any number of independent jobs via -ConfigPath, replacing separate script copies per share/database.
  • Telegram token and all settings removed from the script body.
  • Robocopy now writes a Unicode log (/UNILOG:) — fixes garbled Cyrillic file/path names.
  • Concurrent-run protection: the Mutex name is unique per task (TaskName) — different jobs no longer block each other.
  • Source availability and destination free-space checks run before Robocopy starts.
  • Telegram notifications now retry (up to 3 attempts) with a timeout, and use parse_mode: Markdown.
  • New per-task CopyAcls option controls the /SEC flag individually (file shares — yes, database dump folders — no).
  • New TreatCopiedFailuresAsWarning option: a Robocopy exit code with bit 8 set ("some files were not copied") is now explicitly flagged as WARNING instead of silently reporting SUCCESS.
  • Old logs are now automatically pruned based on LogRetentionDays.
  • Added a -DryRun mode (/L) for a no-op test pass.
  • The whole script is wrapped in try/catch/finally — unhandled exceptions now trigger a Telegram alert instead of failing silently.
  • Added README.md, common.psd1.example, and .gitignore for safe publication to git.

Migration notes:

  • Revoke any token previously hardcoded in older script versions — the new token goes into common.psd1 (not committed to git; see .gitignore).
  • The two separate scripts (share / database) are replaced by one Invoke-MirrorBackup.ps1 plus configs under tasks/ — update your Task Scheduler entries to the new -ConfigPath command.
  • Apply NTFS permissions (icacls) to the script folder and common.psd1 — it now stores the token in plain text.
  • Log paths/prefixes come from each task's LogDir/LogFilePrefix — set them to the previous values if you need to keep the old log layout.

How to test:

  1. Copy common.psd1.example → common.psd1, fill in BotToken/ChatId.
  2. Review the task configs under tasks/ (share01.psd1, sql01.psd1).
  3. Do a dry run: Invoke-MirrorBackup.ps1 -ConfigPath tasks\share01.psd1 -DryRun.
  4. Check the task log and the "STARTED" Telegram message.
  5. Run without -DryRun and verify the final status (SUCCESS / WARNING / CRITICAL) and matching message.
  6. Run both tasks in parallel and confirm they don't block each other (separate Mutexes).