Repository navigation
переведён на многозадачную конфигурацию / uses a layered multi-task configuration
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конфига задачи — при необходимости сохранить прежнюю структуру, укажите старые значения.
Как тестировать:
- Скопировать
common.psd1.example→common.psd1, вписатьBotToken/ChatId. - Проверить конфиги задач в
tasks/(share01.psd1,sql01.psd1). - Прогнать вхолостую:
Invoke-MirrorBackup.ps1 -ConfigPath tasks\share01.psd1 -DryRun. - Проверить лог задачи и сообщение «ЗАПУСК» в Telegram.
- Запустить без
-DryRun, проверить итоговый статус (УСПЕХ / ВНИМАНИЕ / КРИТИЧЕСКИЙ СБОЙ) и соответствующее сообщение. - Запустить обе задачи параллельно и убедиться, что они не блокируют друг друга (разные 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: sharedcommon.psd1(Telegram, error codes, log retention) + per-task config intasks/*.psd1(Source/Destination/exclusions), merged in three layers (defaults → common → task) with required-field validation. - A single
Invoke-MirrorBackup.ps1script 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
CopyAclsoption controls the/SECflag individually (file shares — yes, database dump folders — no). - New
TreatCopiedFailuresAsWarningoption: 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
-DryRunmode (/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.gitignorefor 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.ps1plus configs undertasks/— update your Task Scheduler entries to the new-ConfigPathcommand. - Apply NTFS permissions (
icacls) to the script folder andcommon.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:
- Copy
common.psd1.example→common.psd1, fill inBotToken/ChatId. - Review the task configs under
tasks/(share01.psd1,sql01.psd1). - Do a dry run:
Invoke-MirrorBackup.ps1 -ConfigPath tasks\share01.psd1 -DryRun. - Check the task log and the "STARTED" Telegram message.
- Run without
-DryRunand verify the final status (SUCCESS / WARNING / CRITICAL) and matching message. - Run both tasks in parallel and confirm they don't block each other (separate Mutexes).